/******************************************************************************
 * Copyright (c) 2004, 2009 IBM Corporation 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:
 *    IBM Corporation - initial API and implementation
 *    Mariot Chauvin <mariot.chauvin@obeo.fr> - bug 233344 
 ****************************************************************************/


package org.eclipse.gmf.runtime.draw2d.ui.internal.routers;

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

import org.eclipse.draw2d.AbsoluteBendpoint;
import org.eclipse.draw2d.Bendpoint;
import org.eclipse.draw2d.BendpointConnectionRouter;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.draw2d.ui.geometry.LineSeg;
import org.eclipse.gmf.runtime.draw2d.ui.internal.Draw2dDebugOptions;
import org.eclipse.gmf.runtime.draw2d.ui.internal.Draw2dPlugin;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;

/**
 * This class is a top level router for managing the individual branches in a set of
 * tree routed connections.
 *
 * @author sshaw
 */
public class TreeRouter extends BendpointConnectionRouter implements OrthogonalRouter {

	private BranchRouter branchRouter = new BranchRouter(this);
	private ArrayList connectionList = new ArrayList();
	private Dimension trunkVertex;
	private Orientation trunkOrientation;
	private boolean updatingPeers = false;
	
	static private class Orientation {

		private Orientation() {
			// Empty constructor
		}
		
		/**
		 * Constant for the top orientation 
		 */
		static public Orientation TOP = new Orientation();
		
		/**
		 * Constant for the bottom orientation 
		 */
		static public Orientation BOTTOM = new Orientation();
		
		/**
		 * Constant for the right orientation 
		 */
		static public Orientation RIGHT = new Orientation(); 
		
		/**
		 * Constant for the left orientation 
		 */
		static public Orientation LEFT = new Orientation(); 
		
		/**
		 * getEdge
		 * Method to return the edge point of the given Rectangle representative
		 * of the orientation value of the instance.
		 * 
		 * @param bounds Rectangle to retrieve the edge value from.
		 * @return Point that is the edge of the rectangle for the orientation of this.
		 */
		public Point getEdge(Rectangle bounds) {
			if (this == TOP)
				return bounds.getTop();
			else if (this == BOTTOM)
				return bounds.getBottom();
			else if (this == RIGHT)
				return bounds.getRight();

			return bounds.getLeft();
		}
	}
	
	/**
	 * 
	 */
	public TreeRouter() {
		super();
	}

	
	/**
	 * @see org.eclipse.draw2d.ConnectionRouter#invalidate(Connection)
	 */
	public void invalidate(Connection conn) {
		if (conn.getSourceAnchor() == null || conn.getSourceAnchor().getOwner() == null ||
			conn.getTargetAnchor() == null || conn.getTargetAnchor().getOwner() == null)
			return;

		ListIterator li = connectionList.listIterator();
		while (li.hasNext()) {
			Connection connNext = (Connection)li.next();
			
			if (!trunkVertexEqual(connNext, conn)) {
				final ConnectionAnchor connExtSourceAnchor = connNext.getSourceAnchor();
				final ConnectionAnchor connExtTargetAnchor = connNext.getTargetAnchor();
				if (connExtSourceAnchor != null && connExtSourceAnchor.getOwner() != null &&
						connExtTargetAnchor != null && connExtTargetAnchor.getOwner() != null){
					updateConstraint(connNext);
				}
			}
		}
	}
	
	private boolean trunkVertexEqual(Connection connMaster, Connection connSlave) {
		PointList cmPts = connMaster.getPoints();
		PointList csPts = connSlave.getPoints();
		if (cmPts.size() > 2 && csPts.size() > 2)
			return cmPts.getPoint(2).equals(csPts.getPoint(2));
		
		return false;
	}
    
	private Rectangle getTargetAnchorRelativeBounds(final Connection conn) {
		final Rectangle bounds = conn.getTargetAnchor().getOwner().getBounds().getCopy();
		conn.getTargetAnchor().getOwner().translateToAbsolute(bounds);
		conn.translateToRelative(bounds);
		return bounds;
	}

	private Rectangle getSourceAnchorRelativeBounds(final Connection conn) {
		final Rectangle bounds = conn.getSourceAnchor().getOwner().getBounds().getCopy();
		conn.getSourceAnchor().getOwner().translateToAbsolute(bounds);
		conn.translateToRelative(bounds);
		return bounds;
	}

	
	/**
	 * getTrunkLocation
	 * Method to retrieve the trunk location in relative coordinates based on 
	 * current tree state.
	 * 
	 * @param conn Connection being routed
	 * @return Point that is the trunk location in relative coordinates.
	 */
	public Point getTrunkLocation(Connection conn) {
		Dimension vertex = getTrunkVertex();
		Point target = getTrunkOrientation().getEdge(getTargetAnchorRelativeBounds(conn));

		Point ptTrunkLoc = new Point(vertex.width, vertex.height);
		ptTrunkLoc = ptTrunkLoc.getTranslated(target);
		
		return ptTrunkLoc;
	}
	
	/**
	 * setTrunkLocation
	 * Setter method to set the trunk location.  Translates the point into a relative
	 * point from the target edge.
	 * 
	 * @param conn Connection being routed
	 * @param ptTrunkLoc Point that is the trunk location in relative coordinates.
	 */
	public void setTrunkLocation(Connection conn, Point ptTrunkLoc) {
		Point ptRelTrunkLoc = new Point(ptTrunkLoc);
		
		final Rectangle targetAnchorBounds = getTargetAnchorRelativeBounds(conn); 
		
		// update orientation
		if (isTopDown(conn)) {
			if (ptTrunkLoc.y < targetAnchorBounds.getCenter().y)
				setTrunkOrientation(Orientation.TOP);
			else
				setTrunkOrientation(Orientation.BOTTOM);
		}
		else {
			if (ptTrunkLoc.x < targetAnchorBounds.getCenter().x)
				setTrunkOrientation(Orientation.LEFT);
			else
				setTrunkOrientation(Orientation.RIGHT);
		}

		Point target = getTrunkOrientation().getEdge(targetAnchorBounds);
		
		Dimension currentVertex = ptRelTrunkLoc.getDifference(target);
		setTrunkVertex(currentVertex);
	}
	
	/**
	 * updateConstraint
	 * Updates the constraint value for the connection based on the tree vertex
	 *
	 * @param conn Connection whose constraint is to be updated.
	 */
	protected void updateConstraint(Connection conn) {
		if (isUpdatingPeers())
			return;
		
		List bendpoints = (List)conn.getRoutingConstraint(); 
		if (bendpoints == null)
			bendpoints = new ArrayList(conn.getPoints().size());
		
		if (bendpoints != null) {
			Point sourceRefPoint = conn.getSourceAnchor().getReferencePoint();
			conn.translateToRelative(sourceRefPoint);

			Point targetRefPoint = conn.getTargetAnchor().getReferencePoint();
			conn.translateToRelative( targetRefPoint);

			Point ptTrunk = getTrunkLocation(conn);
			Point ptSource = getBranchRouter().getSourceLocation(conn, ptTrunk);
			
			bendpoints.clear();
			PointList pts = getBranchRouter().recreateBranch(conn, ptSource, ptTrunk);
			for (int i=0; i<pts.size(); i++) {
				Bendpoint bp = new AbsoluteBendpoint(pts.getPoint(i));
				bendpoints.add(bp);
			}
		}
		
		setUpdatingPeers(true);
		
		try {
			setConstraint(conn, bendpoints);
			conn.invalidate();
			conn.validate();
		}
		catch (Exception e) {
			Trace.catching(Draw2dPlugin.getInstance(), Draw2dDebugOptions.EXCEPTIONS_CATCHING, TreeRouter.class, "updateConstraint", //$NON-NLS-1$
				e);
		}
		finally {
			setUpdatingPeers(false);
		}
	}
	
	/**
	 * getPointsFromConstraint
	 * Utility method retrieve the PointList equivalent of the bendpoint constraint
	 * set in the Connection.
	 * 
	 * @param conn Connection to retrieve the constraint from.
	 * @return PointList list of points that is the direct equivalent of the set constraint.
	 */
	public PointList getPointsFromConstraint(Connection conn) {
		List bendpoints = (List)conn.getRoutingConstraint();
		if (bendpoints == null)
			return new PointList();
		
		PointList points = new PointList(bendpoints.size());
		for (int i = 0; i < bendpoints.size(); i++) {
			Bendpoint bp = (Bendpoint) bendpoints.get(i);
			points.addPoint(bp.getLocation());
		}
		
		straightenPoints(points, MapModeUtil.getMapMode(conn).DPtoLP(3));
		return points;
	}
	
    /**
     * straightenPoints
     * This is a simpler version of the @see updateIfNotRectilinear that simply ensures
     * that the lines are horizontal or vertical without any intelligence in terms of 
     * shortest distance around a rectangle.
     * 
	 * @param newLine PointList to check for rectilinear qualities and change if necessary.
	 * @param tolerance int tolerance value by which points will be straightened in HiMetrics
	 */
	static protected void straightenPoints(PointList newLine, int tolerance) {
        for (int i=0; i<newLine.size()-1; i++) {
            Point ptCurrent = newLine.getPoint(i);
            Point ptNext = newLine.getPoint(i+1);
            
            int xDelta = Math.abs(ptNext.x - ptCurrent.x);
            int yDelta = Math.abs(ptNext.y - ptCurrent.y);
            
            if (xDelta < yDelta) {
            	if (xDelta > tolerance)
            		return;
                ptNext.x = ptCurrent.x;
            } else {
            	if (yDelta > tolerance)
            		return;
                ptNext.y = ptCurrent.y;
            }
            
            newLine.setPoint(ptNext, i+1);
        }
    }
	
	/**
	 * Returns the branch router in the chain.
	 * @return The getBranchRouter router
	 * 
	 */
	protected BranchRouter getBranchRouter() {
		return branchRouter;
	}

	/**
	 * @see org.eclipse.draw2d.ConnectionRouter#remove(Connection)
	 */
	public void remove(Connection conn) {
		if (conn.getSourceAnchor() == null || conn.getTargetAnchor() == null)
			return;
		
		int index = connectionList.indexOf(conn);
		connectionList.remove(conn);
		for (int i = index + 1; i < connectionList.size(); i++)
			((Connection)connectionList.get(i)).revalidate();
	
		getBranchRouter().remove(conn);
	}

	/**
	 * isTopDown
	 * Utility method to determine if the connection should routed in a top-down fashion
	 * or in a horizontal fashion.
     * 
	 * @param conn Connection to query
	 * @return boolean true if connection should be routed top-down, false otherwise.
	 */
	public boolean isTopDown(Connection conn) {
		boolean vertical = true;
		if (conn instanceof ITreeConnection) {
			vertical = ((ITreeConnection)conn).getOrientation().equals(ITreeConnection.Orientation.VERTICAL) ? vertical = true : false;
		}
		
		return vertical;
	}
	
	private int DEFAULT_TRUNK_HEIGHT = 32;
	
	/**
	 * checkTrunkVertex
	 * Method to initialize the trunk vertex to a default value if not already set
	 * 
	 * @param conn Connection to be routed.
	 */
	private void checkTrunkVertex(Connection conn) {
		if (getTrunkVertex() == null) {
			Rectangle sourceRect = conn.getSourceAnchor().getOwner().getBounds();
			Rectangle targetRect = conn.getTargetAnchor().getOwner().getBounds();
			
			Dimension default_trunk = new Dimension(0, DEFAULT_TRUNK_HEIGHT);
			conn.translateToRelative(default_trunk);
			
			if (isTopDown(conn)) {
				if (sourceRect.getCenter().y < targetRect.getCenter().y) {
					setTrunkVertex(new Dimension(0, -default_trunk.height));
					setTrunkOrientation(Orientation.TOP);
				}
				else {
					setTrunkVertex(new Dimension(0, default_trunk.height));
					setTrunkOrientation(Orientation.BOTTOM);
				}
			}
			else {
				if (sourceRect.getCenter().x < targetRect.getCenter().x) {
					setTrunkVertex(new Dimension(-default_trunk.height, 0));
					setTrunkOrientation(Orientation.LEFT);
				}
				else {
					setTrunkVertex(new Dimension(default_trunk.height, 0));
					setTrunkOrientation(Orientation.RIGHT);
				}
			}
		}
	}
	
	/* (non-Javadoc)
	 * Routes the given connection.  Calls the 'getBranchRouter' router method first
	 * @see org.eclipse.draw2d.ConnectionRouter#route(org.eclipse.draw2d.Connection)
	 */
	public void route(Connection conn) {
		
		if (conn.getSourceAnchor() == null || conn.getSourceAnchor().getOwner() == null ||
			conn.getTargetAnchor() == null || conn.getTargetAnchor().getOwner() == null) {
			super.route(conn);
			return;
		}
		
		if (!connectionList.contains(conn)) {
			connectionList.add(conn);
		}
		
		checkTrunkVertex(conn);
		
		getBranchRouter().route(conn);
		invalidate(conn);
	}

	/**
	 * @return Returns the truckVertex.
	 */
	protected Dimension getTrunkVertex() {
		return trunkVertex;
	}

	/**
	 * @param trunkVertex The trunkVertex to set.
	 */
	protected void setTrunkVertex(Dimension trunkVertex) {
		this.trunkVertex = trunkVertex;
	}
	
	/**
	 * @return Returns the trunkOrientation.
	 */
	protected Orientation getTrunkOrientation() {
		return trunkOrientation;
	}
	
	/**
	 * @param trunkOrientation The trunkOrientation to set.
	 */
	protected void setTrunkOrientation(Orientation trunkOrientation) {
		this.trunkOrientation = trunkOrientation;
	}
	
	/**
	 * Utility method to determine if the given set of points conforms to the constraints
	 * of being an orthogonal connection tree-branch.
	 * 1. Points size must be 4.
	 * 2. Source point resides with-in boundary of source shape based on orientation
	 * 3. Target point resides with-in boundary of target shape based on orientation
	 * 4. Middle line is perpendicular to the 2 end lines.
	 * 
	 * @param conn the <code>Connection</code> to test
	 * @param points <code>PointList</code> to test constraints against
	 * @return <code>boolean</code> <code>true</code> if points represent valid orthogaonl tree 
	 * branch, <code>false</code> otherwise.
	 */
	public boolean isOrthogonalTreeBranch(Connection conn, PointList points) {
		if (isTreeBranch(conn, points)) {
			LineSeg branch = new LineSeg(points.getPoint(0), points.getPoint(1));
			LineSeg trunkShoulder = new LineSeg(points.getPoint(1), points.getPoint(2));
			LineSeg trunk = new LineSeg(points.getPoint(2), points.getPoint(3));
			
			if (isTopDown(conn))
				return branch.isVertical() && trunkShoulder.isHorizontal() && trunk.isVertical();
			else
				return branch.isHorizontal() && trunkShoulder.isVertical() && trunk.isHorizontal();
		}
		
		return false;
	}
	
	/**
	 * Utility method to determine if the given set of points conforms to the constraints
	 * of being a connection tree-branch.
	 * 1. Points size must be 4.
	 * 2. Source point resides with-in boundary of source shape based on orientation
	 * 3. Target point resides with-in boundary of target shape based on orientation
	 * 
	 * @param conn the <code>Connection</code> to test
	 * @param points the <code>PointList</code> to test constraints against
	 * @return <code>boolean</code> <code>true</code> if points represent valid tree branch, 
	 * <code>false</code> otherwise.
	 */
	public boolean isTreeBranch(Connection conn, PointList points) {
		if (points.size() == 4) {
			// just check if ends are with-in the owner bounding box
			Rectangle targetBounds = getTargetAnchorRelativeBounds(conn);
			Rectangle sourceBounds = getSourceAnchorRelativeBounds(conn);
			
			if (isTopDown(conn)) {
				return (points.getPoint(0).x > sourceBounds.x && 
					    points.getPoint(0).x < sourceBounds.x + sourceBounds.width) &&
					   (points.getPoint(3).x > targetBounds.x && 
						points.getPoint(3).x < targetBounds.x + targetBounds.width);
			}
			else
			{
				return (points.getPoint(0).y > sourceBounds.y && 
					    points.getPoint(0).y < sourceBounds.y + sourceBounds.height) &&
					   (points.getPoint(3).y > targetBounds.y && 
						points.getPoint(3).y < targetBounds.y + targetBounds.height);
			}
		}
		
		return false;
	}
	
	/**
	 * @return Returns the connectionList List which is a copy of the internal list.
	 */
	public List getConnectionList() {
		return (List)connectionList.clone();
	}
	/**
	 * @return Returns the updatingPeers.
	 */
	protected boolean isUpdatingPeers() {
		return updatingPeers;
	}
	/**
	 * @param updatingPeers The updatingPeers to set.
	 */
	protected void setUpdatingPeers(boolean updatingPeers) {
		this.updatingPeers = updatingPeers;
	}
}
