//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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.diagram.core.commands;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.command.CopyCommand.Helper;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.epf.common.CommonPlugin;
import org.eclipse.epf.diagram.core.DiagramCorePlugin;
import org.eclipse.epf.diagram.core.part.DiagramEditorInput;
import org.eclipse.epf.diagram.core.part.DiagramEditorInputProxy;
import org.eclipse.epf.library.LibraryServiceUtil;
import org.eclipse.epf.library.edit.command.DeleteMethodElementCommand;
import org.eclipse.epf.library.edit.command.INestedCommandProvider;
import org.eclipse.epf.library.edit.command.MethodElementAddCommand;
import org.eclipse.epf.library.edit.command.ResourceAwareCompoundCommand;
import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.process.command.ActivityDropCommand;
import org.eclipse.epf.library.edit.process.command.CopyHelper;
import org.eclipse.epf.library.edit.process.command.ProcessDeepCopyCommand;
import org.eclipse.epf.library.edit.ui.IActionTypeProvider;
import org.eclipse.epf.library.edit.util.ActivityHandler;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.edit.domain.TraceableAdapterFactoryEditingDomain;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;

/**
 * @author Shilpa Toraskar
 * @author Phong Nguyen Le
 * @since 1.2
 */
public class NestedCommandProvider implements INestedCommandProvider {

	private static final boolean DEBUG = DiagramCorePlugin.getDefault()
			.isDebugging();

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.library.edit.command.INestedCommandProvider#createNestedCommand(org.eclipse.emf.common.command.Command)
	 */
	public Command createNestedCommand(Command command) {
		if (command instanceof ActivityDropCommand) {
			ActivityDropCommand cmd = (ActivityDropCommand) command;
			if (IActionTypeProvider.COPY == cmd.getType())
				return createNestedCommandForCopy(cmd);
			else if (IActionTypeProvider.DEEP_COPY == cmd.getType())
				return createNestedCommandForDeepCopy(cmd);
		}
		else if (command instanceof ProcessDeepCopyCommand) {
			ProcessDeepCopyCommand cmd = (ProcessDeepCopyCommand) command;
			Process deepCopy = null;
			Collection<?> result = cmd.getResult();
			if(!result.isEmpty()) {
				deepCopy = (Process) result.iterator().next();
			}
			if(deepCopy != null) {
				Collection<Activity> deepCopies = new ArrayList<Activity>();
				deepCopies.add(deepCopy);
				return createNestedCommandForDeepCopy(deepCopies, cmd.getTargetProcess(), 
						cmd.getCopyHelper(), cmd.getMethodConfiguration(), true);
			}
		}
		return null;
	}

	/**
	 * Create nested command for Drag & Drop Copy
	 * 
	 * @param command
	 * @return
	 */
	private Command createNestedCommandForCopy(ActivityDropCommand command) {
		Collection<Resource> modifiedResources = ((ActivityDropCommand) command).getModifiedResources(); 
		if (modifiedResources != null && !modifiedResources.isEmpty()) {
			CompoundCommand cmd = new ResourceAwareCompoundCommand(
					CompoundCommand.MERGE_COMMAND_ALL);

			Helper copiedHelper = command.getActivityHandler().getCopyHelper();
			Activity targetActivity = command.getActivity();
			Process targetProc = TngUtil.getOwningProcess(targetActivity);
			if (targetProc != null) {
				try {
					cmd.append(new CopyDiagramCommand(copiedHelper.values(),
							copiedHelper, targetProc));
				
				} catch (Exception ex) {
					CommonPlugin.getDefault().getLogger().logError(ex);
					if (DEBUG) {
						ex.printStackTrace();
					}
				} finally {
	
				}
			}
			if (!cmd.isEmpty()) {
				return cmd;
			}
		}
		return null;
	}
	
	/**
	 * Created nested command for Drag and Drop Deep copy
	 * 
	 * @param command
	 * @return
	 */
	private Command createNestedCommandForDeepCopy(ActivityDropCommand command) {
		ActivityHandler activityHandler = ((ActivityDropCommand) command)
				.getActivityHandler();
		if (activityHandler != null
				&& !activityHandler.getDeepCopies().isEmpty()) {
			return createNestedCommandForDeepCopy(activityHandler
					.getDeepCopies(), activityHandler.getTargetProcess(),
					activityHandler.getDeepCopyHelper(), activityHandler.getDeepCopyConfig(), false);
		}
		return null;
	}
	
	private Command createNestedCommandForDeepCopy(
			Collection<Activity> deepCopies, final Process targetProc,
			CopyHelper copyHelper, MethodConfiguration config,
			boolean saveDiagram) {
		CompoundCommand cmd;
		if (saveDiagram) {
			cmd = new ResourceAwareCompoundCommand(
					CompoundCommand.MERGE_COMMAND_ALL) {
				@Override
				public void execute() {
					super.execute();

					// save diagram file
					//
					if (org.eclipse.epf.diagram.core.services.DiagramManager
							.hasDiagramManager(targetProc)) {
						org.eclipse.epf.diagram.core.services.DiagramManager mgr = org.eclipse.epf.diagram.core.services.DiagramManager
								.getInstance(targetProc, this);
						ILibraryPersister.FailSafeMethodLibraryPersister persister = LibraryServiceUtil
								.getPersisterFor(targetProc.eResource())
								.getFailSafePersister();
						try {
							Resource resource = mgr.getResource();
							persister.save(resource);
							persister.commit();
						} catch (Exception e) {
							DiagramCorePlugin.getDefault().getLogger()
									.logError(e);
							try {
								persister.rollback();
							} catch (Exception ex) {
								DiagramCorePlugin.getDefault().getLogger()
										.logError(ex);
							}
						} finally {
							mgr.removeConsumer(this);
						}
					}
				}
			};
		} else {
			cmd = new ResourceAwareCompoundCommand(
					CompoundCommand.MERGE_COMMAND_ALL);
		}
		for (Activity copyAct : deepCopies) {
			Activity origAct = (Activity) copyHelper.getOriginal(copyAct);
			Process srcProc = TngUtil.getOwningProcess(origAct);
			Map<Activity, Activity> copyToOriginalMap = new HashMap<Activity, Activity>();
			Iterator<BreakdownElement> copyTree = new AbstractTreeIterator<BreakdownElement>(
					copyAct) {

				@Override
				protected Iterator<? extends BreakdownElement> getChildren(
						Object object) {
					if (object instanceof Activity) {
						return ((Activity) object).getBreakdownElements()
								.iterator();
					}
					return Collections.EMPTY_LIST.iterator();
				}

			};
			while (copyTree.hasNext()) {
				BreakdownElement e = copyTree.next();
				if (e instanceof Activity) {
					Object orig = copyHelper.getOriginal(e);
					if (orig == null) {
						System.out
								.println("NestedCommandProvider.createNestedCommandForDeepCopy(): FATAL ERROR: could not find source activity of deep copy: " + e); //$NON-NLS-1$
					} else {
						copyToOriginalMap.put((Activity) e, (Activity) orig);
					}
				}
			}
			cmd.append(new CopyDiagramForDeepCopyCommand(copyToOriginalMap.keySet(),
					copyToOriginalMap, srcProc, targetProc, copyHelper, config));
		}
		return !cmd.isEmpty() ? cmd : null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.library.edit.command.INestedCommandProvider#createRelatedObjects(java.util.Collection,
	 *      org.eclipse.emf.common.command.Command)
	 */
	public Command createRelatedObjects(Collection createdElements,
			Command createCommand) {

		CompoundCommand cmd = new ResourceAwareCompoundCommand(
				CompoundCommand.MERGE_COMMAND_ALL);
		if (createCommand instanceof MethodElementAddCommand) {

			MethodElementAddCommand meCommand = ((MethodElementAddCommand) createCommand);
			Command addCommand = meCommand.getCommand();
			if (addCommand instanceof AddCommand) {
				EditingDomain ed = ((AddCommand) addCommand).getDomain();
				
				if (((AddCommand)addCommand).getOwner() instanceof ProcessPackage) {
					if (ed instanceof TraceableAdapterFactoryEditingDomain) {
						Map copyToOriginalMap = ((TraceableAdapterFactoryEditingDomain) ed)
								.getCopyToOriginalMap();
						if (!copyToOriginalMap.isEmpty()) {
							Collection affects = meCommand.getAffectedObjects();
							for (Iterator iter = affects.iterator(); iter
									.hasNext();) {
								MethodElement element = (MethodElement) iter
										.next();
								if (element instanceof ProcessComponent) {
									cmd.append(new CopyDiagramCommand(
											copyToOriginalMap.keySet(),
											copyToOriginalMap,
											((ProcessComponent) element)
													.getProcess()));
								}
							}
						}
					}
				} else {
					// Copy/paste within the process editor
					if (ed instanceof TraceableAdapterFactoryEditingDomain) {
						Map originalToCopyMap = ((TraceableAdapterFactoryEditingDomain) ed)
								.getOriginalToClipboardMap();
						Map copyToOriginalMap = new HashMap();
						Object owner = ((AddCommand) addCommand).getOwner();
						Process targetProc = TngUtil.getOwningProcess(owner);
						if (targetProc != null) {
							for (Iterator iter = originalToCopyMap.keySet()
									.iterator(); iter.hasNext();) {
								Object key = iter.next();
								Object val = originalToCopyMap.get(key);
	
								copyToOriginalMap.put(val, key);
							}
	
							cmd.append(new CopyDiagramCommand(copyToOriginalMap.keySet(),
									copyToOriginalMap, targetProc));
						}
					}
				}
			}
		}
		if (!cmd.isEmpty()) {
			return cmd;
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.library.edit.command.INestedCommandProvider#removeRelatedObjects(java.util.Collection,
	 *      org.eclipse.emf.common.command.Command)
	 */
	public Command removeRelatedObjects(Collection deletedElements,
			Command deleteCommand) {
		CompoundCommand cmd = new ResourceAwareCompoundCommand(
				CompoundCommand.MERGE_COMMAND_ALL);
		if(deleteCommand instanceof DeleteMethodElementCommand){
			Command removeCommand = ((DeleteMethodElementCommand)deleteCommand).getCommand();
			List<RemoveCommand> removeCommands = null;
			if(removeCommand instanceof RemoveCommand){
				removeCommands = Collections.singletonList((RemoveCommand)removeCommand);
			}
			else if(removeCommand instanceof CompoundCommand) {
				removeCommands = new ArrayList<RemoveCommand>();
				for (Command command : ((CompoundCommand)removeCommand).getCommandList()) {
					if(command instanceof RemoveCommand) {
						removeCommands.add((RemoveCommand) command);
					}
				}
			}
			if(removeCommands != null && !removeCommands.isEmpty()) {
				Object owner = removeCommands.get(0).getOwner();
				if(owner instanceof Activity) {
					Process process = TngUtil.getOwningProcess((Activity)owner);
					Collection<Activity> allElements = new HashSet<Activity>();
					for (Iterator iter = deletedElements.iterator(); iter
					.hasNext();) {
						Object element = iter.next();
						if (element instanceof Activity) {
							Iterator iterator = new AbstractTreeIterator<Object>(element) {

								private static final long serialVersionUID = 1L;

								@Override
								protected Iterator<? extends Object> getChildren(
										Object object) {
									if(object instanceof Activity) {
										return ((Activity)object).getBreakdownElements().iterator();
									}
									else {
										return Collections.emptyList().iterator();
									}
								}

							};
							while(iterator.hasNext()) {
								Object e = iterator.next();
								if(e instanceof Activity) {
									allElements.add((Activity) e);
								}
							}
						} 
					}					
					if(!allElements.isEmpty()){
						cmd.append(new DeleteDiagramCommand(allElements, process));
					}

					for (RemoveCommand command : removeCommands) {
						if(command.getOwner() instanceof Activity) {
							DeleteDiagramNodeCommand deleteDiagramNodeCommand = new DeleteDiagramNodeCommand(
									(Activity) command.getOwner(), command.getCollection());
							if(deleteDiagramNodeCommand.canExecute()) {
								cmd.append(deleteDiagramNodeCommand);
							}
						}
					}
				}
			}
		}
		if(!deletedElements.isEmpty()){
			for (Iterator iter = deletedElements.iterator(); iter.hasNext();) {
				Object element = (Object) iter.next();
				closeDiagramEditors(element);
			}
		}
		if(!cmd.isEmpty()){
			return cmd;
		}
		return null;
	}
	
	/**
	 * Closes Diagram Editors if the owning process is deleted.
	 * @param process
	 */
	private void closeDiagramEditors(Object e) {
		IWorkbenchPage workbenchPage = PlatformUI.getWorkbench()
				.getActiveWorkbenchWindow().getActivePage();
		IEditorReference[] editorReferences = workbenchPage
				.getEditorReferences();
		ArrayList<IEditorReference> editorsToClose = new ArrayList<IEditorReference>();
		for (int i = 0; i < editorReferences.length; i++) {
			IEditorReference editorRef = editorReferences[i];
			IEditorInput editorInput;
			try {
				editorInput = editorRef.getEditorInput();
				if (editorInput instanceof DiagramEditorInputProxy) {
					DiagramEditorInput input = ((DiagramEditorInputProxy) editorInput)
							.getDiagramEditorInput();
					Object wrapper = input.getWrapper();
					Process owningProcess = null;
					if (wrapper != null) {
						if (wrapper instanceof BreakdownElementWrapperItemProvider) {
							owningProcess = TngUtil
									.getOwningProcess(((BreakdownElementWrapperItemProvider) wrapper));
						}
					} else {
						wrapper = input.getMethodElement();
						if (wrapper instanceof BreakdownElement) {
							owningProcess = TngUtil
									.getOwningProcess(((BreakdownElement) wrapper));
						}
					}
					if (owningProcess != null ) {
						if (e == owningProcess)
							editorsToClose.add(editorRef);
						if ((owningProcess.eContainer() == null || UmaUtil
									.isContainedBy(owningProcess, e))) {
							editorsToClose.add(editorRef);
						}
					}
				}
			} catch (PartInitException ex) {
				DiagramCorePlugin.getDefault().getLogger().logError(ex);
			}
		}
		if(!editorsToClose.isEmpty()) {
			IEditorReference[] refs = new IEditorReference[editorsToClose.size()];
			editorsToClose.toArray(refs);
			workbenchPage.closeEditors(refs, false);
		}
	}
}
