/*******************************************************************************
 * 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.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.dom.DOMPosition;
import org.eclipse.jst.pagedesigner.dom.DOMPositionHelper;
import org.eclipse.jst.pagedesigner.dom.DOMRefPosition;
import org.eclipse.jst.pagedesigner.dom.EditModelQuery;
import org.eclipse.jst.pagedesigner.parts.NodeEditPart;
import org.eclipse.jst.pagedesigner.parts.TextEditPart;
import org.eclipse.jst.pagedesigner.validation.caret.IMovementMediator;
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 EditPartPositionHelper {
//	private final static Logger _log = PDPlugin
//			.getLogger(EditPartPositionHelper.class);

	/**
	 * Add something to curent
	 * 
	 * @param lineBox
	 * @param host
	 * @param point
	 * @param validator
	 */
	private static void addToCurrentLine(FlowBoxLine lineBox, EditPart host,
			Point point, IPositionMediator validator) {
		Node node = Target.resolveNode(host);
		if (!(node == null || EditModelQuery.isDocument(node))) {
			// Either it is referencable or is editable.
			if (validator.isValidPosition(new DOMRefPosition(node, true))
					|| //
					validator
							.isValidPosition((new DOMRefPosition(node, false)))
					|| //
					validator.isValidPosition(new DOMPosition(node, 0))) {
				lineBox.addLayoutPart(host, point);
			}
		}
	}

	/**
	 * @param position 
	 * @return null means failed to convert to rect.
	 */
	public static Rectangle convertToAbsoluteCaretRect(DesignPosition position) {
		Rectangle ret = null;
		try {
			final int CARET_OFFSET = 1;
			if (position == null || !position.isValid()) {
				return null;
			}
			EditPart containerEditPart = position.getContainerPart();
			if (containerEditPart instanceof TextEditPart) {
				CSSTextFigure figure = (CSSTextFigure) ((TextEditPart) containerEditPart)
						.getFigure();
				ret = figure.calculateCaretPosition(position.getOffset());
				figure.translateToAbsolute(ret);
				ret.width = CaretUpdater.CARET_WIDTH;
			} else {
				int offset = position.getOffset();
				// there is no child
				if (containerEditPart.getChildren().isEmpty()
						|| LayoutPart.getConcretePart(containerEditPart) == null) {
					IFigure figure = ((GraphicalEditPart) containerEditPart)
							.getFigure();
					Rectangle bounds = figure.getBounds();
					if (figure instanceof CSSFigure) {
						List fragments = ((CSSFigure) figure)
								.getFragmentsForRead();
						if (fragments.size() > 0) {
							FlowBox box = (FlowBox) fragments.get(fragments
									.size() - 1);
							bounds = LayoutPart.getBounds(box);
						}
					}

					ret = new Rectangle(bounds.x + CARET_OFFSET, bounds.y,
							CaretUpdater.CARET_WIDTH, bounds.height);

					figure.translateToAbsolute(ret);
				} else if (offset >= 0
						&& offset <= containerEditPart.getChildren().size()) {
					ret = getRefRect(position);
				}
			}
		} catch (Exception e) {
			// This should never happen, we catch here for later analysis.
			// _log.debug("Error in caret rect resolving", e);
			ret = new Rectangle(0, 0, 0, 0);
		}
		if (ret == null) {
			ret = new Rectangle(0, 0, 0, 0);
		}
		return ret;
	}

	/**
	 * This method will create FlowBoxLine to calculate the accurate parts.
	 * 
	 * @param host
	 * @param p
	 * @param validator 
	 * @return the design position
	 */
	public static DesignPosition findEditPartPosition(EditPart host, Point p,
			IPositionMediator validator) {
		try {
			host = validator.getEditableContainer(new Target(host));
			FlowBoxLine boxLine = new FlowBoxLine(
					new Rectangle(p.x, p.y, 0, 0), validator, p);
			DesignPosition position = innerFindEditPartPosition(host, host, p,
					boxLine, validator);
			if (position == null) {
				position = innerFindEditPartPosition(host, host, p, boxLine,
						validator);
				if (position == null) {
					EditPart part = boxLine.getClosestPart();
					if (part != null) {
						LayoutPart layoutPart = new LayoutPart(part, p);
						position = layoutPart.resolvePosition(validator);
					}
				}
			}
			return position;
		} catch (Exception e) {
			return null;
		}

	}

	/**
	 * This function find the position, if there is one which is widget or text
	 * and it contains p, or there is not such widget, then boxLine will returns
	 * the widget that are in a sameline which contains p;
	 * @param rootHost 
	 * @param host 
	 * 
	 * @param p
	 * @param boxLine 
	 * @param validator 
	 * @return the design position
	 */
    //TODO: needs refactoring
	public static DesignPosition innerFindEditPartPosition(EditPart rootHost,
			EditPart host, Point p, FlowBoxLine boxLine,
			IPositionMediator validator) {
		Target target = new Target(host);
		LayoutPart lPart = new LayoutPart(host, p);
		// text
		if (host instanceof TextEditPart) {
			if (lPart.contains(p)) {
				DesignPosition position = null;
				// see if the point is within string.
				position = findTextEditPartPosition((TextEditPart) host, p);
				if (position == null) {
					addToCurrentLine(boxLine, host, p, validator);
				}
				// found?!!
				return position;
			}
            addToCurrentLine(boxLine, host, p, validator);
            return null;
		}
		// widget
		else if (isWidget(host)) {
			if (lPart.contains(p)
					&& (validator.isValidPosition(new DOMRefPosition(target
							.getNode(), true)) || //
					validator.isValidPosition((new DOMRefPosition(target
							.getNode(), false))))) {
				if (IHTMLConstants.TAG_BR.equalsIgnoreCase(Target.resolveNode(
						host).getNodeName())) {
					return new DesignRefPosition(host, lPart.isBeforePoint(p));
				}
                return new DesignRefPosition(host, lPart.isBeforePoint(p)
                		|| !lPart.atLeftPart(p));
			}
            addToCurrentLine(boxLine, host, p, validator);
		} else {
			// root host. we always supporse it has editable area.
			if (host == rootHost) {
				if (host.getChildren().size() > 0) {
					List children = host.getChildren();
					for (int i = 0, size = children.size(); i < size; i++) {
						GraphicalEditPart child = (GraphicalEditPart) children
								.get(i);
						DesignPosition position = innerFindEditPartPosition(
								rootHost, child, p, boxLine, validator);
						if (position != null) {
							return position;
						}
					}
				}
				if (boxLine.getPartsList().size() == 0) {
					if (lPart.contains(p)) {
						// found!!!
						return new DesignPosition(host, 0);
					}
					addToCurrentLine(boxLine, host, p, validator);
				}
			}
			// container
			else {
				// cann't edit it.
				if (!validator.hasEditableArea(target)) {
					if (lPart.contains(p) && //
							(validator.isValidPosition(new DesignRefPosition(
									target.getPart(), true)) || //
							validator.isValidPosition(new DesignRefPosition(
									target.getPart(), true)))) {
						return new DesignRefPosition(host, lPart
								.isBeforePoint(p)
								|| !lPart.atLeftPart(p));
					}
                    addToCurrentLine(boxLine, host, p, validator);
				}
				// can edit
				else {
					// contains p
					if (lPart.contains(p) || //
							(!validator.isValidPosition(new DesignRefPosition(
									target.getPart(), true)) && //
							!validator.isValidPosition(new DesignRefPosition(
									target.getPart(), true)))) {
						if (host.getChildren().size() > 0) {
							List children = host.getChildren();
							for (int i = 0, size = children.size(); i < size; i++) {
								GraphicalEditPart child = (GraphicalEditPart) children
										.get(i);
								DesignPosition position = innerFindEditPartPosition(
										rootHost, child, p, boxLine, validator);
								if (position != null) {
									return position;
								}
							}
						} else {
							// we put the container which is empty here.
							if (lPart.contains(p)) {
								// found!!!
								return new DesignPosition(host, 0);
							}
                            addToCurrentLine(boxLine, host, p, validator);
						}
					}
					// not contains p
					else {
						addToCurrentLine(boxLine, host, p, validator);
					}
				}
			}
		}
		return null;
	}

	/**
	 * similiar to findEditPartPositionConstrained, this method is used to
	 * vertically move caret.
	 * 
	 * @param host
	 * @param p
	 * @param validator 
	 * @return the design position
	 */
	public static DesignPosition findEditPartPositionConstrained(EditPart host,
			Point p, IMovementMediator validator) {
		try {
			FlowBoxLine boxLine = new FlowBoxLine(
					new Rectangle(p.x, p.y, 0, 0), validator, p);
			DesignPosition position = innerFindEditPartPositionConstrained(
					host, host, p, boxLine, validator);
			if (position == null) {
				position = innerFindEditPartPositionConstrained(host, host, p,
						boxLine, validator);
				if (position == null) {
					EditPart part = boxLine.getClosestPart();
					if (part != null) {
						LayoutPart layoutPart = new LayoutPart(part, p);
						position = layoutPart.resolvePosition(validator);
					}
				}
			}
			return position;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * This method is used for move up/down, except for using tactics to deal
	 * with container, this method is similiar to findEditPartPosition.
	 * 
	 * @param rootHost 
	 * @param host 
	 * @param p
	 * @param boxLine 
	 * @param validator 
	 * @return the design position
	 */
    // TODO: needs refactoring
	public static DesignPosition innerFindEditPartPositionConstrained(
			EditPart rootHost, EditPart host, Point p, FlowBoxLine boxLine,
			IMovementMediator validator) {
		Target target = new Target(host);
		LayoutPart lPart = new LayoutPart(host, p);
		// text
		if (host instanceof TextEditPart) {
			if (lPart.contains(p)) {
				DesignPosition position = null;
				// see if the point is within string.
				position = findTextEditPartPosition((TextEditPart) host, p);
				if (position == null) {
					addToCurrentLine(boxLine, host, p, validator);
				}
				// found?!!
				return position;
			}
            addToCurrentLine(boxLine, host, p, validator);
            return null;
		}
		// widget
		else if (isWidget(host)) {
			if (lPart.contains(p)) {
				// found!!!
				if (IHTMLConstants.TAG_BR.equalsIgnoreCase(Target.resolveNode(
						host).getNodeName())) {
					return new DesignRefPosition(host, lPart.isBeforePoint(p));
				}
                return new DesignRefPosition(host, lPart.isBeforePoint(p)
                		|| !lPart.atLeftPart(p));
			}
            addToCurrentLine(boxLine, host, p, validator);
		} else {
			// root host. we always supporse it has editable area.
			if (host == rootHost) {
				if (host.getChildren().size() > 0) {
					List children = host.getChildren();
					for (int i = 0, size = children.size(); i < size; i++) {
						GraphicalEditPart child = (GraphicalEditPart) children
								.get(i);
						DesignPosition position = innerFindEditPartPositionConstrained(
								rootHost, child, p, boxLine, validator);
						if (position != null) {
							return position;
						}
					}
				} else {
					if (lPart.contains(p)) {
						// found!!!
						return new DesignPosition(host, 0);
					}
					addToCurrentLine(boxLine, host, p, validator);
				}
			}
			// container
			else {
				// cann't edit it.
				if (!validator.hasEditableArea(target)
						|| !validator.allowsMoveIn(target)) {
					if (validator.canReference(target, true)
							|| validator.canReference(target, false)) {
						if (lPart.contains(p)) {
							return new DesignRefPosition(host, lPart
									.isBeforePoint(p)
									|| !lPart.atLeftPart(p));
						}
                        addToCurrentLine(boxLine, host, p, validator);
					}
				}
				// can edit
				else {
					// contains p
					if (lPart.contains(p)) {
						if (host.getChildren().size() > 0) {
							List children = host.getChildren();
							for (int i = 0, size = children.size(); i < size; i++) {
								GraphicalEditPart child = (GraphicalEditPart) children
										.get(i);
								DesignPosition position = innerFindEditPartPositionConstrained(
										rootHost, child, p, boxLine, validator);
								if (position != null) {
									return position;
								}
							}
						} else {
							// we put the container which is empty here.
							if (lPart.contains(p)) {
								// found!!!
								return new DesignPosition(host, 0);
							}
                            addToCurrentLine(boxLine, host, p, validator);
						}
					}
					// not contains p
					else {
						addToCurrentLine(boxLine, host, p, validator);
					}
				}
			}
		}
		return null;

	}

	// /**
	// * @param host
	// * @param p
	// * @return
	// */
	// private static DesignPosition
	// findTextEditPartPositionAdjacent(TextEditPart host, Point p)
	// {
	// if (host.getFigure() instanceof CSSTextFigure)
	// {
	// CSSTextFigure figure = (CSSTextFigure) host.getFigure();
	// // make a copy to not destroy the original o
	// p = p.getCopy();
	// figure.translateToRelative(p);
	// int offset = figure.getNewInsertionOffset(p);
	// if (offset >= 0)
	// {
	// return new DesignPosition(host, offset);
	// }
	// else
	// {
	// return null;
	// }
	// }
	// else
	// {
	// // should not happen.
	// return new DesignPosition(host, 0);
	// }
	// }

	/**
	 * @param host
	 * @param p
	 * @return
	 */
	private static DesignPosition findTextEditPartPosition(TextEditPart host,
			Point p) {
		if (host.getFigure() instanceof CSSTextFigure) {
			CSSTextFigure figure = (CSSTextFigure) host.getFigure();
			// make a copy to not destroy the original o
			p = p.getCopy();
			figure.translateToRelative(p);
			int offset = figure.getInsertionOffset(p);
			if (offset >= 0) {
				return new DesignPosition(host, offset);
			}
            return null;
		}
        // should not happen.
        return new DesignPosition(host, 0);
	}

	/**
	 * @param figure
	 * @param box
	 * @return
	 */
//	public static Rectangle getBoxBounds(IFigure figure, FlowBox box) {
//		Rectangle r = new Rectangle(box._x, box._y, box.getWidth(), box
//				.getHeight());
//		figure.translateToAbsolute(r);
//		return r;
//	}

	/**
	 * If child is a GraphicalEditPart, a new copy of its bounding rectangle
	 * will be returned translated to absolute bounds. If child is not a GraphicalEditPart
	 * then the empty rectangle (0,0,0,0) is returned.
	 * 
	 * @param child
	 * @return the bounding rectangle or (0,0,0,0) if none.
	 */
	public static Rectangle getAbsoluteBounds(EditPart child) {
		if (child instanceof GraphicalEditPart) {
			Rectangle bounds = ((GraphicalEditPart) child).getFigure()
					.getBounds().getCopy();
			((GraphicalEditPart) child).getFigure().translateToAbsolute(bounds);
			return bounds;
		}
        return new Rectangle(0, 0, 0, 0);
	}

	/**
	 * @param host
	 * @param tagName
	 * @return
	 */
	private static boolean isWidget(EditPart host) {
		if (host instanceof NodeEditPart) {
			return ((NodeEditPart) host).isWidget();
		}
        return false;
	}

	/**
	 * Is Caret at right?
	 * 
	 * @param position
	 * @param caretRefResult
	 * @return
	 */
	private static EditPart tryTwoWays(DesignPosition position,
			List<Boolean> caretRefResult) {
		EditPart result = null;
		// Sibling first:
		Node node = EditModelQuery.getInstance().getSibling(
				DOMPositionHelper.toDOMPosition(position), true);
		if (node != null && !EditModelQuery.isTransparentText(node)) {
			result = Target.resolvePart(node);
			caretRefResult.add(Boolean.FALSE);
		} else {
			node = EditModelQuery.getInstance().getSibling(
					DOMPositionHelper.toDOMPosition(position), false);
			if (node != null && !EditModelQuery.isTransparentText(node)) {
				result = Target.resolvePart(node);
				caretRefResult.add(Boolean.TRUE);
			}
		}
		if (result == null) {
			if (getConcretePart(position, false) != null) {
				result = getConcretePart(position, false);
				caretRefResult.add(Boolean.TRUE);
			} else if (getConcretePart(position, true) != null) {
				result = getConcretePart(position, true);
				caretRefResult.add(Boolean.FALSE);
			}
		}
		return result;
	}

	/*
	 * Here we are doing something to avoid reference witespace tag. Since we
	 * still need to improve whitespace tags's layout furthure more.
	 */
	private static EditPart getNextConcretPart(DesignPosition position,
			List<Boolean> caretIsAtRightTest) {
		EditPart result = null;
		boolean caretIsAtRight = true;
		if (position instanceof DesignRefPosition) {
			caretIsAtRight = ((DesignRefPosition) position).caretIsAtRight();
			result = ((DesignRefPosition) position).getRefPart();
			caretIsAtRightTest.add(Boolean.valueOf(caretIsAtRight));
		}
		if (result == null
				|| EditModelQuery.isTransparentText(Target.resolveNode(result))) {
			caretIsAtRightTest.clear();
			result = tryTwoWays(position, caretIsAtRightTest);
		}
		return result;
	}

	/**
	 * Avoid whitespaces
	 * 
	 * @param position
	 * @param forward
	 * @return the edit part at position which is non-whitespace ? TODO:
	 */
	public static EditPart getConcretePart(DesignPosition position,
			boolean forward) {
		EditPart result = null;
		Node node = EditModelQuery.getInstance().getSibling(
				DOMPositionHelper.toDOMPosition(position), forward);
		while (node != null && EditModelQuery.isTransparentText(node)) {
			node = EditModelQuery.getInstance().getSibling(node, forward);
		}
		if (node != null) {
			result = Target.resolvePart(node);
		}
		return result;
	}

	/**
	 * @param position
	 * @param forward
	 * @return the next concrete part.
	 */
	public static EditPart getNextConcretPart(DesignPosition position,
			boolean forward) {
		Node node;
		EditPart result = null;
		node = EditModelQuery.getInstance().getSibling(
				DOMPositionHelper.toDOMPosition(position), forward);
		if (node != null) {
			if (forward) {
				while (node != null) {
					if (!EditModelQuery.isTransparentText(node)
							&& (result = Target.resolvePart(node)) != null) {
						result = Target.resolvePart(node);
						break;
					}
					node = node.getNextSibling();
				}
			} else {
				while (node != null) {
					if (!EditModelQuery.isTransparentText(node)
							&& (result = Target.resolvePart(node)) != null) {
						result = Target.resolvePart(node);
						break;
					}
					node = node.getPreviousSibling();
				}
			}
		}
		return result;
	}

	private static Rectangle getRefRect(DesignPosition position) {
		List<Boolean> caretLocation = new ArrayList<Boolean>();
		EditPart part = getNextConcretPart(position, caretLocation);
		LayoutPart layoutPart;
		Rectangle rect = null;
		if (part != null) {
			layoutPart = new LayoutPart(part, null);
			boolean caretIsAtRight = caretLocation.get(0)
					.booleanValue();
			final int CARET_OFFSET = 1;
			Rectangle bounds = null;
			IFigure figure = ((GraphicalEditPart) part).getFigure();
			if (!caretIsAtRight) {
				FlowBox box;
				if ((box = layoutPart.getLine(0)) != null) {
					bounds = LayoutPart.getBounds(box);
				}
			} else {
				FlowBox box;
				if ((box = layoutPart.getLastLine()) != null) {
					bounds = LayoutPart.getBounds(box);
				}
			}
			if (bounds == null) {
				bounds = figure.getBounds();
			}
			if (!caretIsAtRight) {
				rect = new Rectangle(bounds.x - CARET_OFFSET, bounds.y,
						CaretUpdater.CARET_WIDTH, bounds.height);// new
			} else {
				rect = new Rectangle(bounds.getRight().x + CARET_OFFSET,
						bounds.y, CaretUpdater.CARET_WIDTH, bounds.height);// new
			}
			figure.translateToAbsolute(rect);
		} else {
			System.out.println("No concrete part?");
		}
		return rect;
	}
}
