//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.authoring.gef.edit;

import java.util.Iterator;
import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.epf.authoring.gef.commands.ChangeBoundsCommand;
import org.eclipse.epf.authoring.gef.commands.ReconnectLinkCommand;
import org.eclipse.epf.authoring.gef.util.DiagramUIResources;
import org.eclipse.epf.diagram.model.Link;
import org.eclipse.epf.diagram.model.Node;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;

/**
 * Service class to allow create and register common action to the action
 * register. Most of the code are moved from the Editor class.
 * 
 * @author Jinhua Xi
 * @since 1.0
 */
public class DiagramActionService {

	public static final String ALIGN_HORZ_AVERAGE = "align_horizontal_to_average"; //$NON-NLS-1$

	public static final String ALIGN_HORZ_FIRST_SELECTED = "align_horizontal_to_first_selection"; //$NON-NLS-1$

	public static final String ALIGN_VERT_AVERAGE = "align_vertical_to_average"; //$NON-NLS-1$

	public static final String ALIGN_VERT_FIRST_SELECTED = "align_vertical_to_first_selection"; //$NON-NLS-1$

	private DefaultEditDomain editDomain;

	private GraphicalViewer graphicalViewer;

	private ActionRegistry actionRegistry;

	/**
	 * Constructor 
	 * @param graphicalViewer {@link GraphicalViewer}
	 * @param editDomain 	{@link DefaultEditDomain}
	 * @param actionRegistry 	{@link ActionRegistry}
	 */
	public DiagramActionService(GraphicalViewer graphicalViewer,
			DefaultEditDomain editDomain, ActionRegistry actionRegistry) {
		this.graphicalViewer = graphicalViewer;
		this.editDomain = editDomain;
		this.actionRegistry = actionRegistry;
	}

	/**
	 * Sets the GraphicalViewer.
	 */
	public void setGraphicalViewer(GraphicalViewer graphicalViewer) {
		this.graphicalViewer = graphicalViewer;
	}

	/**
	 * returns GraphicalViewer
	 */
	private GraphicalViewer getGraphicalViewer() {
		return graphicalViewer;
	}

	/**
	 * Returns the command stack.
	 * 
	 * @return the command stack
	 */
	protected CommandStack getCommandStack() {
		return getEditDomain().getCommandStack();
	}

	/**
	 * Returns the edit domain.
	 * 
	 * @return the edit domain
	 */
	protected DefaultEditDomain getEditDomain() {
		return editDomain;
	}

	protected ActionRegistry getActionRegistry() {
		return actionRegistry;
	}

	/**
	 * Register HorizontalAlignAverageAction action. 
	 * HorizontalAignAverage Action aligns selected editparts to horizontal average.  
	 */
	public IAction registerHorizontalAlignAverageAction() {
		// align horizontally to average y-value of all nodes
		IAction hAlignAverageAction = new Action(
				DiagramUIResources.AbstractDiagramEditor_hAlignAverageAction_text) { //$NON-NLS-1$
			public void run() {
				horizAlignToAverageSelected();
			}

			public String getId() {
				return ALIGN_HORZ_AVERAGE;
			}
		};
		getActionRegistry().registerAction(hAlignAverageAction);

		return hAlignAverageAction;
	}
	
	/**
	 * Register HorizontalAlignFirstSelectedAction action. 
	 * HorizontalAlignFirstSelectedAction aligns selected editparts with 
	 * respect to first selected editpart. 
	 */

	public IAction registerHorizontalAlignFirstSelectedAction() {
		// align horizontally to y-value of first selected node
		IAction hAlignFirstSelectedAction = new Action(
				DiagramUIResources.AbstractDiagramEditor_hAlignFirstSelectedAction_text) { //$NON-NLS-1$
			public void run() {
				horzAlignToFirstSelected();
			}

			public String getId() {
				return ALIGN_HORZ_FIRST_SELECTED;
			}
		};
		getActionRegistry().registerAction(hAlignFirstSelectedAction);

		return hAlignFirstSelectedAction;
	}
	
	/**
	 * Register vertialAlignAverageAction action. 
	 * vertialAlignAverageAction aligns selected editparts vertically w.r.t average.
	 * 
	 */
	
	public IAction registerVerticalAlignAverageAction() {
		// align vertically to average x-value of all selected nodes
		IAction vAlignAverageAction = new Action(
				DiagramUIResources.AbstractDiagramEditor_vAlignAverageAction_text) { //$NON-NLS-1$
			public void run() {
				verticalAlignToAverageSelected();
			}

			public String getId() {
				return ALIGN_VERT_AVERAGE;
			}
		};
		getActionRegistry().registerAction(vAlignAverageAction);

		return vAlignAverageAction;
	}

	/**
	 * Register vertialAlignFirstSelectedAction action. 
	 * vertialAlignFirstSelectedAction aligns selected editparts vertically w.r.t first selected.
	 * 
	 */

	public IAction registerVerticalAlignFirstSelectedAction() {
		// align vertically to x-value of first selected node
		IAction vAlignFirstSelectedAction = new Action(
				DiagramUIResources.AbstractDiagramEditor_vAlignFirstSelectedAction_text) { //$NON-NLS-1$
			public void run() {
				verticalAlignToFirstSelected();
			}

			public String getId() {
				return ALIGN_VERT_FIRST_SELECTED;
			}
		};
		getActionRegistry().registerAction(vAlignFirstSelectedAction);

		return vAlignFirstSelectedAction;
	}

	// /////////////////////////////////////////////////////////////////////////////////////////////////
	// action methods
	// /////////////////////////////////////////////////////////////////////////////////////////////////
	
	/** 
	 * Action implementation method for horizontalAlignFirsteSElectedAction.
	 * 
	 */
	public void horzAlignToFirstSelected() {
		List editParts = getGraphicalViewer().getSelectedEditParts();
		AbstractGraphicalEditPart firstPart = null;
		// loop through all selected items, remember the y-value of the
		// first node,
		// set the following nodes to the same y-value
		for (int a = 0; a < editParts.size(); a++) {
			if (editParts.get(a) instanceof NodeEditPart
					|| editParts.get(a) instanceof NodeContainerEditPart) {
				AbstractGraphicalEditPart ep = (AbstractGraphicalEditPart) editParts
						.get(a);
				// remember the first part we move
				if (firstPart == null) {
					firstPart = ep;
				} else {
					// calculate the offset for centerline alignment
					Rectangle bounds = ep.getFigure().getBounds();
					int offset = (int) ((double) (bounds.height - firstPart
							.getFigure().getBounds().height) / 2.0);
					// is this node in a container?
					if (!(ep.getParent() instanceof DiagramEditPart)) {
						// need to move the container, adjust the offset
						ep = (AbstractGraphicalEditPart) ep.getParent();
						Rectangle parentBounds = ep.getFigure().getBounds();
						offset += bounds.y - parentBounds.y;
						bounds = parentBounds;
					}
					// send the command to move the node
					org.eclipse.gef.commands.Command c = new ChangeBoundsCommand(
							(Node) ep.getModel(), new Point(bounds.x, firstPart
									.getFigure().getBounds().y
									- offset), bounds.width);
					getCommandStack().execute(c);
				}
			}
		}
	}
	
	/** 
	 * Action implementation method for horizontalAlignAverageAction.
	 * 
	 */
	public void horizAlignToAverageSelected() {
		List editParts = getGraphicalViewer().getSelectedEditParts();
		AbstractGraphicalEditPart firstPart = null;
		int total = 0;
		int ysum = 0;
		for (int a = 0; a < editParts.size(); a++) {
			if (editParts.get(a) instanceof NodeEditPart
					|| editParts.get(a) instanceof NodeContainerEditPart) {
				AbstractGraphicalEditPart ep = (AbstractGraphicalEditPart) editParts
						.get(a);
				// remember the first part we move
				if (firstPart == null) {
					firstPart = ep;
				}
				ysum += ep.getFigure().getBounds().y;
				total++;
			}
		}
		// calculate the average y-value for all nodes
		int yave = (int) ((double) ysum / (double) total);
		// loop through all the nodes again and set them
		for (int a = 0; a < editParts.size(); a++) {
			if (editParts.get(a) instanceof NodeEditPart
					|| editParts.get(a) instanceof NodeContainerEditPart) {
				AbstractGraphicalEditPart ep = (AbstractGraphicalEditPart) editParts
						.get(a);
				// calculate the height difference, so that elements are aligned
				// through the centerline
				Rectangle bounds = ep.getFigure().getBounds();
				int offset = (int) ((double) (bounds.height - firstPart
						.getFigure().getBounds().height) / 2.0);
				// is this node inside a container?
				if (!(ep.getParent() instanceof DiagramEditPart)) {
					// we need to move the container, adjust the offset
					ep = (AbstractGraphicalEditPart) ep.getParent();
					Rectangle parentBounds = ep.getFigure().getBounds();
					offset += bounds.y - parentBounds.y;
					bounds = parentBounds;
				}
				// send the command to move the node
				org.eclipse.gef.commands.Command c = new ChangeBoundsCommand(
						(Node) ep.getModel(),
						new Point(bounds.x, yave - offset), bounds.width);
				getCommandStack().execute(c);
			}
		}

	}
	/** 
	 * Action implementation method for verticalAlignToAverageAction.
	 * 
	 */

	public void verticalAlignToAverageSelected() {
		List editParts = getGraphicalViewer().getSelectedEditParts();
		AbstractGraphicalEditPart firstPart = null;
		int total = 0;
		int xsum = 0;
		// loop through the selected parts
		for (int a = 0; a < editParts.size(); a++) {
			// we are only interested in nodes and containers
			if (editParts.get(a) instanceof NodeEditPart
					|| editParts.get(a) instanceof NodeContainerEditPart) {
				AbstractGraphicalEditPart ep = (AbstractGraphicalEditPart) editParts
						.get(a);
				if (firstPart == null) {
					firstPart = ep;
				}
				// sum the x coordinates of each element
				xsum += ep.getFigure().getBounds().x;
				// remember how many selected elements applied to this operation
				total++;
			}
		}
		// calculate the average x-value for all nodes
		int xave = (int) ((double) xsum / (double) total);
		// loop through all the nodes again and set them
		for (int a = 0; a < editParts.size(); a++) {
			if (editParts.get(a) instanceof NodeEditPart
					|| editParts.get(a) instanceof NodeContainerEditPart) {
				AbstractGraphicalEditPart ep = (AbstractGraphicalEditPart) editParts
						.get(a);
				// calculate the offset for centerline alignment
				Rectangle bounds = ep.getFigure().getBounds();
				int offset = (int) ((double) (bounds.width - firstPart
						.getFigure().getBounds().width) / 2.0);
				// are we inside a container?
				if (!(ep.getParent() instanceof DiagramEditPart)) {
					// adjust the offset since we have to move the container
					ep = (AbstractGraphicalEditPart) ep.getParent();
					Rectangle parentBounds = ep.getFigure().getBounds();
					offset += bounds.x - parentBounds.x;
					bounds = parentBounds;
				}
				// send the command to move the element
				org.eclipse.gef.commands.Command c = new ChangeBoundsCommand(
						(Node) ep.getModel(),
						new Point(xave - offset, bounds.y), bounds.width);
				getCommandStack().execute(c);
			}
		}

	}
	/** 
	 * Action implementation method for verticalAlignToFirstSelectedAction.
	 * 
	 */

	public void verticalAlignToFirstSelected() {
		// get the selected items
		List editParts = getGraphicalViewer().getSelectedEditParts();
		AbstractGraphicalEditPart alignToPart = null;
		// find the first diagram part we can align to
		for (int a = 0; a < editParts.size(); a++) {
			if (editParts.get(a) instanceof NodeEditPart
					|| editParts.get(a) instanceof NodeContainerEditPart) {
				AbstractGraphicalEditPart ep = (AbstractGraphicalEditPart) editParts
						.get(a);
				if (alignToPart == null) {
					// remember it and stop
					alignToPart = ep;
					break;
				}
			}
		}
		// loop through the elements and set their new position
		for (int a = 0; a < editParts.size(); a++) {
			if (editParts.get(a) instanceof NodeEditPart
					|| editParts.get(a) instanceof NodeContainerEditPart) {
				AbstractGraphicalEditPart ep = (AbstractGraphicalEditPart) editParts
						.get(a);
				// we can skip the first one since this is an align-to
				if (ep != alignToPart
						&& !(alignToPart instanceof SynchBarNodeEditPart)) {
					// calculate the offset for centerline alignment
					if (!(ep instanceof SynchBarNodeEditPart)) {
						Rectangle bounds = ep.getFigure().getBounds();
						int offset = (int) ((double) (bounds.width - alignToPart
								.getFigure().getBounds().width) / 2.0);
						// is this inside a container?
						if (!(ep.getParent() instanceof DiagramEditPart)) {
							// adjust the offset since we are moving the
							// container
							ep = (AbstractGraphicalEditPart) ep.getParent();
							Rectangle parentBounds = ep.getFigure().getBounds();
							offset += bounds.x - parentBounds.x;
							bounds = parentBounds;
						}
						// send the command to move the element
						org.eclipse.gef.commands.Command c = new ChangeBoundsCommand(
								(Node) ep.getModel(), new Point(alignToPart
										.getFigure().getBounds().x
										- offset, bounds.y), bounds.width);
						getCommandStack().execute(c);
						ep.getFigure().setLocation(
								new Point(alignToPart.getFigure().getBounds().x
										- offset, bounds.y));
					} else {
						Point tp = ep.getFigure().getBounds().getLocation();
						boolean connected = false;
						boolean source = false;
						Point endPoint = null;
						LinkEditPart lp = null;
						// check target connections
						List list = ((NodeEditPart) ep).getTargetConnections();
						for (Iterator itor = list.iterator(); itor.hasNext();) {
							lp = (LinkEditPart) itor.next();
							if (lp.getSource().equals(alignToPart)) {
								endPoint = ((Link) lp.getModel())
										.getTargetEndPoint();
								tp = tp.getTranslated(endPoint);
								connected = true;
								break;
							}
						}
						// check source connections if not found in target connections
						if (!connected) {
							list = ((NodeEditPart) ep).getSourceConnections();
							for (Iterator itor = list.iterator(); itor
									.hasNext();) {
								lp = (LinkEditPart) itor.next();
								if (lp.getTarget().equals(alignToPart)) {
									endPoint = ((Link) lp.getModel())
											.getSourceEndPoint();
									tp = tp.getTranslated(endPoint);
									connected = true;
									source = true;
									break;
								}
							}
						}
						if (connected && (alignToPart instanceof NodeEditPart)) {
									Point centerPoint = alignToPart.getFigure()
											.getBounds().getCenter();
									int delta = centerPoint.x - tp.x;
							endPoint.x += delta;
									ReconnectLinkCommand c = new ReconnectLinkCommand(
									(Link) lp.getModel(), (Node) ep.getModel(),
									source);
							c.setEndPoint(endPoint);
									getCommandStack().execute(c);
						}

					}
				}
				// If first selected edit part is syncbarnodeeditpart, need to
				// handle differently
				if (ep != alignToPart
						&& (alignToPart instanceof SynchBarNodeEditPart)) {

					Point sp = alignToPart.getFigure().getBounds()
							.getLocation();
					boolean connected = false;
					// check if the part is connected via source connections
					List list = ((NodeEditPart) alignToPart)
							.getSourceConnections();
					for (Iterator itor = list.iterator(); itor.hasNext();) {
						LinkEditPart lp = (LinkEditPart) itor.next();
						if (lp.getTarget().equals(ep)) {
							Point sourceEndPoint = ((Link) lp.getModel())
									.getSourceEndPoint();
							sp = sp.getTranslated(sourceEndPoint);
							connected = true;
							break;
						}
					}
					// if not found above, check if it is connected via target connections
					if (!connected) {
						list = ((NodeEditPart) alignToPart)
								.getTargetConnections();
						for (Iterator itor = list.iterator(); itor.hasNext();) {
							LinkEditPart lp = (LinkEditPart) itor.next();
							if (lp.getSource().equals(ep)) {
								Point targetEndPoint = ((Link) lp.getModel())
										.getTargetEndPoint();
								sp = sp.getTranslated(targetEndPoint);
								connected = true;
								break;
							}
						}
					}
					if (ep instanceof SynchBarNodeEditPart) {
						Point tp = ((Node) ep.getModel()).getLocation()
								.getCopy();
						Point alignToCenter = alignToPart.getFigure().getBounds().getCenter();
						Point centerPoint = ep.getFigure().getBounds().getCenter();
						int delta = alignToCenter.x - centerPoint.x;
						tp.x = tp.x + delta;
						org.eclipse.gef.commands.Command c = new ChangeBoundsCommand(
								(Node) ep.getModel(), tp, ep.getFigure()
										.getBounds().width);
						getCommandStack().execute(c);
						ep.getFigure().setLocation(new Point(tp.x, tp.y));
					} else if (ep instanceof NodeEditPart) {
						Point tp = ((Node) ep.getModel()).getLocation()
								.getCopy();
						Point centerPoint = ep.getFigure().getBounds()
								.getCenter();
						int delta = sp.x - centerPoint.x;
						tp.x = tp.x + delta;
						org.eclipse.gef.commands.Command c = new ChangeBoundsCommand(
								(Node) ep.getModel(), tp, ep.getFigure()
										.getBounds().width);
						getCommandStack().execute(c);
						ep.getFigure().setLocation(new Point(tp.x, tp.y));
					}
				}
			}
		}
	}

}
