/******************************************************************************
 * 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 API and implementation 
 ****************************************************************************/

package org.eclipse.gmf.runtime.diagram.ui.commands;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.util.ObjectAdapter;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.internal.commands.ElementTypeLabelProvider;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.diagram.ui.menus.PopupMenu;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateUnspecifiedTypeConnectionRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequestFactory;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest;
import org.eclipse.gmf.runtime.emf.ui.services.modelingassistant.ModelingAssistantService;
import org.eclipse.gmf.runtime.emf.ui.services.modelingassistant.SelectExistingElementForSourceOperation;
import org.eclipse.gmf.runtime.emf.ui.services.modelingassistant.SelectExistingElementForTargetOperation;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;

/**
 * <p>
 * A command that pops up a menu which can allow the user to select the type of
 * connection to be created and whether they want to create a new type or select
 * an existing element for the other end of the connection.
 * </p>
 * 
 * <p>
 * The <code>getRelationshipTypeAdapter()</code> method returns an adaptable
 * to the relationship type result.
 * </p>
 * 
 * <p>
 * The <code>getEndAdapter()</code> method returns an adaptable to the end
 * type result.
 * </p>
 * 
 * @author cmahoney
 */
public class PromptForConnectionAndEndCommand
	extends PopupMenuCommand {

	/**
	 * Label provider of the first popup menu with the relationship types.
	 */
	protected class ConnectionLabelProvider
		extends ElementTypeLabelProvider {

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
		 */
		public String getText(Object element) {
			String theInputStr = null;
			if (isDirectionReversed())
				theInputStr = DiagramUIMessages.ConnectionHandle_Popup_CreateXFrom;
			else
				theInputStr = DiagramUIMessages.ConnectionHandle_Popup_CreateXTo;

			String text = NLS.bind(theInputStr, super
				.getText(element));

			return text;

		}
	}

	/**
	 * Label provider of the second popup (submenus) for the type of the other
	 * end.
	 */
	protected class EndLabelProvider
		extends ElementTypeLabelProvider {

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
		 */
		public String getText(Object element) {
			if (element instanceof IElementType) {
				String theInputStr = DiagramUIMessages.ConnectionHandle_Popup_NewX;
				String text = NLS.bind(theInputStr,
					super.getText(element));
				return text;
			} else {
				return element.toString();
			}
		}
	}

	/**
	 * Label provider of the first and only popup for the type of the other end
	 * when there is only one connection type (e.g. a single relationship type
	 * palette tool is used).
	 */
	protected class ConnectionAndEndLabelProvider
		extends ElementTypeLabelProvider {

		/** the known connection item */
		private Object connectionItem;

		/**
		 * Creates a new <code>ConnectionAndEndLabelProvider</code>.
		 * 
		 * @param connectionType
		 *            the single known connection type
		 */
		protected ConnectionAndEndLabelProvider(Object connectionItem) {
			this.connectionItem = connectionItem;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
		 */
		public String getText(Object element) {
			String theInputStr = null;
			if (element instanceof IElementType) {
				if (isDirectionReversed())
					theInputStr = DiagramUIMessages.ConnectionHandle_Popup_CreateXFromNewY;
				else
					theInputStr = DiagramUIMessages.ConnectionHandle_Popup_CreateXToNewY;
				String text = NLS.bind(theInputStr, new Object[] {
					super.getText(connectionItem), super.getText(element)});
				return text;
			} else {
				if (isDirectionReversed())
					theInputStr = DiagramUIMessages.ConnectionHandle_Popup_CreateXFromY;
				else
					theInputStr = DiagramUIMessages.ConnectionHandle_Popup_CreateXToY;
				String text = NLS.bind(theInputStr, new Object[] {
					super.getText(connectionItem), super.getText(element)});
				return text;
			}
		}

		/**
		 * Gets the connection item.
		 * 
		 * @return the connection item
		 */
		protected Object getConnectionItem() {
			return connectionItem;
		}

	}

	/**
	 * This can be added to the content list to add a 'select existing' option.
	 */
	private static String EXISTING_ELEMENT = DiagramUIMessages.ConnectionHandle_Popup_ExistingElement;

	/** Label provider of the popup menu for the connection types. */
	private ConnectionLabelProvider connectionLabelProvider;

	/** Label provider of the submenus for the other end element. */
	private static EndLabelProvider endLabelProvider;

	/** Adapts to the connection type result. */
	private ObjectAdapter connectionAdapter = new ObjectAdapter();

	/** Adapts to the other end type result. */
	private ObjectAdapter endAdapter = new ObjectAdapter();

	/**
	 * The request to create a connection. It may contain the connection type or
	 * it may be a <code>CreateUnspecifiedTypeConnectionRequest</code>.
	 */
	private CreateConnectionRequest request;

	/** The container editpart to send the view request to. */
	private IGraphicalEditPart containerEP;

	/**
	 * Creates a new <code>PromptForConnectionAndEndCommand</code>.
	 * 
	 * @param request
	 *            The request to create a connection. It may contain the
	 *            connection type or it may be a
	 *            <code>CreateUnspecifiedTypeConnectionRequest</code>.
	 * @param containerEP
	 *            The container edit part, where the view and element request to
	 *            create the other end is sent. This is used only for testing
	 *            that a type is valid for the other end.
	 */
	public PromptForConnectionAndEndCommand(CreateConnectionRequest request,
			IGraphicalEditPart containerEP) {

		super(DiagramUIMessages.Command_GetRelationshipTypeAndEndFromUser_Label,
			Display.getCurrent().getActiveShell());
		this.request = request;
		this.containerEP = containerEP;
	}

	/**
	 * Gets a list of all the connection items that will represent the
	 * connection choices and will appear in the first part of the popup menu.
	 * 
	 * <p>
	 * If the objects in this are not <code>IElementTypes</code> or they
	 * require a special label provider, then
	 * {@link #getConnectionLabelProvider()} should be overridden to provide
	 * this.
	 * </p>
	 * <p>
	 * When this command has executed, the connection adapter result ({@link #getConnectionAdapter()})
	 * will be populated with the connection item chosen.
	 * </p>
	 * 
	 * @return the list of connection items to appear in the popup menu
	 */
	protected List getConnectionMenuContent() {
		List validRelTypes = new ArrayList();
		if (request instanceof CreateUnspecifiedTypeConnectionRequest) {
			List allRelTypes = null;
			if (((CreateUnspecifiedTypeConnectionRequest) request)
				.useModelingAssistantService()) {
				allRelTypes = isDirectionReversed() ? ModelingAssistantService
					.getInstance().getRelTypesOnTarget(getKnownEnd())
					: ModelingAssistantService.getInstance()
						.getRelTypesOnSource(getKnownEnd());
			} else {
				allRelTypes = ((CreateUnspecifiedTypeConnectionRequest) request)
					.getElementTypes();
			}

			if (isDirectionReversed()) {
				validRelTypes = allRelTypes;
			} else {
				// Cycle through and make sure each connection type is
				// supported
				// for starting a connection on the source.
				for (Iterator iter = allRelTypes.iterator(); iter.hasNext();) {
					IElementType rType = (IElementType) iter.next();
					if (((CreateConnectionRequest) ((CreateUnspecifiedTypeConnectionRequest) request)
						.getRequestForType(rType)).getStartCommand() != null) {
						validRelTypes.add(rType);
					}
				}
			}

		} else if (request instanceof CreateConnectionViewAndElementRequest) {
			if (((CreateConnectionViewAndElementRequest) request)
				.getStartCommand() != null) {
				validRelTypes
					.add(((CreateRelationshipRequest) ((CreateConnectionViewAndElementRequest) request)
						.getConnectionViewAndElementDescriptor()
						.getCreateElementRequestAdapter().getAdapter(
							CreateRelationshipRequest.class)).getElementType());
			}
		} else if (request instanceof CreateConnectionViewRequest) {
			if (((CreateConnectionViewRequest) request).getStartCommand() != null) {
				Object type = ((CreateConnectionViewRequest) request)
					.getConnectionViewDescriptor().getElementAdapter()
					.getAdapter(IElementType.class);
				if (type != null) {
					validRelTypes.add(type);
				}
			}
		}
		return validRelTypes;
	}

	/**
	 * Gets a list of all the end items that will represent the other end
	 * choices and will appear in the submenu popup of the given connection
	 * item.
	 * 
	 * <p>
	 * If the objects in this are not <code>IElementTypes</code> or they
	 * require a special label provider, then {@link #getEndLabelProvider()}
	 * should be overridden to provide this.
	 * </p>
	 * <p>
	 * When this command has executed, the end adapter result ({@link #getEndAdapter()})
	 * will be populated with the end item chosen.
	 * </p>
	 * 
	 * @param connectionItem
	 *            the connection item for which this will be a submenu
	 * @return the list of end items to appear in the popup menu
	 */
	protected List getEndMenuContent(Object connectionItem) {
		if (connectionItem instanceof IElementType) {
			IElementType connectionType = (IElementType) connectionItem;
			List menuContent = isDirectionReversed() ? ModelingAssistantService
				.getInstance().getTypesForSource(getKnownEnd(), connectionType)
				: ModelingAssistantService.getInstance().getTypesForTarget(
					getKnownEnd(), connectionType);

			menuContent = filterUnsupportedNodeTypes(menuContent);

			if (!menuContent.isEmpty()
				&& supportsExistingElement(connectionType)) {
				menuContent.add(EXISTING_ELEMENT);
			}

			return menuContent;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * Gets the content to be used in the popup menu from the Modeling Assistant
	 * Service and creates the popup menu.
	 * 
	 * @return the top-level popup menu
	 */
	protected PopupMenu createPopupMenu() {

		final List connectionMenuContent = getConnectionMenuContent();

		if (connectionMenuContent == null || connectionMenuContent.isEmpty()) {
			return null;
		} else if (connectionMenuContent.size() == 1) {
			List menuContent = getEndMenuContent(connectionMenuContent.get(0));
			if (menuContent == null || menuContent.isEmpty()) {
				return null;
			}

			ILabelProvider labelProvider = getConnectionAndEndLabelProvider(connectionMenuContent
				.get(0));
			return new PopupMenu(menuContent, labelProvider) {

				/**
				 * @see org.eclipse.gmf.runtime.diagram.ui.menus.PopupMenu#getResult()
				 */
				public Object getResult() {
					Object endResult = super.getResult();
					if (endResult == null) {
						return null;
					} else {
						List resultList = new ArrayList(2);
						resultList.add(connectionMenuContent.get(0));
						resultList.add(endResult);
						return resultList;
					}
				}
			};
		} else {
			List menuContent = new ArrayList();
			for (Iterator iter = connectionMenuContent.iterator(); iter
				.hasNext();) {
				Object connectionItem = iter.next();

				List subMenuContent = getEndMenuContent(connectionItem);

				if (subMenuContent.isEmpty()) {
					continue;
				}

				PopupMenu subMenu = new PopupMenu(subMenuContent,
					getEndLabelProvider());

				menuContent.add(new PopupMenu.CascadingMenu(connectionItem,
					subMenu));
			}
			if (!menuContent.isEmpty()) {
				return new PopupMenu(menuContent, getConnectionLabelProvider());
			}
		}
		return null;
	}

	/**
	 * Returns a new list with all the types from the list given that can be
	 * created.
	 * 
	 * @param allTypes
	 *            a list of <code>IElementTypes</code>.
	 */
	private List filterUnsupportedNodeTypes(List allTypes) {
		List validTypes = new ArrayList();
		for (Iterator iter = allTypes.iterator(); iter.hasNext();) {
			IElementType type = (IElementType) iter.next();
			Request createRequest = CreateViewRequestFactory
				.getCreateShapeRequest(type, containerEP
					.getDiagramPreferencesHint());

			EditPart target = containerEP.getTargetEditPart(createRequest);
			if (target != null) {
				Command cmd = target.getCommand(createRequest);
				if (cmd != null && cmd.canExecute()) {
					validTypes.add(type);
				}
			}
		}
		return validTypes;
	}

    public boolean canExecute() {
		return createPopupMenu() != null;
	}

	/**
	 * Pops up the dialog with the content provided. If the user selects 'select
	 * existing', then the select elements dialog also appears.
	 */
	protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor,
            IAdaptable info)
        throws ExecutionException {
        
		PopupMenu popup = createPopupMenu();

		if (popup == null) {
			return CommandResult.newErrorCommandResult(getLabel());
		}

		setPopupMenu(popup);

		CommandResult cmdResult = super.doExecuteWithResult(progressMonitor, info);
		if (!cmdResult.getStatus().isOK()) {
			return cmdResult;
		}

		Object result = cmdResult.getReturnValue();
		if (result instanceof List) {
			List resultList = (List) result;
			if (resultList.size() == 2) {
				connectionAdapter.setObject(resultList.get(0));

				Object targetResult = resultList.get(1);

				if (targetResult.equals(EXISTING_ELEMENT)) {
					targetResult = isDirectionReversed() ? ModelingAssistantService
						.getInstance().selectExistingElementForSource(
							getKnownEnd(), (IElementType) resultList.get(0))
						: ModelingAssistantService.getInstance()
							.selectExistingElementForTarget(getKnownEnd(),
								(IElementType) resultList.get(0));
					if (targetResult == null) {
						return CommandResult.newCancelledCommandResult();
					}
				}
				endAdapter.setObject(targetResult);
				return CommandResult.newOKCommandResult();
			}
		}
		return CommandResult.newErrorCommandResult(getLabel());
	}

	/**
	 * Checks if the <code>ModelingAssistantService</code> supports the
	 * ability to open a dialog for the user to select an existing element
	 * 
	 * @param connectionType
	 * @return true if the supported by the modeling assistant service; false
	 *         otherwise
	 */
	private boolean supportsExistingElement(IElementType connectionType) {
		if (isDirectionReversed()) {
			if (ModelingAssistantService.getInstance().provides(
				new SelectExistingElementForSourceOperation(getKnownEnd(),
					connectionType))) {
				return true;
			}
		} else if (ModelingAssistantService.getInstance().provides(
			new SelectExistingElementForTargetOperation(getKnownEnd(),
				connectionType))) {
			return true;
		}
		return false;
	}

	/**
	 * Gets the connectionAdapter.
	 * 
	 * @return Returns the connectionAdapter.
	 */
	public ObjectAdapter getConnectionAdapter() {
		return connectionAdapter;
	}

	/**
	 * Gets the endAdapter.
	 * 
	 * @return Returns the endAdapter.
	 */
	public IAdaptable getEndAdapter() {
		return endAdapter;
	}

	/**
	 * Returns true if the request is a reversed
	 * <code>CreateUnspecifiedTypeConnectionRequest</code>.
	 * 
	 * @return Returns true if the request is a reversed
	 *         <code>CreateUnspecifiedTypeConnectionRequest</code>; false
	 *         otherwise
	 */
	protected boolean isDirectionReversed() {
		return (request instanceof CreateUnspecifiedTypeConnectionRequest && ((CreateUnspecifiedTypeConnectionRequest) request)
			.isDirectionReversed());
	}

	/**
	 * Gets the known end, which even in the case of a reversed
	 * <code>CreateUnspecifiedTypeConnectionRequest</code>, is the source
	 * editpart.
	 * 
	 * @return the known end
	 */
	private EditPart getKnownEnd() {
		return request.getSourceEditPart();
	}

	/**
	 * Gets the label provider that is to be used in the first menu of the popup
	 * where the user is to choose the connection to be created.
	 * 
	 * @return the connection label provider
	 */
	protected ILabelProvider getConnectionLabelProvider() {
		if (connectionLabelProvider == null) {
			connectionLabelProvider = new ConnectionLabelProvider();
		}
		return connectionLabelProvider;
	}

	/**
	 * Gets the label provider that is to be used in the second menu of the
	 * popup where the user is to choose the end (could be source or target) to
	 * be created.
	 * 
	 * @return the end label provider
	 */
	protected ILabelProvider getEndLabelProvider() {
		if (endLabelProvider == null) {
			endLabelProvider = new EndLabelProvider();
		}
		return endLabelProvider;
	}

	/**
	 * Gets the label provider that is to be used when there is only one option
	 * for the connection type so the popup menu consists of a single menu
	 * identifying the connection type to be created and options for the other
	 * end of which the user must choose
	 * 
	 * @param connectionItem
	 *            the single known connection item
	 * @return the label provider
	 */
	protected ILabelProvider getConnectionAndEndLabelProvider(
			Object connectionItem) {
		return new ConnectionAndEndLabelProvider(connectionItem);
	}

}