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

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

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.jface.text.Assert;
import org.eclipse.jst.pagedesigner.IHTMLConstants;
import org.eclipse.jst.pagedesigner.css2.layout.CSSFigure;
import org.eclipse.jst.pagedesigner.css2.layout.CSSTextFigure;
import org.eclipse.jst.pagedesigner.css2.layout.FlowBox;
import org.eclipse.jst.pagedesigner.css2.layout.FlowUtilities;
import org.eclipse.jst.pagedesigner.css2.layout.TextFragmentBox;
import org.eclipse.jst.pagedesigner.css2.layout.TextLayoutSupport;
import org.eclipse.jst.pagedesigner.dom.DOMRefPosition;
import org.eclipse.jst.pagedesigner.dom.EditModelQuery;
import org.eclipse.jst.pagedesigner.parts.SubNodeEditPart;
import org.eclipse.jst.pagedesigner.parts.TextEditPart;
import org.eclipse.jst.pagedesigner.validation.caret.IPositionMediator;
import org.eclipse.jst.pagedesigner.validation.caret.Target;
import org.w3c.dom.Node;

/**
 * @author mengbo
 */
public class LayoutPart {
	private final static int MAX_OFFSET_TO_EDGE = 10;

	private EditPart _part;

	private FlowBox _box;

	private final Point EMPTY_POINT = new Point(0, 0);

	private Point _point = EMPTY_POINT;

	/**
	 * If caller didn't resolve FlowBox, call this.
	 * 
	 * @param part
	 * @param point
	 */
	public LayoutPart(EditPart part, Point point) {
		Assert.isTrue(part != null);
		_part = part;
		_point = point;
	}

	/**
	 * @return Returns the _box, when it is null, generate box with part and
	 *         point.
	 */
	public FlowBox getBox() {
		if (_box == null) {
			_box = getClosestBox();
		}
		return _box;
	}

	/**
	 * @return Returns the _part.
	 */
	public EditPart getPart() {
		return _part;
	}

	/**
	 * Get closest box's bounds.
	 * 
	 * @param point
	 * @return
	 */
	private Rectangle getClosestBoxAbsoluteBounds() {
		Rectangle rect = null;
		if (getBox() != null) {
			rect = getAbsoluteBounds(getBox());
		}
		return rect;
	}

	/**
	 * Try to get the closest flowbox absolute bounds.
	 * 
	 * @param point
	 * @return
	 */
	public Rectangle getAbsoluteBounds() {
		Rectangle bounds = null;
		if ((bounds = getClosestBoxAbsoluteBounds()) == null) {
			// This should never happens.
			bounds = EditPartPositionHelper.getAbsoluteBounds(_part);
		}
		return bounds;
	}

	/**
	 * Get box's absolute bounds.
	 * 
	 * @param point
	 * @return
	 */
	public Rectangle getAbsoluteBounds(FlowBox box) {
		if (box != null) {
			IFigure figure = ((GraphicalEditPart) _part).getFigure();
			Rectangle rect = new Rectangle(box._x, box._y, box.getWidth(), box
					.getHeight());
			figure.translateToAbsolute(rect);
			return rect;
		}
		return null;
	}

	/**
	 * Closest box is the part's FlowBox which y coordinate is closest to point,
	 * and then its x coordinate is more close to point than other boxs of the
	 * same line.
	 * 
	 * @param part
	 * @param point
	 * @return
	 */
	private FlowBox getClosestBox() {
		FlowBox closestBox = null;
		List fragments = getLines(_part);

		// if there is one which are at the same line with relative,
		// calculate that line first;
		for (int i = 0; i < fragments.size(); i++) {
			FlowBox box = (FlowBox) fragments.get(i);
			Rectangle boxRect = getAbsoluteBounds(box);
			if (boxRect.contains(_point.x, _point.y)) {
				closestBox = box;
				break;
			} else {
				if (closestBox == null) {
					closestBox = box;
				} else {
					// compare y.
					int offset1 = Math.abs(CaretPositionResolver.getYDistance(
							boxRect, _point));
					Rectangle closestRect = getAbsoluteBounds(closestBox);
					int offset2 = Math.abs(CaretPositionResolver.getYDistance(
							closestRect, _point));
					if (offset1 < offset2) {
						closestBox = box;
					}
				}
				// at the same line
				if (closestBox != box && boxRect.contains(boxRect.x, _point.y)) {
					// compare x.
					int offset1 = Math.abs(CaretPositionResolver.getXDistance(
							boxRect, _point));
					Rectangle closestRect = getAbsoluteBounds(closestBox);
					int offset2 = Math.abs(CaretPositionResolver.getXDistance(
							closestRect, _point));
					if (offset1 < offset2) {
						closestBox = box;
					}
				}
			}
		}
		return closestBox;
	}

	/**
	 * The point is whitin the bounds of the figure.
	 * 
	 * @param point
	 * @return
	 */
	public boolean contains(Point point) {
		return getAbsoluteBounds().contains(point);
	}

	public DesignPosition resolveTextPosition() {
		DesignPosition result = null;
		if (_part instanceof TextEditPart
				&& !EditModelQuery.isTransparentText(Target.resolveNode(_part))) {
			FlowBox flowBox = getBox();
			if (flowBox instanceof TextFragmentBox) {
				TextFragmentBox box = (TextFragmentBox) flowBox;
				if (((TextEditPart) _part).getFigure() instanceof CSSTextFigure) {
					CSSTextFigure figure = (CSSTextFigure) ((TextEditPart) _part)
							.getFigure();
					Rectangle boxRect = getAbsoluteBounds(box);
					int index = FlowUtilities.getTextInWidth(box.getTextData(),
							figure.getCSSStyle().getCSSFont().getSwtFont(),
							_point.x - boxRect.x, TextLayoutSupport
									.getAverageCharWidth(box));
					result = new DesignPosition(_part, box._offset + index);
				}
			}
		}
		return result;
	}

	public DesignPosition resolvePosition(IPositionMediator validator) {
		DesignPosition result;
		if ((result = resolveTextPosition()) == null) {
			boolean atPointLeft = false;
			boolean atPointRight = false;
			atPointLeft = isBeforePoint(_point);
			atPointRight = isAfterPoint(_point);
			if (!(atPointLeft ^ atPointRight)) {

			}
			Target target = new Target(getPart());
			if (validator.isValidPosition(new DOMRefPosition(target.getNode(),
					atPointLeft))) {
				result = new DesignRefPosition(_part, atPointLeft);
			} else if (validator.isValidPosition(new DOMRefPosition(target
					.getNode(), !atPointLeft))) {
				result = new DesignRefPosition(_part, !atPointLeft);
			} else if (validator.isEditable(target)) {
				if (atPointLeft) {
					result = new DesignPosition(_part, 0);
				} else {
					result = new DesignPosition(_part, _part.getChildren()
							.size());
				}
			}
		}
		return result;
	}

	private IFigure getFigure() {
		return ((GraphicalEditPart) _part).getFigure();
	}

	public boolean isAfterPoint(Point point) {
		boolean result = false;
		FlowBox flowBox = getLine(0);
		if (IHTMLConstants.TAG_BR.equalsIgnoreCase(Target.resolveNode(_part)
				.getNodeName())) {
			if (flowBox != null) {
				Rectangle boxRect = getAbsoluteBounds(flowBox);
				result = CaretPositionResolver.getYDistance(boxRect, point) == 0;
			}
		} else {

			if (flowBox != null) {
				Rectangle boxRect = getAbsoluteBounds(flowBox);
				if (CaretPositionResolver.getXDistance(boxRect, point) != 0) {
					result = CaretPositionResolver.getXDistance(boxRect, point) < 0
							&& // 
							CaretPositionResolver.getYDistance(boxRect, point) == 0;
				}
			}
		}
		result |= isUnderCaret();
		// if (isWidget() && flowBox != null)
		// {
		// result |= contains(point) &&
		// CaretPositionResolver.toXMiddle(getAbsoluteBounds(flowBox), point) <
		// 0;
		// }
		return result;

	}

	/**
	 * EditPart is at point's left
	 * 
	 * @param part
	 * @param point
	 * @return
	 */
	public boolean isBeforePoint(Point point) {
		boolean result = false;
		FlowBox flowBox = getLastLine();
		if (flowBox != null) {
			Rectangle boxRect = getAbsoluteBounds(flowBox);
			if (IHTMLConstants.TAG_BR.equalsIgnoreCase(Target
					.resolveNode(_part).getNodeName())) {
				return CaretPositionResolver.getYDistance(boxRect, point) == 0;
			} else if (CaretPositionResolver.getXDistance(boxRect, point) != 0) {
				result = CaretPositionResolver.getXDistance(boxRect, point) > 0
						&& // 
						CaretPositionResolver.getYDistance(boxRect, point) == 0;
			}
		}
		result |= isAboveCaret();
		// if (isWidget() && flowBox != null)
		// {
		// result |= contains(point) &&
		// CaretPositionResolver.toXMiddle(getAbsoluteBounds(flowBox), point) >
		// 0;
		// }
		return result;
		// return !isAfterPoint(point);
	}

	public boolean isBeforePoint() {
		return isBeforePoint(_point);
	}

	public boolean atLeftPart(Point point) {
		FlowBox flowBox = getBox();
		if (flowBox != null) {
			Rectangle boxRect = getAbsoluteBounds(flowBox);
			return CaretPositionResolver.toXMiddle(boxRect, point) < 0;
		}
		return true;
	}

	public boolean isAfterPoint() {
		return isAfterPoint(_point);
	}

	public boolean atSameLine(Point point) {
		Rectangle bounds = getAbsoluteBounds();
		return bounds.contains(bounds.getTop().x, point.y);
	}

	public boolean atSameRow(Point point) {
		Rectangle bounds = getAbsoluteBounds();
		return bounds.contains(point.x, bounds.getRight().y);
	}

	public static Rectangle getBounds(FlowBox box) {
		return new Rectangle(box._x, box._y, box.getWidth(), box.getHeight());
	}

	/**
	 * @return Returns the _point.
	 */
	public Point getPoint() {
		return _point;
	}

	FlowBox getLine(int index) {
		FlowBox result = null;
		List lines = getLines(_part);
		if (lines.size() > 0 && index >= 0 && index <= lines.size() - 1) {
			result = (FlowBox) lines.get(index);
		}
		return result;
	}

	FlowBox getLastLine() {
		FlowBox result = null;
		List lines = getLines(_part);
		if (lines.size() > 0) {
			result = (FlowBox) lines.get(lines.size() - 1);
		}
		return result;
	}

	/**
	 * @param _part
	 * @return
	 */
	List getLines(EditPart _part) {
		List fragments = new ArrayList();
		if (_part instanceof SubNodeEditPart) {
			IFigure figure = ((GraphicalEditPart) _part).getFigure();

			if (figure instanceof CSSTextFigure) {
				fragments = ((CSSTextFigure) figure).getFragments();
				((CSSTextFigure) figure).getCSSStyle();
			} else if (figure instanceof CSSFigure) {
				fragments = ((CSSFigure) figure).getFragmentsForRead();
				((CSSFigure) figure).getCSSStyle();
			}
		}
		return fragments;
	}

	/**
	 * To search for none empty string, this is not final.
	 * 
	 * @param lineBox
	 * @param host
	 * @param rect
	 * @param validator
	 */
	public static EditPart getConcretePart(EditPart part) {
		if (part != null) {
			Node node = Target.resolveNode(part);
			Node child = node.getFirstChild();
			EditPart result;
			while (child != null) {
				if (!EditModelQuery.isTransparentText(child)
						&& (result = Target.resolvePart(child)) != null) {
					return result;
				}
				child = child.getNextSibling();
			}
		}
		return null;
	}

	/**
	 * To search for none empty string, this is not final.
	 * 
	 * @param lineBox
	 * @param host
	 * @param rect
	 * @param validator
	 */
	public EditPart getConcretePart() {
		return getConcretePart(_part);
	}

	public static Node getConcreteNode(Node node) {
		if (node != null) {
			Node child = node.getFirstChild();
			while (child != null) {
				if (!EditModelQuery.isTransparentText(child)) {
					return node;
				}
				child = child.getNextSibling();
			}
		}
		return null;
	}

	public boolean isCloseToEdgeFromOutSide() {
		boolean result = false;
		if (EditModelQuery.isBlockNode(Target.resolveNode(_part))) {
			result = Math.abs(getAbsoluteBounds().getLeft().x - _point.x) <= MAX_OFFSET_TO_EDGE;
			if (!result) {
				result = Math.abs(getAbsoluteBounds().getRight().x - _point.x) <= MAX_OFFSET_TO_EDGE;
			}
		}
		return result;
	}

	private boolean isAboveCaret() {
		return getAbsoluteBounds().getBottom().y <= _point.y;
	}

	private boolean isUnderCaret() {
		return getAbsoluteBounds().getTop().y >= _point.y;
	}

	public boolean isInline() {
		return EditModelQuery.isInline(Target.resolveNode(_part));
	}

	private boolean isWidget() {
		return EditModelQuery.isWidget(_part);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("editPart:" + _part + ", --- box: " + getBox());
		return sb.toString();
	}
}
