//------------------------------------------------------------------------------
// 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.library.edit.process.command;

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.ListIterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.epf.library.edit.IConfigurator;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.Providers;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.command.BatchCommand;
import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.util.Messenger;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.Deliverable;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.TeamProfile;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;


/**
 * Command for one-way synchronization from method to process.
 * 
 * @author Phong Nguyen Le - Nov 22, 2005
 * @since 1.0
 */
public class SynchronizeCommand extends CompoundCommand implements
		IResourceAwareCommand {

	private Collection elements;

	private IConfigurator configurator;

	protected boolean aborted;

	private ArrayList deleteList;

	protected boolean preExecSuccessful;

	protected List deleteCommandList;

	protected boolean successful;

	private MethodConfiguration config;

	private Set synchFeatures;

	private DeleteUnusedDescriptorsCommand deleteUnusedDescriptorsCommand;
	
	private Collection activities;

	private boolean showSuccessfulMsg = true;

	private boolean intialized;
	
	private BatchCommand batchCommand = new BatchCommand(false);
	private Map<VariabilityElement, VariabilityElement> replacerToBaseMap = new HashMap<VariabilityElement, VariabilityElement>();  

//	private Object UIContext;

	/**
	 * Constructs a SynchronizeCommand that use the process default
	 * configuration to synchronize all the synchronizable features
	 * 
	 * @param elements
	 *            a list of BreakdownElement objects
	 */
	public SynchronizeCommand(String label, Collection elements) {
		super(label);
		this.elements = elements;
	}
	
	/**
	 * Constructs a SynchronizeCommand that use the given configuration 
	 * and list of synchronizable features to synchronize
	 * 
	 * @param elements
	 * @param config the configuration
	 * @param synchFeatures the synchronizable features
	 */
	public SynchronizeCommand(Collection elements, MethodConfiguration config, Set synchFeatures, boolean showSuccessfulMsg) {
		super(LibraryEditResources.AutoSynchronizeCommand_label); 
		this.elements = elements;
		this.config = config;
		this.synchFeatures = synchFeatures;
		this.showSuccessfulMsg = showSuccessfulMsg; 
	}
	
	public void setMethodConfiguration(MethodConfiguration config) {
		this.config = config;
		if(configurator != null) {
			configurator.setMethodConfiguration(config);
		}
	}
	
	public void setSynchronizationFeatures(Set synchFeatures) {
		this.synchFeatures = synchFeatures;
	}
	
	private boolean doInitialize() {
		commandList.clear();
		
		if (elements == null || elements.isEmpty()) {
			return false;
		}

		deleteCommandList = new ArrayList();
		deleteList = new ArrayList();
		activities = new ArrayList();
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object element = (Object) iter.next();
			addToDeleteList(element, deleteList);
			if(element instanceof Activity) {
				activities.add(element);
			}
		}
		elements.removeAll(deleteList);
		
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object object = iter.next();
			if (object instanceof Descriptor) {
				Descriptor descriptor = (Descriptor) object;
				if (descriptor.getIsSynchronizedWithSource().booleanValue()
						&& !deleteList.contains(descriptor)) {
					if(descriptor.getSuperActivities() == null) {						
						// descriptor is used by TeamProfile to represent a role or used by a deliverable descriptor to
						// represent a deliverable part
						//
						if(descriptor instanceof WorkProductDescriptor && ((WorkProductDescriptor)descriptor).getWorkProduct() instanceof Deliverable) {
							append(new SynchronizeDeliverableDescriptorCommand((WorkProductDescriptor) descriptor, synchFeatures, config));
						}
						else {
							append(new BasicSynchronizeDescriptorCommand(descriptor, synchFeatures, config));
						}
					}
					else {
						Activity act = descriptor.getSuperActivities();
						if (object instanceof TaskDescriptor) {
							Task task = ((TaskDescriptor) object).getTask();
							if (task != null) {
								if(replacerToBaseMap.containsKey(task)) {
									task = (Task) replacerToBaseMap.get(task);
								}
								append(new WBSDropCommand(act, Collections
										.singletonList(task), config, synchFeatures));
							}
						} else if (object instanceof RoleDescriptor) {
							Role role = ((RoleDescriptor) object).getRole();
							if (role != null) {
								if(replacerToBaseMap.containsKey(role)) {
									role = (Role) replacerToBaseMap.get(role);
								}
								append(new OBSDropCommand(act, Collections
										.singletonList(role), config, synchFeatures, configurator));
							}
						} else if (object instanceof WorkProductDescriptor) {
							WorkProduct wp = ((WorkProductDescriptor) object)
							.getWorkProduct();
							if (wp != null) {
								if(replacerToBaseMap.containsKey(wp)) {
									wp = (WorkProduct) replacerToBaseMap.get(wp);
								}
								append(new PBSDropCommand(act, Collections
										.singletonList(wp), config, synchFeatures, configurator));
							}
						}
					}
				}
			} else if (object instanceof Activity) {
				appendCommands((Activity) object);
			} else if (object instanceof TeamProfile) {
				appendCommands((TeamProfile)object);
			}
		}
		return !deleteList.isEmpty() || !commandList.isEmpty() || !activities.isEmpty();
	}

	public boolean initilize() {
		boolean b = isPrepared;
		try {
			// since Eclipse 3.3, CompoundCommand.append() throws IllegalStateException if isPrepared is already set
			// but this method is called after isPrepared is set in canExecute() and it makes many calls to append()
			// work-around is to unset isPrepared at beginning of this method and set it back to old value at method end.
			//
			isPrepared = false;
			return intialized = doInitialize();		
		}
		finally {
			isPrepared = b;
		}
	}
	
	/**
	 * @return the intialized
	 */
	public boolean isIntialized() {
		return intialized;
	}

	/**
	 * @param activity
	 */
	private void appendCommands(Activity activity) {
		List tasks = new ArrayList();
		List roles = new ArrayList();
		List workProducts = new ArrayList();
		List activities = new ArrayList();
		for (Iterator iter = activity.getBreakdownElements().iterator(); iter
				.hasNext();) {
			Object element = iter.next();
			if (element instanceof Descriptor) {
				if (((Descriptor) element).getIsSynchronizedWithSource()
						.booleanValue()
						&& !deleteList.contains(element)) {
					if (element instanceof TaskDescriptor) {
						Task task = ((TaskDescriptor) element).getTask();
						if (task != null) {
							if(replacerToBaseMap.containsKey(task)) {
								task = (Task) replacerToBaseMap.get(task);
							}
							tasks.add(task);
						}
					} else if (element instanceof RoleDescriptor) {
						Role role = ((RoleDescriptor) element).getRole();
						if (role != null) {
							if(replacerToBaseMap.containsKey(role)) {
								role = (Role) replacerToBaseMap.get(role);
							}
							roles.add(role);
						}
					} else if (element instanceof WorkProductDescriptor) {
						WorkProduct wp = ((WorkProductDescriptor) element)
								.getWorkProduct();
						if (wp != null) {
							if(replacerToBaseMap.containsKey(wp)) {
								wp = (WorkProduct) replacerToBaseMap.get(wp);
							}
							workProducts.add(wp);
						}
					}
				}
			} else if (element instanceof Activity) {
				activities.add(element);
			} else if (element instanceof TeamProfile) {
				appendCommands((TeamProfile)element);
			}
		}
		if (!tasks.isEmpty()) {
			append(new WBSDropCommand(activity, tasks, config, synchFeatures));
		}
		if (!roles.isEmpty()) {
			append(new OBSDropCommand(activity, roles, config, synchFeatures, configurator));
		}
		if (!workProducts.isEmpty()) {
			append(new PBSDropCommand(activity, workProducts, config,
					synchFeatures, configurator));
		}
		for (Iterator iter = activities.iterator(); iter.hasNext();) {
			appendCommands((Activity) iter.next());
		}
	}
	
	private void appendCommands(TeamProfile team) {
		Iterator iter = new AbstractTreeIterator(team, false) {

			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			protected Iterator getChildren(Object object) {
				if(object instanceof TeamProfile) {
					TeamProfile team = ((TeamProfile)object);
					List children = new ArrayList(team.getSubTeam());
					children.addAll(team.getTeamRoles());
					return children.iterator();
				}
				else {
					return Collections.EMPTY_LIST.iterator();
				}
			}
			
		};
		while(iter.hasNext()) {
			Object obj = iter.next();
			
			// synch only own role descriptor of team profile
			//
			if(obj instanceof RoleDescriptor && ((RoleDescriptor)obj).getSuperActivities() == null) {
				append(new BasicSynchronizeDescriptorCommand((Descriptor) obj, synchFeatures, config));
			}
		}
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.command.IResourceAwareCommand#getModifiedResources()
	 */
	public Collection getModifiedResources() {
		HashSet modifiedResources = new HashSet();
		for (Iterator iter = commandList.iterator(); iter.hasNext();) {
			
			Object cmd = iter.next();
			if(cmd instanceof IResourceAwareCommand) {
				modifiedResources.addAll(((IResourceAwareCommand)cmd).getModifiedResources());
			}
		}
		return modifiedResources;
	}
	
//	public void setUIContext(Object UIContext) {
//		this.UIContext = UIContext;
//	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.CompoundCommand#execute()
	 */
	public void execute() {
		// delete all descriptors whose linked element are no longer in the
		// configuration
		//
		if (!deleteList.isEmpty()) {
			Command cmd = delete(deleteList);
			if (cmd != null) {
				deleteCommandList.add(cmd);
			}
		}
		
		batchCommand.execute();
		
		if (!aborted) {
//			IRunnableWithProgress runnable = new IRunnableWithProgress() {
//
//				public void run(IProgressMonitor monitor)
//						throws InvocationTargetException, InterruptedException {
//					preExecSuccessful = preExecute();
//				}
//
//			};
//						
//			UserInteractionHelper.runWithProgress(runnable, false, null);
//
//			if (preExecSuccessful) {
//				try {
//					BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
//						
//						public void run() {
//							superRedo();
//							successful = true;
//						}
//						
//					});
//				}
//				catch(RuntimeException e) {
//					LibraryEditPlugin.getDefault().getMsgDialog().displayError(getLabel(), e.toString());
//				}
//			}
			
			Runnable runnable = new Runnable() {

				public void run() {
					preExecSuccessful = preExecute();
					if(preExecute()) {
						superRedo();
						successful = true;
					}
				}

			};
			UserInteractionHelper.runInUI(runnable, getLabel());
			
			if (successful) {				
				if(!activities.isEmpty()) {
					if(deleteUnusedDescriptorsCommand == null) {
						deleteUnusedDescriptorsCommand = new DeleteUnusedDescriptorsCommand(elements, true, deleteList) {
							
							protected Command delete(List elements) {
								return SynchronizeCommand.this.delete(elements);
							}
							
						};
						deleteCommandList.add(deleteUnusedDescriptorsCommand);
					}
					deleteUnusedDescriptorsCommand.execute();
				}
				
				if (showSuccessfulMsg) {
					if(!replacerToBaseMap.isEmpty()) {
						refreshViewer();
					}
					Messenger.INSTANCE.showInfo(
									LibraryEditResources.SynchronizeCompleteDialog_Title,
									LibraryEditResources.AutoSynchronizeCommand_sucessful);
				}
			}
		}
	}

	private void refreshViewer() {
		if(elements.isEmpty())  return;
		Process proc = TngUtil.getOwningProcess(elements.iterator().next());
		if(proc != null) {
			for (int i = 0; i < TngAdapterFactory.processAdapterFactories.length; i++) {
				AdapterFactory adapterFactory = TngAdapterFactory.processAdapterFactories[i];
				ProcessUtil.refreshViewer(adapterFactory, proc);
			}
		}
	}

	private void superRedo() {
		super.redo();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.CompoundCommand#redo()
	 */
	public void redo() {
		execute();
	}

	public boolean isSucessful() {
		return successful;
	}

	protected boolean preExecute() {
		for (ListIterator commands = commandList.listIterator(); commands
				.hasNext();) {
			Object command = commands.next();
			if(command instanceof BSDropCommand && !((BSDropCommand)command).preExecute()) {
				return false;
			}
			
			// be polite to other threads (no effect on some platforms)
			//
			Thread.yield();
		}
		return true;
	}

	/**
	 * Deletes the specified elements
	 * @param elements
	 * @return the executed command that deleted the given elements
	 */
	protected Command delete(List elements) {
		EditingDomain domain = new AdapterFactoryEditingDomain(
				TngAdapterFactory.INSTANCE.getProcessComposedAdapterFactory(),
				new BasicCommandStack());
		Command cmd = new ProcessElementDeleteCommand(RemoveCommand.create(domain,
				elements), elements);
		cmd.execute();
		return cmd;
	}

	private IConfigurator getConfigurator() {
		if (configurator == null) {
			MethodConfiguration config = this.config;
			if(config == null) {
				Process proc = TngUtil.getOwningProcess((BreakdownElement) elements
						.iterator().next());
				config = proc.getDefaultContext();
			}
			configurator = Providers.getConfiguratorFactory()
					.createConfigurator(config);
		}
		return configurator;
	}

	/**
	 * @param element
	 * @param deleteList
	 */
	private void addToDeleteList(Object element, List deleteList) {
		if (element instanceof Descriptor) {
			if (!getConfigurator().accept(element)) {
				MethodElement linkedElement = ProcessUtil.getAssociatedElement((Descriptor) element);				
				if(linkedElement instanceof VariabilityElement && TngUtil.isReplacer((VariabilityElement) linkedElement)) {
					// if the linked element of the descriptor is a replacer, delete the descriptor in this synchronization
					// only if the base of linked element is not in the configuration
					//
					VariabilityElement base = ((VariabilityElement)linkedElement).getVariabilityBasedOnElement();
					while(base != null && TngUtil.isContributorOrReplacer(base)) {
						base = base.getVariabilityBasedOnElement();
					}
					if(base != null) {
						if(!getConfigurator().accept(base)) {
							deleteList.add(element);
						}
						else {
							batchCommand.addFeatureValue((EObject) element, 
									ProcessUtil.getLinkReference((Descriptor) element), base);
							replacerToBaseMap.put((VariabilityElement) linkedElement, base);
						}
					}
				}
				else {
					deleteList.add(element);
				}
			}
		} else if (element instanceof Activity) {
			for (Iterator iter = ((Activity) element).getBreakdownElements()
					.iterator(); iter.hasNext();) {
				addToDeleteList(iter.next(), deleteList);
			}
		}
	}

	private void superUndo() {
		super.undo();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.CompoundCommand#undo()
	 */
	public void undo() {
		BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {

			public void run() {
				if (!deleteCommandList.isEmpty()) {
					for (ListIterator commands = deleteCommandList
							.listIterator(deleteCommandList.size()); commands
							.hasPrevious();) {
						try {
							Command command = (Command) commands.previous();
							command.undo();
						} catch (RuntimeException exception) {
							// Skip over the command that threw the exception.
							//
							commands.next();

							try {
								// Iterate forward over the undone commands to
								// redo them.
								//
								while (commands.hasNext()) {
									Command command = (Command) commands.next();
									command.redo();
								}
							} catch (RuntimeException nestedException) {
								CommonPlugin.INSTANCE
										.log(new WrappedException(
												CommonPlugin.INSTANCE
														.getString("_UI_IgnoreException_exception"), nestedException).fillInStackTrace()); //$NON-NLS-1$
							}

							throw exception;
						}
					}
				}

				superUndo();
				
				batchCommand.undo();
			}

		});
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.CompoundCommand#prepare()
	 */
	protected boolean prepare() {
		return true;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.emf.common.command.CompoundCommand#dispose()
	 */
	public void dispose() {
		if(activities != null) {
			activities.clear();
		}
		if(deleteCommandList != null) {
			for (Iterator iter = deleteCommandList.iterator(); iter.hasNext();) {
				Command cmd = (Command) iter.next();
				cmd.dispose();
			}
		}
		if(deleteList != null) {
			deleteList.clear();
		}
		
		super.dispose();
	}
}
