/*******************************************************************************
 * 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;

	/**
	 * the block box for the layout object
	 */
	protected BlockBox _blockBox = null;

	/**
	 * The font metrics for this layout object
	 */
	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.
	 * @param cssfigure
	 */
	public CSSBlockFlowLayout(CSSFigure cssfigure) {
		super(cssfigure);
	}

	/**
	 * @return true if this layout box has more than one line
	 */
	protected boolean hasMoreThanOneLine() {
		return _previousLine != null;
	}

	/**
	 * @return true if this layout block is inline
	 */
	public boolean isInlineBlock() {
		String obj = getCSSStyle().getDisplay();
		return ICSSPropertyID.VAL_INLINE_BLOCK.equals(obj)
				|| ICSSPropertyID.VAL_INLINE_TABLE.equals(obj);
	}

	/**
	 * @return true if should expand the width to all available width. 
	 */
	public boolean shouldExpand() {
		ICSSStyle style = getCSSStyle();
		if (style == null) {
			return false;
		}
        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.setMarginInsets(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);
	}

	/**
	 * @param style
	 * @param property
	 * @return the length value
	 */
	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().getCurrentLine().getRecommendedContentWidth()
								* 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
	}

	// -------------------------------------------------------------------------------------------------------
	/**
	 * layout the lines in this layout
	 */
	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.getPaddingInsets().getHeight()
									+ BorderUtil.SCROLL_WIDTH) {
						_needVScroll = true;
					}
				}
				if (!_needHScroll && _needVScroll) {
					if (_userSpecifiedWidth > 0
							&& _blockBox.getInternalContentWidth() >= 0
							&& _userSpecifiedWidth < _blockBox
									.getInternalContentWidth()
									+ _blockBox.getPaddingInsets().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.getMarginInsets().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().getMarginInsets().bottom = getCSSStyle()
				.getMarginInsets().bottom;

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

	/**
	 * @param line
	 */
	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
	 * @param topMargin 
	 */
	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.getMarginInsets().bottom; // XXX:
				// should
				// add
				// previous
				// margin
				// bottom?
			} else {
				line._y = _previousLine._y
						+ _previousLine.getHeight()
						+ Math.max(topMargin,
								_previousLine.getMarginInsets().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.getBorderInsets());

					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);
					}
				}
			}
		}
	}
}
