/*******************************************************************************
 * 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.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;

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

	private List _fragments = new ArrayList(1);

	/**
	 * @param provider
	 */
	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;
	}

	/**
	 * @return the default flow layout
	 * 
	 */
	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();
	}

	/**
	 * @return the text
	 */
	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 {
			//Bug 191539 - [WPE] non-standard selection color in Web Page Editor
			TextLayoutSupport.paintTextFigureWithSelection(g, _fragments,
					_provider.getTextData(), getCSSStyle().getCSSFont()
							.getSwtFont(), color, ((Integer) getCSSStyle()
							.getStyleProperty(
									ICSSPropertyID.ATTR_TEXTDECORATION))
							.intValue(), range[0], range[1],
					ColorConstants.white, Display.getDefault().getSystemColor(SWT.COLOR_LIST_SELECTION));
		}
		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 return the offset
	 */
    // TODO: refactoring?
	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;
			}
            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;
		}
        return -1;
	}

	/**
	 * @param relative
	 * @return the insertion offset
	 */
	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 the caret position
	 */
	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);
					}
                    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.
		return new Rectangle(getBounds().x, getBounds().y, 1, getBounds().height);
	}

}
