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