/*******************************************************************************
 * 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.ColorConstants;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
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.provider.ICSSTextProvider;
import org.eclipse.jst.pagedesigner.css2.style.DefaultStyle;
import org.eclipse.jst.pagedesigner.css2.style.StyleUtil;
import org.eclipse.jst.pagedesigner.viewer.CaretPositionResolver;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;

/**
 * @author mengbo
 */
public class CSSTextFigure extends FlowFigure implements ICSSFigure {
	private ICSSTextProvider _provider;

	private List _fragments = new ArrayList(1);

	public CSSTextFigure(ICSSTextProvider provider) {
		_provider = provider;
		this.setLayoutManager(createDefaultFlowLayout());
	}

	public ICSSStyle getCSSStyle() {
		IFigure parentFigure = this.getParent();
		if (parentFigure instanceof ICSSFigure) {
			ICSSStyle style = ((ICSSFigure) parentFigure).getCSSStyle();
			if (style != null) {
				return style;
			}
		}
		return DefaultStyle.getInstance();
	}

	/**
	 * @see org.eclipse.draw2d.IFigure#containsPoint(int, int)
	 */
	public boolean containsPoint(int x, int y) {
		if (!super.containsPoint(x, y)) {
			return false;
		}
		List frags = getFragments();
		for (int i = 0, n = frags.size(); i < n; i++) {
			if (((FlowBox) frags.get(i)).containsPoint(x, y)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @see FlowFigure#createDefaultFlowLayout()
	 */
	protected FlowFigureLayout createDefaultFlowLayout() {
		return new CSSTextLayout(this);
	}

	/**
	 * Returns the <code>LineBox</code> fragments contained in this InlineFlow
	 * 
	 * @return The fragments
	 */
	public List getFragments() {
		return _fragments;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.ICSSFigure#getFragmentsForRead()
	 */
	public List getFragmentsForRead() {
		return getFragments();
	}

	public String getText() {
		return _provider.getTextData();
	}

	/**
	 * @see FlowFigure#postValidate()
	 */
	public void postValidate() {
		List list = getFragments();
		FlowBox box;
		int left = Integer.MAX_VALUE, top = left;
		int right = Integer.MIN_VALUE, bottom = right;
		for (int i = 0, n = list.size(); i < n; i++) {
			box = (FlowBox) list.get(i);
			left = Math.min(left, box._x);
			right = Math.max(right, box._x + box._width);
			top = Math.min(top, box._y);
			bottom = Math.max(bottom, box._y + box._height);
		}
		setBounds(new Rectangle(left, top, right - left, bottom - top));
		list = getChildren();
		for (int i = 0, n = list.size(); i < n; i++) {
			((FlowFigure) list.get(i)).postValidate();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.draw2d.Figure#paintBorder(org.eclipse.draw2d.Graphics)
	 */
	protected void paintBorder(Graphics graphics) {
		if (Debug.DEBUG_TEXTBORDER) {
			if (_fragments != null) {
				graphics.setForegroundColor(ColorConstants.darkBlue);
				for (int i = 0, size = _fragments.size(); i < size; i++) {
					FlowBox box = (FlowBox) _fragments.get(i);
					BoxUtil.drawBox(graphics, box);
				}
				graphics.restoreState();
			}
		}
	}

	/**
	 * @see org.eclipse.draw2d.Figure#paintFigure(Graphics)
	 */
	protected void paintFigure(Graphics g) {
		Object result = this.getCSSStyle().getColor();
		Color color;
		if (result instanceof Color) {
			color = (Color) result;
		} else if (result instanceof RGB) {
			color = new Color(null, (RGB) result);
		} else {
			color = null;
		}
		int[] range = null;
		if (!StyleUtil.isInWidget(this.getCSSStyle())) {
			range = _provider.getSelectedRange();
		}
		if (range == null || range[0] == range[1]) {
			// we are not in selection
			TextLayoutSupport.paintTextFigure(g, _fragments, getCSSStyle()
					.getCSSFont().getSwtFont(), color, ((Integer) getCSSStyle()
					.getStyleProperty(ICSSPropertyID.ATTR_TEXTDECORATION))
					.intValue());
		} else {
			TextLayoutSupport.paintTextFigureWithSelection(g, _fragments,
					_provider.getTextData(), getCSSStyle().getCSSFont()
							.getSwtFont(), color, ((Integer) getCSSStyle()
							.getStyleProperty(
									ICSSPropertyID.ATTR_TEXTDECORATION))
							.intValue(), range[0], range[1],
					ColorConstants.white, ColorConstants.blue);
		}
		if (color != result && color != null) {
			color.dispose();
		}
	}

	/**
	 * Find out lines which has closer y coordinate to point, and then line
	 * which has closer x coordinate.
	 * 
	 * @param relative
	 * @return
	 */
	public int getNewInsertionOffset(Point relative) {
		TextFragmentBox closestBox = null;
		// if there is one which are at the same line with relative, calculate
		// that line first;
		for (int i = 0, n = _fragments.size(); i < n; i++) {
			TextFragmentBox box = (TextFragmentBox) _fragments.get(i);
			if (box.containsPoint(relative.x, relative.y)) {
				int index = FlowUtilities.getTextInWidth(box.getTextData(),
						getCSSStyle().getCSSFont().getSwtFont(), relative.x
								- box._x, TextLayoutSupport
								.getAverageCharWidth(box));
				return box._offset + index;
			} else {
				if (closestBox == null) {
					closestBox = box;
				} else {
					// box is above point
					TextFragmentBox tempBox = box;
					int offset1 = Math
							.abs(CaretPositionResolver.getYDistance(
									new Rectangle(tempBox._x, tempBox._y,
											tempBox._width, tempBox._height),
									relative));
					tempBox = closestBox;
					int offset2 = Math
							.abs(CaretPositionResolver.getYDistance(
									new Rectangle(tempBox._x, tempBox._y,
											tempBox._width, tempBox._height),
									relative));
					if (offset1 < offset2) {
						closestBox = box;
					}
				}
				// at the same line
				if (box.containsPoint(box._x, relative.y)) {
					TextFragmentBox tempBox = box;
					int offset1 = Math
							.abs(CaretPositionResolver.getXDistance(
									new Rectangle(tempBox._x, tempBox._y,
											tempBox._width, tempBox._height),
									relative));
					tempBox = closestBox;
					int offset2 = Math
							.abs(CaretPositionResolver.getXDistance(
									new Rectangle(tempBox._x, tempBox._y,
											tempBox._width, tempBox._height),
									relative));
					if (offset1 < offset2) {
						closestBox = box;
					}
				}
			}
		}

		if (closestBox.containsPoint(closestBox._x, relative.y)
				|| closestBox.containsPoint(relative.x, closestBox._y)) {
			int offset = relative.x - closestBox._x;
			int index = FlowUtilities.getTextInWidth(closestBox.getTextData(),
					getCSSStyle().getCSSFont().getSwtFont(), offset,
					TextLayoutSupport.getAverageCharWidth(closestBox));
			return closestBox._offset + index;
		} else {
			return -1;
		}
	}

	public int getInsertionOffset(Point relative) {
		for (int i = 0, n = _fragments.size(); i < n; i++) {
			TextFragmentBox box = (TextFragmentBox) _fragments.get(i);
			if (box.containsPoint(relative.x, relative.y)) {
				int index = FlowUtilities.getTextInWidth(box.getTextData(),
						getCSSStyle().getCSSFont().getSwtFont(), relative.x
								- box._x, TextLayoutSupport
								.getAverageCharWidth(box));
				return box._offset + index;
			}
		}
		return -1;
	}

	/**
	 * the returned rectangle will be relative to this text figure.
	 * 
	 * @param offset
	 * @return
	 */
	public Rectangle calculateCaretPosition(int offset) {
		// search reverse order, find the latest box that has _offset small than
		// the specified one
		if (offset > 0) {
			for (int i = _fragments.size() - 1; i >= 0; i--) {
				TextFragmentBox box = (TextFragmentBox) _fragments.get(i);
				if (box._offset <= offset) {
					// ok, we find the box.
					if (box._offset + box._length < offset) {
						return new Rectangle(box._x + box._width, box._y, 1,
								box._height);
					} else {
						String s = box.getTextData().substring(0,
								offset - box._offset);
						int width = FlowUtilities.getTextExtents(s,
								getCSSStyle().getCSSFont().getSwtFont()).width;
						return new Rectangle(box._x + width, box._y, 1,
								box._height);
					}
				}
			}
		} else {
			if (_fragments.size() > 0) {
				TextFragmentBox box = (TextFragmentBox) _fragments.get(0);
				return new Rectangle(box._x, box._y, 1, box._height);
			}
		}
		// should only reach here when there is no fragments.
		Rectangle bounds = this.getBounds();
		return new Rectangle(bounds.x, bounds.y, 1, bounds.height);
	}

}
