//------------------------------------------------------------------------------
// 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.uma.edit.domain;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.edit.command.CopyCommand.Helper;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.epf.uma.MethodElement;

/**
 * A traceable adapter factory editing domain used for copying method elements.
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class TraceableAdapterFactoryEditingDomain extends
		AdapterFactoryEditingDomain {

	// Maps copied method elements to their original counterparts.
	// Note: Copied elements are copies of the clipboard copies.
	private HashMap copyToOriginalMap = null;

	// Maps original elements to their clipboard copies.
	private Map originalToClipboardMap = null;

	/**
	 * Creates a new instance.
	 * 
	 * @param adapterFactory
	 *            an adapter factory used to create the adapter to which calls
	 *            are delegated
	 * @param commandStack
	 *            a command stack
	 */
	public TraceableAdapterFactoryEditingDomain(AdapterFactory adapterFactory,
			CommandStack commandStack) {
		super(adapterFactory, commandStack);
	}

	/**
	 * Creates a new instance.
	 * 
	 * @param adapterFactory
	 *            an adapter factory used to create the adapter to which calls
	 *            are delegated
	 * @param commandStack
	 *            a command stack
	 * @param resourceToReadOnlyMap
	 *            controls whether the domain is read only
	 */
	public TraceableAdapterFactoryEditingDomain(AdapterFactory adapterFactory,
			CommandStack commandStack, Map resourceToReadOnlyMap) {
		super(adapterFactory, commandStack, resourceToReadOnlyMap);
	}

	/**
	 * Creates a new instance.
	 * 
	 * @param adapterFactory
	 *            an adapter factory used to create the adapter to which calls
	 *            are delegated
	 * @param commandStack
	 *            a command stack
	 * @param resourceSet
	 *            a resource set
	 */
	public TraceableAdapterFactoryEditingDomain(AdapterFactory adapterFactory,
			CommandStack commandStack, ResourceSet resourceSet) {
		super(adapterFactory, commandStack, resourceSet);
	}

	/**
	 * Returns a map containing the copied elements mapped to their original
	 * counterparts.
	 * 
	 * @return a map containing the copied elements mapped to their original
	 *         counterparts
	 */
	public Map getCopyToOriginalMap() {
		if (copyToOriginalMap == null) {
			copyToOriginalMap = new HashMap();
		}
		return copyToOriginalMap;
	}
	
	
	/**
	 * Returns a map containing the original elements mapped to their copied 
	 * counterparts on clipboard
	 * 
	 * @return a map containing the original elements mapped to their copied 
	 *         counterparts
	 */
	public Map getOriginalToClipboardMap() {
		if (originalToClipboardMap == null) {
			originalToClipboardMap = new HashMap();
		}
		return originalToClipboardMap;
	}

	/**
	 * Used by the CreateCopyCommand. Adds infomation to construct maps that
	 * keep track of the original method elements and their copies.
	 * 
	 * @param c
	 *            a collection to store the mapping info
	 * @param copyHelper
	 *            a helper class that is used to keep track of copied objects
	 *            and their associated copies
	 */
	public void addCopyInfo(Collection c, Helper copyHelper) {
		if (isNewCopy(c, copyHelper)) {
			addNewCopy(c, copyHelper);
			return;
		} else {
			chainCopy(c, copyHelper);
			return;
		}
	}

	/**
	 * Adds a new element that is being copied to the clipboard.
	 */
	private void addNewCopy(Collection c, Helper copyHelper) {
		// this means we are copying the Collection c to the clipboard
		if (originalToClipboardMap == null)
			originalToClipboardMap = new HashMap();
		Iterator iter = copyHelper.keySet().iterator();
		while (iter.hasNext()) {
			Object key = iter.next();
			Object value = copyHelper.get(key);
			originalToClipboardMap.put(key, value);
		}
	}

	/**
	 * Creates a map from the copied elements to their original counterparts.
	 */
	private void chainCopy(Collection c, Helper copyHelper) {
		// chain the maps - change the copyToOriginalMap
		if (originalToClipboardMap != null) {
			if (copyToOriginalMap == null)
				copyToOriginalMap = new HashMap();
			Iterator iter = originalToClipboardMap.keySet().iterator();
			while (iter.hasNext()) {
				Object o2CKey = iter.next();
				Object o2CValue = originalToClipboardMap.get(o2CKey);
				Object copyValue = copyHelper.get(o2CValue);
				if (copyValue == null) {
					// error
					continue;
				}
				if (o2CKey instanceof MethodElement)
					copyToOriginalMap.put(copyValue, o2CKey);
			}
		}
	}

	private boolean isNewCopy(Collection c, Helper copyHelper) {
		// originalToClipboardMap was set to null at start of copy command
		if (originalToClipboardMap == null)
			return true;

		// iterate through copyHelper map, see if any copyHelper keys are o2C
		// values, which means we are copying clipboard
		Iterator iter = copyHelper.keySet().iterator();
		while (iter.hasNext()) {
			Object clipKey = iter.next();
			if (!originalToClipboardMap.containsValue(clipKey))
				return true;
		}

		return false;
	}

	/**
	 * Initializes the copy maps. It should be called within the copy action.
	 */
	public void resetCopyMaps() {
		if (originalToClipboardMap != null) {
			originalToClipboardMap.clear();
			originalToClipboardMap = null;
		}
		if (copyToOriginalMap != null) {
			copyToOriginalMap.clear();
			copyToOriginalMap = null;
		}
	}

}
