//------------------------------------------------------------------------------
// 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.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.command.Command;
import org.eclipse.epf.library.edit.IConfigurator;
import org.eclipse.epf.library.edit.LibraryEditPlugin;
import org.eclipse.epf.library.edit.command.INestedCommandProvider;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.util.ExtensionManager;
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.Deliverable;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.TeamProfile;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;

/**
 * Command to drap and drop roles to Team Allocation breakdown structure
 * 
 * @author Phong Nguyen Le
 * @author Shilpa Toraskar
 * @since 1.0
 */
public class OBSDropCommand extends BSDropCommand {
	private ArrayList wpDescList;

	private ArrayList roleDescList;

	private Map roleDescTeamProfileMap;

	private Map wpDescToDeliverableParts;

	private HashMap wpdToDeliverableDescriptorMap;

	private HashMap wpdToTaskFeaturesMap; // map of WorkProductDescriptor to

	// map of task ot feature list

	private IConfigurator configrator;

	private boolean newDuplicatesRemoved;
	
	public OBSDropCommand(Activity act, List roles) {
		super(act, roles);
		for (Iterator iter = dropElements.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (!(element instanceof Role)) {
				iter.remove();
			}
		}
	}

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

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

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

		MethodConfiguration config = getMethodConfiguration();
		Set descriptorsToRefresh = synchronize ? batchCommand
				.getDescriptorsToRefresh() : null;

		List bes = activity.getBreakdownElements();
		UniqueNamePNameHandler uniqueNamesHandler = new UniqueNamePNameHandler(bes, bes);
				
		int size = dropElements.size();
		for (int i = 0; i < size; i++) {
			Role role = (Role) dropElements.get(i);
			if (TngUtil.isContributor(role)) {
				role = (Role) TngUtil.getBase(role);
			}

			// check if the role descriptor of the role exists under this
			// activity
			RoleDescriptor roleDesc = (RoleDescriptor) ProcessCommandUtil
					.getDescriptor(role, activity, config);

			if (roleDesc == null) {
				// create role descriptor object
				roleDesc = ProcessUtil.createRoleDescriptor(role);
				uniqueNamesHandler.ensureUnique(roleDesc);
				roleDescList.add(roleDesc);
			} else {
				// need to clear all the refreshable features of the existing
				// descriptor
				//
				if (synchronize
						&& roleDesc.getIsSynchronizedWithSource()
								.booleanValue()) {
					batchCommand.getDescriptorsToRefresh().add(roleDesc);
				}
			}
		}

		// if not a synchronization, get all workproducts which have role as
		// responsible role for
		// which work product descriptor needs to be created
		//
		if (!synchronize) {
			for (int i = 0; i < size; i++) {
				Role role = (Role) dropElements.get(i);
				List workProducts = ProcessUtil.getWorkProductsForRole(role,
						config);
				if ((workProducts != null) && (!(workProducts.isEmpty()))) {
					HashMap wpToExistingDescriptorMap = new HashMap();
					List elements = new ArrayList(activity
							.getBreakdownElements());
					elements.addAll(wpDescList);
					for (Iterator iter = workProducts.iterator(); iter
							.hasNext();) {
						WorkProduct wp = (WorkProduct) iter.next();						
						Object wpd = ProcessUtil.getWorkProductDescriptor(wpDescList, wp);
						if(wpd == null) {
							wpd = ProcessCommandUtil.getDescriptor(wp, activity, config);
						}
						if (wpd != null) {
							wpToExistingDescriptorMap.put(wp, wpd);
						}
					}
					List selectedWorkProducts = new ArrayList(
							wpToExistingDescriptorMap.keySet());
					workProducts.removeAll(selectedWorkProducts);
					
					final List finalSelectedWps = new ArrayList();
					if (!workProducts.isEmpty()) {
						final List finalWps = new ArrayList();
						finalWps.addAll(workProducts);
						final Role finalRole = role;
						
						UserInteractionHelper.runInUIThread(new Runnable() {
							public void run() {
								List selected = UserInteractionHelper
										.selectWorkProducts(finalWps, finalRole);
								if (selected != null) {
									finalSelectedWps.addAll(selected);
								}
							}
						});
					}

					selectedWorkProducts.addAll(finalSelectedWps);
					if (!selectedWorkProducts.isEmpty()) {
						HashSet allSelectedTasks = new HashSet();

						for (int j = 0; j < selectedWorkProducts.size(); j++) {
							WorkProduct wp = (WorkProduct) selectedWorkProducts
									.get(j);

							if (TngUtil.isContributor(wp)) {
								wp = (WorkProduct) TngUtil.getBase(wp);
							}
							WorkProductDescriptor wpDesc = (WorkProductDescriptor) wpToExistingDescriptorMap.get(wp);
							if (wpDesc == null) {
								wpDesc = (WorkProductDescriptor) ProcessCommandUtil
										.getDescriptor(wp, activity, config);
							}
							if (wpDesc == null) {
								wpDesc = ProcessCommandUtil
										.createWorkProductDescriptor(wp,
												config,
												wpDescToDeliverableParts);
								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);
								}

							} 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);
								}
							}

							// 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)) {
								// exclude any task that is already selected or already exists in activity
								//
								tasks.removeAll(allSelectedTasks);
								for (Iterator iter = tasks.iterator(); iter
										.hasNext();) {
									Task task = (Task) iter.next();
									Object td = ProcessUtil.getTaskDescriptor(taskDescList, task); 
									if(td == null) {
										td = ProcessCommandUtil.getDescriptor(task, activity, config);
									}
									if(td != null) {
										iter.remove();
									}
								}

								if (!tasks.isEmpty()) {
									final List finalTasks = tasks;
									final WorkProduct finalWp = wp;
									final List finalSelected = new ArrayList();
									List selectedTasks = new ArrayList();
									// show task selections dialog
									UserInteractionHelper.runInUIThread(new Runnable() {
										public void run() {
											List selected = UserInteractionHelper
											.selectTasks(finalTasks, finalWp);
											finalSelected.addAll(selected);
										}
									});
									selectedTasks.addAll(finalSelected);
									if ((selectedTasks != null)
											&& ((!selectedTasks.isEmpty()))) {
										allSelectedTasks.addAll(selectedTasks);
									} else {
										// If no tasks are selected, add
										// Responsible role to wp
										PBSDropCommand.addResponsibleRole(
												wpDesc, activity, roleDescList,
												null, config);
									}
								}
							} else {
								// If there are no tasks to show, add
								// Responsible role to wp
								PBSDropCommand.addResponsibleRole(wpDesc,
										activity, roleDescList, null, config);
							}
						}

						// create task descriptors for this workproduct
						if ((allSelectedTasks != null)
								&& (!(allSelectedTasks.isEmpty()))) {
							for (Iterator itor = allSelectedTasks.iterator(); itor
									.hasNext();) {

								Task task = (Task) itor.next();

								// 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, synchFeatures);
							}
						}
					}
				}
			}
		}

		return (!roleDescList.isEmpty() // || !roleAssociationList.isEmpty()
				|| !taskDescList.isEmpty()
				|| !wpDescList.isEmpty()
				|| (wpDescToDeliverableParts != null && !wpDescToDeliverableParts
						.isEmpty()) || !wpdToDeliverableDescriptorMap.isEmpty())
				|| (descriptorsToRefresh != null && !descriptorsToRefresh
						.isEmpty()) || batchCommand.canExecute();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.library.edit.process.command.BSDropCommand#doExecute()
	 */
	protected void doExecute() {
		removeNewDuplicates();

		// add role descriptors to activity
		//
		activity.getBreakdownElements().addAll(roleDescList);

		if (roleDescTeamProfileMap == null) {
			// prepare for automatic assignment of role descriptor to team
			// profile
			//
			roleDescTeamProfileMap = new HashMap();
			for (Iterator iter = roleDescList.iterator(); iter.hasNext();) {
				RoleDescriptor roleDesc = (RoleDescriptor) iter.next();
				TeamProfile teamProfile = UserInteractionHelper.getTeam(
						activity, roleDesc.getRole());
				if (teamProfile != null) {
					roleDescTeamProfileMap.put(roleDesc, teamProfile);
				}
			}
		}

		// add role descriptors to team profiles
		//
		for (Iterator iter = roleDescTeamProfileMap.entrySet().iterator(); iter
				.hasNext();) {
			Map.Entry entry = (Map.Entry) iter.next();
			TeamProfile team = (TeamProfile) entry.getValue();
			team.getTeamRoles().add(entry.getKey());
		}

		// automatically add work product descriptor to 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().add(entry.getKey());
			}
		}

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

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

		// add deliverable parts to the work product descriptors
		//
		if (!wpDescToDeliverableParts.isEmpty()) {
			for (Iterator iter = wpDescToDeliverableParts.entrySet().iterator(); iter
					.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				WorkProductDescriptor wpDesc = (WorkProductDescriptor) entry
						.getKey();
				wpDesc.getDeliverableParts().addAll(
						(Collection) entry.getValue());
			}
		}

		// 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());

	}

	/**
	 * 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 = wpDescList.iterator(); iter.hasNext();) {
					WorkProductDescriptor wpd = (WorkProductDescriptor) iter
							.next();
					Object desc = ProcessCommandUtil.getDescriptor(wpd
							.getWorkProduct(), activity,
							getMethodConfiguration());
					if (desc != null) {
						iter.remove();
						if (wpDescToDeliverableParts != null) {
							wpDescToDeliverableParts.remove(wpd);
						}
						if (wpdToTaskFeaturesMap != null) {
							wpdToTaskFeaturesMap.remove(wpd);
						}
						if (wpdToDeliverableDescriptorMap != null) {
							wpdToDeliverableDescriptorMap.remove(wpd);
						}
					}
				}
				newDuplicatesRemoved = true;
			}
		}
	}

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

		// remove role descriptors from team profiles
		//
		for (Iterator iter = roleDescTeamProfileMap.entrySet().iterator(); iter
				.hasNext();) {
			Map.Entry entry = (Map.Entry) iter.next();
			TeamProfile team = (TeamProfile) entry.getValue();
			team.getTeamRoles().remove(entry.getKey());
		}

		// remove work product descriptors
		//
		activity.getBreakdownElements().removeAll(wpDescList);

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

		// // 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);
		// }
		// }
		// }
		// }
		// }

		// remove deliverable parts to the work product descriptors
		//
		if (!wpDescToDeliverableParts.isEmpty()) {
			for (Iterator iter = wpDescToDeliverableParts.entrySet().iterator(); iter
					.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				WorkProductDescriptor wpDesc = (WorkProductDescriptor) entry
						.getKey();
				wpDesc.getDeliverableParts().removeAll(
						(Collection) entry.getValue());
			}
		}

		// 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 role 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());
			}
		}
	}

	// /**
	// * Get task descriptors map for an activity
	// * @param activity
	// * @return
	// */
	// private static HashMap getTasksMapForActivity(Activity activity)
	// {
	// List elements = activity.getBreakdownElements();
	// HashMap map = new HashMap();
	// for (int i=0; i < elements.size(); i++)
	// {
	// Object obj = elements.get(i);
	// if (obj instanceof TaskDescriptor)
	// {
	// TaskDescriptor taskDesc = (TaskDescriptor) obj;
	// Task task = taskDesc.getTask();
	// if (task != null)
	// {
	// map.put(task, taskDesc);
	// }
	// }
	// }
	// return map;
	// }
	//	
	//	
	// /**
	// * Show RoleAssociation Dialog
	// * @param tasks
	// */
	// private static int showRoleAssociationDialog(Task task)
	// {
	//		
	// RoleAssociationDialog roleAssoc = new
	// RoleAssociationDialog(Display.getCurrent().getActiveShell(), task);
	// roleAssoc.open();
	//		
	// // selected tasks;
	// return roleAssoc.getRoleAssociation();
	// }

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

		return super.getAffectedObjects();
	}

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

		super.dispose();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.library.edit.process.command.BSDropCommand#executeNestedCommands()
	 */
	protected void executeNestedCommands() {
		List nestedCommandProviders = ExtensionManager
				.getNestedCommandProviders();
		if (!nestedCommandProviders.isEmpty()) {
			if (!taskDescList.isEmpty()) {
				for (Iterator iter = nestedCommandProviders.iterator(); iter
						.hasNext();) {
					INestedCommandProvider cmdProvider = (INestedCommandProvider) iter
							.next();
					try {
						Command cmd = cmdProvider.createRelatedObjects(
								taskDescList, OBSDropCommand.this);
						if (cmd != null && cmd.canExecute()) {
							cmd.execute();
							getNestedCommands().add(cmd);
						}
					} catch (Exception e) {
						LibraryEditPlugin.getDefault().getLogger().logError(e);
					}
				}
			}
		}

		super.executeNestedCommands();
	}
}
