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

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

import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.epf.library.edit.IConfigurator;
import org.eclipse.epf.library.edit.Providers;
import org.eclipse.epf.library.edit.command.BatchCommand;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.edit.validation.UniqueNamePNameHandler;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Artifact;
import org.eclipse.epf.uma.Deliverable;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;


/**
 * Command to drag and drop work products to Work Product Usage breakdown
 * structure
 * 
 * @author Phong Nguyen Le
 * @author Shilpa Toraskar
 * @since 1.0
 */
public class PBSDropCommand extends BSDropCommand {
	private ArrayList wpDescList;

	private ArrayList roleDescList;

	private Map wpDescToDeliverableParts;

	private HashMap<WorkProductDescriptor, WorkProductDescriptor> wpdToDeliverableDescriptorMap;

	private BatchCommand updateDeliverablePartsCmd;

	private boolean newDuplicatesRemoved;

	private IConfigurator configurator;

	private ArrayList linkedTasks;

	private HashMap wpdToTaskFeaturesMap;

	public PBSDropCommand(Activity activity, List workProducts) {
		super(activity, workProducts);
		this.activity = activity;
		for (Iterator iter = dropElements.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (!(element instanceof WorkProduct)) {
				iter.remove();
			}
		}
	}

	/**
	 * @param activity
	 * @param dropElements
	 * @param synch
	 */
	public PBSDropCommand(Activity activity, List dropElements, boolean synch) {
		super(activity, dropElements, synch);
	}

	/**
	 * @param activity
	 * @param dropElements
	 * @param config
	 * @param synchFeatures
	 */
	public PBSDropCommand(Activity activity, List dropElements,
			MethodConfiguration config, Set synchFeatures, IConfigurator configurator) {
		super(activity, dropElements, config, synchFeatures);
		this.configurator = configurator;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.process.command.BSDropCommand#preExecute()
	 */
	protected boolean preExecute() {
		if (!super.preExecute())
			return false;

		wpDescList = new ArrayList();
		taskDescList = new ArrayList();
		roleDescList = new ArrayList();
		wpDescToDeliverableParts = new HashMap();
		wpdToDeliverableDescriptorMap = new HashMap();

		if(!synchronize || (synchronize && synchFeatures.contains(UmaPackage.eINSTANCE.getArtifact_ContainedArtifacts()))) {
			// add subartifacts to dropElements list if there is any
			//
			for (Iterator iter = new ArrayList(dropElements).iterator(); iter
			.hasNext();) {
				Object element = iter.next();
				if (element instanceof Artifact) {
					Iterator iterator = new AbstractTreeIterator(element, false) {
						
						/**
						 * Comment for <code>serialVersionUID</code>
						 */
						private static final long serialVersionUID = -4820477887426087262L;
						
						protected Iterator getChildren(Object object) {
							Object subArtifacts = Providers.getConfigurationApplicator().getReference(
									(VariabilityElement) object,
									UmaPackage.eINSTANCE.getArtifact_ContainedArtifacts(),
									getMethodConfiguration());
							return ((Collection)subArtifacts).iterator();
						}
						
					};
					
					while (iterator.hasNext()) {
						Artifact subArtifact = (Artifact) iterator.next();
						if (!dropElements.contains(subArtifact) && prepareAdd((WorkProduct) subArtifact)) 
						{
							dropElements.add(subArtifact);
						}
					}
				}
			}
		}

		MethodConfiguration config = getMethodConfiguration();
		Set descriptorsToRefresh = synchronize ? batchCommand.getDescriptorsToRefresh() : null;
		
		List bes = activity.getBreakdownElements();
		UniqueNamePNameHandler uniqueNamesHandler = new UniqueNamePNameHandler(bes, bes);
		
		for (int i = 0; i < dropElements.size(); i++) {
			WorkProduct wp = (WorkProduct) dropElements.get(i);			
			if (TngUtil.isContributor(wp)) {
				wp = (WorkProduct) TngUtil.getBase(wp);
			}
			WorkProductDescriptor wpDesc = null;
			if (synchronize) {
				wpDesc = (WorkProductDescriptor) ProcessCommandUtil
					.getDescriptor(wp, activity, config);
			}
			if (wpDesc == null) {
				wpDesc = ProcessCommandUtil.createWorkProductDescriptor(wp, config,
						wpDescToDeliverableParts);
//				uniqueNamesHandler.ensureUnique(wpDesc);
				wpDescList.add(wpDesc);

				// automatic adding to the existing deliverable descriptor in
				// the activity's scope if there is any
				// valid one.
				//
				WorkProductDescriptor descriptor = UserInteractionHelper
						.getDeliverable(activity, wp);
				if (descriptor != null) {
					wpdToDeliverableDescriptorMap.put(wpDesc, descriptor);
				}
				
				if(wpdToTaskFeaturesMap != null) {
					// replace work product with its work product descriptor in wpdToTaskFeaturesMap
					//
					Map featuresMap = (Map) wpdToTaskFeaturesMap.get(wp);
					if(featuresMap != null) {
						wpdToTaskFeaturesMap.remove(wp);
						wpdToTaskFeaturesMap.put(wpDesc, featuresMap);
					}
				}

			} else {
				if (descriptorsToRefresh != null && wpDesc.getIsSynchronizedWithSource().booleanValue()) {
					descriptorsToRefresh.add(wpDesc);
				}
				if (wp instanceof Deliverable && synchFeatures.contains(UmaPackage.eINSTANCE.getDeliverable_DeliveredWorkProducts())) {
					ProcessCommandUtil.createDeliverableParts(wpDesc,
							(Deliverable) wp, config, wpDescToDeliverableParts, descriptorsToRefresh);
				}
				
				if(wpdToTaskFeaturesMap != null) {
					wpdToTaskFeaturesMap.remove(wp);
				}
			}

		
			if (!synchronize) {
				// get all possible tasks for this workproduct for
				// which task descriptor needs to be created
				List tasks = ProcessUtil.getTasksForWorkProduct(wp, config);

				if ((tasks != null) && (tasks.size() > 0)) {
					// show task selections dialog		
					final List finalTasks = tasks;
					final WorkProduct finalWp = wp;
					final List finalSelected = new ArrayList();
					List selectedTasks = new ArrayList();
					// show task selections dialog
					UserInteractionHelper.getUIHelper().runSafely(new Runnable() {
						public void run() {
							List selected = UserInteractionHelper.selectTasks(
									finalTasks, finalWp);						
							finalSelected.addAll(selected);
						}
					}, true);
					selectedTasks.addAll(finalSelected);
					
					// create task descriptors for this workproduct
					if ((selectedTasks != null) && (!(selectedTasks.isEmpty()))) {
						for (int j = 0; j < selectedTasks.size(); j++) {
							Task task = (Task) selectedTasks.get(j);

							// call this method even the descriptor for the
							// given task already exists in this activity
							// to add any additional relationships in case of
							// recent change in the default configuration
							// of the process.
							PBSDropCommand.addToDescriptorLists(task, activity,
									taskDescList, roleDescList, wpDescList,
									wpDescToDeliverableParts,
									descriptorsToRefresh,
									batchCommand.getObjectToNewFeatureValuesMap(), 
									config, true, synchFeatures);
						}
					} else {
						// If no tasks are selected, add Responsible role to wp
						ProcessCommandUtil.addResponsibleRoleDescriptors(wpDesc, activity,
								roleDescList, descriptorsToRefresh, config);
					}
				}
				else {
					//	If there are no tasks to show, add Responsible role to wp
					ProcessCommandUtil.addResponsibleRoleDescriptors(wpDesc, activity,	roleDescList, descriptorsToRefresh, config);
				}
			}
//			else {
//				//	in case of synchronization, add Responsible role to wp
//				if (synchFeatures.contains(UmaPackage.eINSTANCE.getRole_ResponsibleFor()))
//					PBSDropCommand.addResponsibleRole(wpDesc, activity,	roleDescList, descriptorsToRefresh, config);
//			}				
		}

		if(!wpDescToDeliverableParts.isEmpty()) {
			updateDeliverablePartsCmd = new BatchCommand(true);
			for (Iterator iter = wpDescToDeliverableParts.entrySet().iterator(); iter
			.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				Object wpDesc = entry.getKey();
				updateDeliverablePartsCmd.getObjectToNewFeatureValuesMap().put(wpDesc, 
						Collections.singletonMap(UmaPackage.eINSTANCE.getWorkProductDescriptor_DeliverableParts(), entry.getValue()));
			}
		}
		

		// ensure unique names for wp descriptors
		for (int i = 0; i < wpDescList.size(); i++) {
			WorkProductDescriptor wpDesc = (WorkProductDescriptor) wpDescList
					.get(i);
			if (wpDesc != null) {
				uniqueNamesHandler.ensureUnique(wpDesc);
			}
		}
		return !taskDescList.isEmpty()
				|| !roleDescList.isEmpty()
				|| !wpDescList.isEmpty()
				|| (updateDeliverablePartsCmd != null && updateDeliverablePartsCmd.canExecute())
				|| !wpdToDeliverableDescriptorMap.isEmpty()
				|| (descriptorsToRefresh != null && !descriptorsToRefresh
						.isEmpty())
				|| batchCommand.canExecute();
	}
	
	/**
	 * @param subArtifact
	 * @return
	 */
	private boolean prepareAdd(WorkProduct wp) {
		if (synchronize) {	
			// get linked tasks of the task descriptors in the activity for the configuration
			//
			List tasks = getLinkedTasks();
			
			if(!tasks.isEmpty()) {
				// select only work products that are input or output of an existing task in the activity
				//	
				Map featuresMap = ProcessCommandUtil.getFeaturesMap(tasks, wp, getMethodConfiguration());
				if(!featuresMap.isEmpty()) {
					// use the wp to the key in the map right now and replace it with
					// its work product descriptor later
					//
					if(wpdToTaskFeaturesMap == null) {
						wpdToTaskFeaturesMap = new HashMap();
					}
					wpdToTaskFeaturesMap.put(wp, featuresMap);
					return true;
				}
			}
			return false;
		}
		return true;
	}

	/**
	 * @return
	 */
	private List getLinkedTasks() {
		if(linkedTasks == null) {
			linkedTasks = new ArrayList();
			for (Iterator iter = activity.getBreakdownElements().iterator(); iter.hasNext();) {
				Object element = iter.next();
				if(element instanceof TaskDescriptor) {
					Task task = ((TaskDescriptor)element).getTask();
					if(task != null && configurator.accept(element)) {
						linkedTasks.add(task);
					}
				}
			}
		}
		return linkedTasks;
	}

	/**
	 * Removes new elements that are duplicate b/c they are created by the previous WBSDropCommand
	 */
	private void removeNewDuplicates() {
		if(synchronize) {
			if(!newDuplicatesRemoved) {
				for (Iterator iter = roleDescList.iterator(); iter.hasNext();) {
					RoleDescriptor roleDesc = (RoleDescriptor) iter.next();
					Object desc = ProcessCommandUtil.getDescriptor(roleDesc.getRole(), activity, getMethodConfiguration());
					if(desc != null) {
						iter.remove();
					}
				}
				newDuplicatesRemoved = true;			
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.process.command.BSDropCommand#doExecute()
	 */
	protected void doExecute() {
		removeNewDuplicates();
		
		// automatically add work product descriptor to deliverable part
		//
		if (!wpdToDeliverableDescriptorMap.isEmpty()) {
			for (Map.Entry<WorkProductDescriptor, WorkProductDescriptor> entry : 
				wpdToDeliverableDescriptorMap.entrySet()) {
				WorkProductDescriptor deliverable = (WorkProductDescriptor) entry
						.getValue();
				deliverable.getDeliverableParts().add(entry.getKey());
			}
		}

		// add work product descriptors
		//
		activity.getBreakdownElements().addAll(wpDescList);

		// add task descriptors
		//
		activity.getBreakdownElements().addAll(taskDescList);

		// add role descriptors
		//
		activity.getBreakdownElements().addAll(roleDescList);
		
		// associate new work product descriptors with task descriptors
		//
		if(wpdToTaskFeaturesMap != null) {
			for (Iterator iter = wpdToTaskFeaturesMap.entrySet().iterator(); iter.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				Map taskFeatures = (Map) entry.getValue();
				for (Iterator iterator = taskFeatures.entrySet().iterator(); iterator
				.hasNext();) {
					Map.Entry ent = (Map.Entry) iterator.next();
					TaskDescriptor taskDesc = (TaskDescriptor) ProcessCommandUtil.getDescriptor(ent.getKey(), activity.getBreakdownElements(), getMethodConfiguration(), false);
					for (Iterator iterator1 = ((Collection)ent.getValue()).iterator(); iterator1
					.hasNext();) {
						EStructuralFeature f = (EStructuralFeature) iterator1.next();
						EStructuralFeature descFeature = (EStructuralFeature) FEATURE_MAP.get(f);
						if(descFeature.isMany()) {
							((List)taskDesc.eGet(descFeature)).add(entry.getKey());							
						}
						else {
							// TODO: need to back up old value here
							//
							taskDesc.eSet(descFeature, entry.getKey());
						}
					}
				}
			}
		}

		// add new descriptors to activity's package
		//
		ProcessPackage pkg = (ProcessPackage) activity.eContainer();
		if (pkg != null) {
			pkg.getProcessElements().addAll(taskDescList);
			pkg.getProcessElements().addAll(roleDescList);
			pkg.getProcessElements().addAll(wpDescList);

			for (Iterator iter = wpDescToDeliverableParts.values().iterator(); iter
					.hasNext();) {
				pkg.getProcessElements().addAll((Collection) iter.next());
			}
		}

//		getModifiedResources().add(activity.eResource());
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.edit.process.command.BSDropCommand#updateDescriptors()
	 */
	protected void updateDescriptors() {
		super.updateDescriptors();
		
		// add deliverable parts to the work product descriptors
		//
		if(updateDeliverablePartsCmd != null) {
			updateDeliverablePartsCmd.execute();
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.edit.process.command.BSDropCommand#undoUpdateDescriptors()
	 */
	protected void undoUpdateDescriptors() {
		// remove deliverable parts of the work product descriptors
		//
		if(updateDeliverablePartsCmd != null) {
			updateDeliverablePartsCmd.undo();
		}

		super.undoUpdateDescriptors();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.process.command.BSDropCommand#doUndo()
	 */
	protected void doUndo() {
		// remove work product descriptors
		//
		activity.getBreakdownElements().removeAll(wpDescList);

		// remove role descriptors
		//
		activity.getBreakdownElements().removeAll(roleDescList);

		// remove task descriptors
		//
		activity.getBreakdownElements().removeAll(taskDescList);

		// remove work product descriptor from deliverable part
		//
		if (!wpdToDeliverableDescriptorMap.isEmpty()) {
			for (Iterator iter = wpdToDeliverableDescriptorMap.entrySet()
					.iterator(); iter.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				WorkProductDescriptor deliverable = (WorkProductDescriptor) entry
						.getValue();
				deliverable.getDeliverableParts().remove(entry.getKey());
			}
		}

		// remove descriptors from activity's package
		//
		ProcessPackage pkg = (ProcessPackage) activity.eContainer();
		if (pkg != null) {
			pkg.getProcessElements().removeAll(taskDescList);
			pkg.getProcessElements().removeAll(roleDescList);
			pkg.getProcessElements().removeAll(wpDescList);
			for (Iterator iter = wpDescToDeliverableParts.values().iterator(); iter
					.hasNext();) {
				pkg.getProcessElements().removeAll((Collection) iter.next());
			}
		}
		
		// disassociate new work product descriptors with task descriptors
		//
		if(wpdToTaskFeaturesMap != null) {
			for (Iterator iter = wpdToTaskFeaturesMap.entrySet().iterator(); iter.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				Map taskFeatures = (Map) entry.getValue();
				for (Iterator iterator = taskFeatures.entrySet().iterator(); iterator
						.hasNext();) {
					Map.Entry ent = (Map.Entry) iterator.next();
					TaskDescriptor taskDesc = (TaskDescriptor) ProcessCommandUtil.getDescriptor(ent.getKey(), activity, getMethodConfiguration());
					for (Iterator iterator1 = ((Collection)ent.getValue()).iterator(); iterator1
							.hasNext();) {
						EStructuralFeature f = (EStructuralFeature) iterator1.next();
						EStructuralFeature descFeature = (EStructuralFeature) FEATURE_MAP.get(f);
						if(descFeature.isMany()) {
							((List)taskDesc.eGet(descFeature)).remove(entry.getKey());							
						}
						else {
							taskDesc.eSet(descFeature, null);
						}
					}
				}
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.command.AbstractCommand#getAffectedObjects()
	 */
	public Collection getAffectedObjects() {
		if (wpDescList != null) {
			return wpDescList;
		}

		return super.getAffectedObjects();
	}

	/**
	 * 
	 * @param task
	 * @param activity
	 * @param taskDescList
	 * @param roleDescList
	 * @param wpDescList
	 * @param wpDescToDeliverableParts
	 * @param descriptorsToRefresh
	 * @return <code>true</code> if a new TaskDescriptor is created for the
	 *         given task, <code>false</code> otherwise
	 */
	static boolean addToDescriptorLists(Task task, Activity activity,
			List taskDescList, List roleDescList, List wpDescList,
			Map wpDescToDeliverableParts, Set descriptorsToRefresh,
			Map descriptorToNewFeatureValuesMap, MethodConfiguration config, boolean useExistingDescriptor, Set synchFeatures) {
		TaskDescriptor desc = ProcessCommandUtil.createTaskDescriptor(task, activity,
				roleDescList, wpDescList, wpDescToDeliverableParts, null,
				descriptorsToRefresh, descriptorToNewFeatureValuesMap, 
				config, useExistingDescriptor, synchFeatures);
		if ((desc != null) && (taskDescList != null)
				&& !taskDescList.contains(desc)) {
			taskDescList.add(desc);
		}
		return desc != null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.edit.process.command.BSDropCommand#dispose()
	 */
	public void dispose() {
		if(roleDescList != null) {
			roleDescList.clear();
		}
		if(wpDescList != null) {
			wpDescList.clear();
		}
		if(wpDescToDeliverableParts != null) {
			wpDescToDeliverableParts.clear();
		}
		if(wpdToDeliverableDescriptorMap != null) {
			wpdToDeliverableDescriptorMap.clear();
		}
		if(wpdToTaskFeaturesMap != null) {
			wpdToTaskFeaturesMap.clear();
		}
		
		super.dispose();
	}
	
}
