/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.pagedesigner.css2.layout;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.FigureUtilities;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jst.pagedesigner.css2.ICSSStyle;
import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID;
import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyMeta;
import org.eclipse.jst.pagedesigner.css2.style.ITagEditInfo;
import org.eclipse.jst.pagedesigner.css2.value.Length;
import org.eclipse.jst.pagedesigner.css2.widget.BorderUtil;
import org.eclipse.swt.graphics.FontMetrics;

/**
 * The block layout for {@link CSSFigure}figures. Basic code structure is from
 * BlockFlowLayout.
 * 
 * @author mengbo
 */
public class CSSBlockFlowLayout extends CSSLayout implements ICSSPainter2 {
	private LineBox _previousLine = null;

	protected BlockBox _blockBox = null;

	protected FontMetrics _fontMetrices;

	int _userSpecifiedWidth;

	int _userSpecifiedHeight;

	/*
	 * whether we need HScroll and VScroll when overflow is set to "scroll".
	 * will be updated in "endBlock" and used in "paintFigurePostClientArea"
	 */
	boolean _needHScroll = false;

	boolean _needVScroll = false;

	/**
	 * Creates a new CSSBlockFlowLayout with the given BlockFlow.
	 */
	public CSSBlockFlowLayout(CSSFigure cssfigure) {
		super(cssfigure);
	}

	protected boolean hasMoreThanOneLine() {
		return _previousLine != null;
	}

	public boolean isInlineBlock() {
		String obj = getCSSStyle().getDisplay();
		return ICSSPropertyID.VAL_INLINE_BLOCK.equals(obj)
				|| ICSSPropertyID.VAL_INLINE_TABLE.equals(obj);
	}

	/**
	 * whether should expand the width to all available width.
	 * 
	 * @return
	 */
	public boolean shouldExpand() {
		ICSSStyle style = getCSSStyle();
		if (style == null) {
			return false;
		} else {
			return "block".equalsIgnoreCase(style.getDisplay())
					|| "list-item".equalsIgnoreCase(style.getDisplay());
		}
	}

	// ---------------------------------------------------------------------------------------------------
	// preLayout stage. Major job is get the top-left corner information of the
	// new block.

	/**
	 * sets up the single block that contains all of the lines.
	 */
	protected void setupBlock() {
		// int recommended = line.getAvailableWidth();
		// if (recommended != previousRecommendedWidth)
		// Remove all current Fragments
		_blockBox.clear();
		// Ask for a new line, in case we are in the middle of a line

		if (!isInlineBlock()) {
			LineBox lineBox = getFlowContext().getCurrentLine();
			if (lineBox != null && !lineBox.isEmptyStringLine()) {
				getFlowContext().endLine();
			}
		}

		ICSSStyle style = getCSSStyle();

		// endLine will result in context create a new line, so we are in the
		// new line now.
		// passing in the top margin, and context will consider that when create
		// the new line.
		int marginTop = style.getMarginInsets().top;
		LineBox line = getFlowContext().getCurrentLine(marginTop);

		// Setup the one fragment for this Block with the correct X and
		// available width

		// FIXME: according to spec, when using percentage width/height, should
		// percentage to
		// the "containing block". But we don't have very good "containing
		// block" resolution
		// implementation yet.

		// calculate the min size
		// int minWidth = 0;
		// int minHeight = 0;
		// if (style != null)
		// {
		// // try to see whether there is any designer specified min size
		// ITagEditInfo info = (ITagEditInfo)
		// style.getAdapter(ITagEditInfo.class);
		// if (info != null)
		// {
		// minWidth = info.getMinWidth();
		// minHeight = info.getMinHeight();
		// }
		//
		// // CSS also has the min-width/min-height property. We should also get
		// that,
		// // and using the max of the "min-width" css property and the designer
		// specified min size.
		// int height = getLengthValue(style,ICSSPropertyID.ATTR_MIN_HEIGHT);
		// if(height > minHeight)
		// {
		// minHeight = height;
		// }
		// int width = getLengthValue(style,ICSSPropertyID.ATTR_MIN_WIDTH);
		// if(width > minWidth)
		// {
		// minWidth = width;
		// }
		// }

		// keep track of user specified size, this will be used when handling
		// the "overflow" CSS property.
		_userSpecifiedWidth = 0;
		_userSpecifiedHeight = 0;

		{
			int width = getLengthValue(style, ICSSPropertyID.ATTR_WIDTH);

			int availableWidth = line.getAvailableWidth()
					- style.getMarginInsets().getWidth();
			if (width <= 0) {
				// no width setting
				if (isCalculatingMaxWidth()) {
					_blockBox.setRecommendedWidth(Integer.MAX_VALUE);
					// _blockBox.setWidth( (minWidth>0?minWidth:0));
				} else {
					_blockBox.setRecommendedWidth(availableWidth);
					if (shouldExpand()) {
						_blockBox.setWidth(availableWidth);
					} else {
						// _blockBox.setWidth( (minWidth>0?minWidth:0));
					}
				}
			} else {
				int w = width;
				if (!style.isSizeIncludeBorderPadding()) {
					w += style.getBorderInsets().getWidth()
							+ style.getPaddingInsets().getWidth();
				}
				// XXX: should we use minWidth or follow user's choice?
				// if (w < minWidth)
				// {
				// w = minWidth;
				// }
				_userSpecifiedWidth = w;
				_blockBox.setWidth(w);
				_blockBox.setRecommendedWidth(w);
			}
		}

		{
			int height = getLengthValue(style, ICSSPropertyID.ATTR_HEIGHT);
			// Object height =
			// style.getStyleProperty(ICSSPropertyID.ATTR_HEIGHT);
			// Length heightLength = (height instanceof Length) ? (Length)
			// height : null;

			if (height <= 0) {
				// if (minHeight > 0)
				// {
				// // _blockBox.setHeight(minHeight);
				// _blockBox.setRecommendedHeight(minHeight);
				// }
				// else
				{
					_blockBox.setHeight(0);
					_blockBox.setRecommendedHeight(0);
				}
			} else {
				int h = height;
				if (handlingBorderForBlock()
						&& !style.isSizeIncludeBorderPadding()) {
					h += style.getBorderInsets().getHeight()
							+ style.getPaddingInsets().getHeight();
				}
				// XXX: should we follow minHeight or user's choice?
				// if (minHeight > h)
				// {
				// h = minHeight;
				// }
				_userSpecifiedHeight = h;
				_blockBox.setHeight(h);
				_blockBox.setRecommendedHeight(h);
			}
		}
		_blockBox._marginInsets = new Insets(style.getMarginInsets());
		if (handlingBorderForBlock()) {
			BoxUtil.setupBorderPaddingMargin(_blockBox, getCSSStyle());
		}

		// as in designer, we don't want to the element to have zero size, so
		// set a minimun size here.
		// _blockBox.setWidth(Math.max(20, _blockBox.getWidth()));
		// int minHeight = getCSSStyle().getCSSFont().getFontSize() +
		// _blockBox.getBorderPaddingHeight();
		// _blockBox.setHeight(Math.max(minHeight, _blockBox.getHeight()));

		_blockBox._y = line._y;
		_blockBox._x = line._x;

		setBlockVerticalAlign(_blockBox);
	}

	protected int getLengthValue(ICSSStyle style, String property) {
		int lengthValue = 0;
		if (style != null) {
			Object object = style.getStyleProperty(property);
			Length lengthObj = (object instanceof Length) ? (Length) object
					: null;

			if (lengthObj != null) {
				lengthValue = lengthObj.getValue();
				if (lengthObj.isPercentage()) {
					if (ICSSPropertyID.ATTR_WIDTH.equalsIgnoreCase(property)
							|| ICSSPropertyID.ATTR_MIN_WIDTH
									.equalsIgnoreCase(property)) {
						lengthValue = this.getFlowContext().getContainerWidth()
								* lengthValue / 100;
					} else if (ICSSPropertyID.ATTR_HEIGHT
							.equalsIgnoreCase(property)
							|| ICSSPropertyID.ATTR_MIN_HEIGHT
									.equalsIgnoreCase(property)) {
						// XXX: we should omit it because we don't support
						// percentage height now.
						lengthValue = 0;
					}
				}
			}
		}
		return lengthValue;
	}

	private void setBlockVerticalAlign(BlockBox box) {
		ICSSStyle style = getCSSStyle();
		if (style != null) {
			box.setVerticalAlignData(style
					.getStyleProperty(ICSSPropertyID.ATTR_VERTICAL_ALIGN));
		}
	}

	/**
	 * @see FlowContainerLayout#preLayout()
	 */
	protected void preLayout() {
		super.preLayout();
		_blockBox = new BlockBox();
		setupBlock();
		// Probably could setup current and previous line here, or just previous
	}

	// -------------------------------------------------------------------------------------------------------
	protected void layoutLines() {
		List lines = _blockBox.getFragments();
		if (lines != null) {
			for (int i = 0; i < lines.size(); i++) {
				if (lines.get(i) instanceof LineBox) {
					layoutLine((LineBox) lines.get(i));
				}
			}
		}
	}

	/**
	 * Called by flush(), adds the BlockBox associated with this BlockFlowLayout
	 * to the current line and then ends the line.
	 */
	protected void endBlock() {
		layoutLines();
		ICSSStyle style = getCSSStyle();
		if (style != null) {
			int minWidth = 0;
			int minHeight = 0;
			// try to see whether there is any designer specified min size
			ITagEditInfo info = (ITagEditInfo) style
					.getAdapter(ITagEditInfo.class);
			if (info != null) {
				minWidth = info.getMinWidth();
				minHeight = info.getMinHeight();
			}

			// CSS also has the min-width/min-height property. We should also
			// get that,
			// and using the max of the "min-width" css property and the
			// designer specified min size.
			int height = getLengthValue(style, ICSSPropertyID.ATTR_MIN_HEIGHT);
			if (height > minHeight) {
				minHeight = height;
			}
			int width = getLengthValue(style, ICSSPropertyID.ATTR_MIN_WIDTH);
			if (width > minWidth) {
				minWidth = width;
			}
			if (minHeight > _blockBox.getHeight()) {
				_blockBox.setHeight(minHeight);
			}
			if (minWidth > _blockBox.getWidth()) {
				_blockBox.setWidth(minWidth);
			}
		}

		// reset scroll information.
		this._needHScroll = this._needVScroll = false;

		// ok, now we need to adjust the _blockBox's size according to the
		// "overflow" setting.
		// depends on different "overflow" style of this block, different sizing
		// policy may apply.
		// ICSSStyle style = this.getCSSStyle();
		if (style != null) {
			Object overflow = style
					.getStyleProperty(ICSSPropertyID.ATTR_OVERFLOW);
			if (ICSSPropertyID.VAL_HIDDEN.equals(overflow)) {
				if (_userSpecifiedWidth > 0) {
					_blockBox.setWidth(_userSpecifiedWidth);
				}
				if (_userSpecifiedHeight > 0) {
					_blockBox.setHeight(_userSpecifiedHeight);
				}
			} else if (ICSSPropertyID.VAL_SCROLL.equals(overflow)
					|| ICSSPropertyID.VAL_AUTO.equals(overflow)) {
				// adjust _needHScroll and _needVScroll
				if (_userSpecifiedWidth > 0
						&& _userSpecifiedWidth < _blockBox.getWidth()) {
					_needHScroll = true;
				}
				if (_userSpecifiedHeight > 0
						&& _userSpecifiedHeight < _blockBox.getHeight()) {
					_needVScroll = true;
				}
				if (_needHScroll && !_needVScroll) {
					if (_userSpecifiedHeight > 0
							&& _blockBox.getInternalContentHeight() >= 0
							&& _userSpecifiedHeight < _blockBox
									.getInternalContentHeight()
									+ _blockBox._paddingInsets.getHeight()
									+ BorderUtil.SCROLL_WIDTH) {
						_needVScroll = true;
					}
				}
				if (!_needHScroll && _needVScroll) {
					if (_userSpecifiedWidth > 0
							&& _blockBox.getInternalContentWidth() >= 0
							&& _userSpecifiedWidth < _blockBox
									.getInternalContentWidth()
									+ _blockBox._paddingInsets.getWidth()
									+ BorderUtil.SCROLL_WIDTH) {
						_needHScroll = true;
					}
				}

				if (_userSpecifiedWidth > 0) {
					_blockBox.setWidth(_userSpecifiedWidth);
				}
				if (_userSpecifiedHeight > 0) {
					_blockBox.setHeight(_userSpecifiedHeight);
				}
			}
		}

		if (getFlowContext().isCurrentLineOccupied()
				&& getFlowContext().getCurrentLine().getAvailableWidth() < _blockBox._width
						+ _blockBox._marginInsets.getWidth()) {
			getFlowContext().endLine();
		}
		if (!isInlineBlock()) {
			LineBox line = getFlowContext().getCurrentLine();
			line.setHorizonalData(getCSSStyle().getStyleProperty(
					ICSSPropertyID.ATTR_HORIZONTAL_ALIGN));
			line.setHtmlInitData(getCSSStyle().getHTMLelementInitValue(
					ICSSPropertyID.ATTR_HORIZONTAL_ALIGN));
			line.add(_blockBox);
			// getFlowContext().addToCurrentLine(_blockBox);
		} else {
			getFlowContext().addToCurrentLine(_blockBox);
		}
		getFlowContext().getCurrentLine()._marginInsets.bottom = getCSSStyle()
				.getMarginInsets().bottom;

		if (!isInlineBlock()) {
			getFlowContext().endLine();
		}
	}

	protected void layoutLine(LineBox line) {
		// currentLine.x = 0; //XXX: comment out, don't understand why set to 0,
		// because it has already
		// been set when setupLine(). And if do need, should
		// set to getBorderPaddingInsets().left
		// if (!isInlineBlock() && shouldExpand())
		// {
		// FIXME: currently we are using getRecommendedContentWidth,
		// what happen if after adding the new line, the new width is bigger
		// than
		// recommendedContentWidth? should we use getWidth() instead of
		// recommendedcontentWidth?
		Object textalign = line.getHorizonalData();
		if (textalign == null
				|| ICSSPropertyMeta.NOT_SPECIFIED.equals(textalign)) {
			textalign = (getCSSStyle()
					.getStyleProperty(ICSSPropertyID.ATTR_TEXTALIGN));
		}
		if (textalign == null
				|| ICSSPropertyMeta.NOT_SPECIFIED.equals(textalign)) {
			textalign = line.getHtmlInitData();
		}
		if (ICSSPropertyID.VAL_RIGHT.equals(textalign)) {
			line._x = _blockBox.getContentWidth() - line.getWidth();
		} else if (ICSSPropertyID.VAL_CENTER.equals(textalign)) {
			line._x = (_blockBox.getContentWidth() - line.getWidth()) / 2;
		}

		if (line._x < 0) {
			line._x = 0;
		}
		line.commit();
	}

	/**
	 * Adjust all fragments in the current line to have the same baseline. Do
	 * any additional adjustments, such as horizontal alignment.
	 */
	protected void addCurrentLine() {
		// The follow code is commented out, and moved into layoutLine(line)
		// called by endBlock().
		// since only when endBlock is called we really know how big is this
		// block box, and then can
		// do horizontal alignment.
		// // currentLine.x = 0; //XXX: comment out, don't understand why set to
		// 0, because it has already
		// // been set when setupLine(). And if do need, should
		// // set to getBorderPaddingInsets().left
		// if (!isInlineBlock() && shouldExpand())
		// {
		// // FIXME: currently we are using getRecommendedContentWidth,
		// // what happen if after adding the new line, the new width is bigger
		// than
		// // recommendedContentWidth? should we use getWidth() instead of
		// // recommendedcontentWidth?
		//
		// Object textalign =
		// (getCSSStyle().getStyleProperty(ICSSPropertyID.ATTR_TEXTALIGN));
		// if (textalign == ICSSPropertyID.VAL_RIGHT)
		// {
		// _currentLine._x = _blockBox.getContentWidth() +
		// _blockBox.getBorderPaddingInsets().left - _currentLine.getWidth();
		// }
		// else if (textalign == ICSSPropertyID.VAL_CENTER)
		// {
		//
		// _currentLine._x = _blockBox.getBorderPaddingInsets().left +
		// (_blockBox.getContentWidth() - _currentLine.getWidth()) / 2;
		// }
		// if (_currentLine._x < 0)
		// _currentLine._x = 0;
		// }
		//
		// // FIXME: should check vertical alignment here?
		// _currentLine.commit();

		// layoutLine(_currentLine);
		_blockBox.add(_currentLine);
	}

	/**
	 * @see FlowContainerLayout#flush()
	 */
	protected void flush() {
		if (_currentLine != null && _currentLine.isOccupied()) {
			addCurrentLine();
		}
		endBlock();
	}

	/**
	 * @see FlowContainerLayout#cleanup()
	 */
	protected void cleanup() {
		_currentLine = _previousLine = null;
		_fontMetrices = null;
	}

	// ----------------------------------------------------------------------------------

	/**
	 * Override to setup the line's x, remaining, and available width.
	 * 
	 * @param line
	 *            the LineBox to set up
	 */
	protected void setupLine(LineBox line, int topMargin) {
		line.clear();

		// the caller of getCurrentLine() may add leftMargin and leftPadding and
		// leftBorder to line.x
		line._x = 0;

		// FIXME: here should check the floating boxes, and minus the width of
		// them from
		// current line.
		line.setRecommendedWidth(_blockBox.getRecommendedContentWidth());
		if (_previousLine == null) {
			line._y = 0;
			if (topMargin != Integer.MIN_VALUE) {
				line._y += topMargin;
			}
		} else {
			if (topMargin == Integer.MIN_VALUE) {
				line._y = _previousLine._y + _previousLine.getHeight()
						+ getLinePadding() + _previousLine._marginInsets.bottom; // XXX:
				// should
				// add
				// previous
				// margin
				// bottom?
			} else {
				line._y = _previousLine._y
						+ _previousLine.getHeight()
						+ Math.max(topMargin,
								_previousLine._marginInsets.bottom);
			}
		}
		setFontinfoForLine(line);
		// line.validate();
	}

	private void setFontinfoForLine(LineBox line) {

		ICSSStyle style = getCSSStyle();
		if (style != null) {
			if (_fontMetrices == null) {
				// as getSwtFont is resource consuming, so we cache the
				// _fontMetrics.
				_fontMetrices = FigureUtilities.getFontMetrics(style
						.getCSSFont().getSwtFont());
			}
			line.setFontMetrics(_fontMetrices);
		}
	}

	/**
	 * @see FlowContainerLayout#createNewLine()
	 */
	protected void createNewLine() {
		_currentLine = new LineBox();
		setupLine(_currentLine, Integer.MIN_VALUE);
	}

	protected void createNewLine(int topmargin) {
		_currentLine = new LineBox();
		setupLine(_currentLine, topmargin);
	}

	/**
	 * @see FlowContext#endLine()
	 */
	public void endLine() {
		// this is called from child layouts.
		// If there is no current line, state is equivalent to new line
		if (_currentLine == null) {
			return;
		}
		if (_currentLine.isOccupied()) {
			addCurrentLine(); // finalize the current line layout
		} else {
			_currentLine = null;
			return;
		}

		LineBox box = _currentLine;
		// _currentLine = _previousLine; //XXX: ???? why (yang)
		_previousLine = box;

		_currentLine = null;
		// setupLine(getCurrentLine());
	}

	/**
	 * @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getCurrentY()
	 */
	public int getCurrentY() {
		return getCurrentLine()._y; // FIXME: margin of previous block?
	}

	int getLinePadding() {
		return 0;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.CSSLayout#useLocalCoordinates()
	 */
	public boolean useLocalCoordinates() {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.FlowFigureLayout#dispose()
	 */
	public void dispose() {
		// 
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.ICSSLayout#getFragmentsForRead()
	 */
	public List getFragmentsForRead() {
		List r = new ArrayList(1);
		r.add(_blockBox);
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.ICSSLayout#postValidate()
	 */
	public void postValidate() {

		Rectangle r = new Rectangle(_blockBox._x, _blockBox._y, _blockBox
				.getWidth(), _blockBox.getHeight());
		getCSSFigure().setBounds(r);
		List list = getCSSFigure().getChildren();
		for (int i = 0; i < list.size(); i++) {
			((FlowFigure) list.get(i)).postValidate();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.FlowContext#getContainerWidth()
	 */
	public int getContainerWidth() {
		int width = Math.max(0, Math.max(_blockBox.getWidth(), _blockBox
				.getRecommendedWidth()));
		return width;
	}

	/**
	 * when the "overflow" is "scroll", we need to paint the scrollbar
	 */
	public void paintFigurePostClientArea(Graphics g) {
		ICSSStyle style = this.getCSSStyle();
		if (style != null) {
			Object overflow = style
					.getStyleProperty(ICSSPropertyID.ATTR_OVERFLOW);
			if (ICSSPropertyID.VAL_SCROLL.equals(overflow)
					|| ICSSPropertyID.VAL_AUTO.equals(overflow)) {
				if (this._needHScroll || this._needVScroll) {
					// as this is using localCoordinate, so translate to
					// relative to left/up corder of whole
					// blockbox.
					g.translate(-_blockBox.getBorderPaddingInsets().left,
							-_blockBox.getBorderPaddingInsets().top);

					Rectangle rect = new Rectangle(0, 0, _blockBox.getWidth(),
							_blockBox.getHeight());
					rect.crop(_blockBox._borderInsets);

					if (this._needHScroll && this._needVScroll) {
						BorderUtil.drawScrollBar(g, BorderUtil.SCROLL_WIDTH,
								rect, BorderUtil.BOTH);
					} else if (this._needHScroll) {
						BorderUtil.drawScrollBar(g, BorderUtil.SCROLL_WIDTH,
								rect, BorderUtil.HORIZONTAL_BAR);
					} else if (this._needVScroll) {
						BorderUtil.drawScrollBar(g, BorderUtil.SCROLL_WIDTH,
								rect, BorderUtil.VERTICAL_BAR);
					}
				}
			}
		}
	}
}
