//------------------------------------------------------------------------------
// 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.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.Diagram;
import org.eclipse.epf.uma.Discipline;
import org.eclipse.epf.uma.DisciplineGrouping;
import org.eclipse.epf.uma.Domain;
import org.eclipse.epf.uma.Guidance;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.MethodUnit;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessElement;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.RoleSet;
import org.eclipse.epf.uma.RoleSetGrouping;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.WorkOrderType;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductType;

/**
 * Utility class for accessing and updating the UMA model objects.
 * 
 * @author Phong Nguyen Le
 * @author Kelvin Low
 * @since 1.0
 */
public class UmaUtil {

	/**
	 * Replaces the feature values of an old method element with the
	 * corresponding feature values of a new method element.
	 * <p>
	 * Note: All features are updated except for the GUID feature.
	 * 
	 * @param oldElement
	 *            the old method element
	 * @param newElement
	 *            the new method element
	 */
	public static void replace(MethodElement oldElement,
			MethodElement newElement) {
		List features = oldElement.eClass().getEAllStructuralFeatures();
		if (features != null) {
			int size = features.size();
			for (int i = 0; i < size; i++) {
				EStructuralFeature feature = (EStructuralFeature) features
						.get(i);
				if (feature != UmaPackage.eINSTANCE.getMethodElement_Guid()) {
					// don't replace GUID
					Object newValue = newElement.eGet(feature);
					oldElement.eSet(feature, newValue);
				}
			}
		}

	}

	/**
	 * Checks whether a model object has a direct resource.
	 * 
	 * @param e
	 *            a model object
	 * @return <code>true</code> if the specified model object is contained by
	 *         a resource
	 */
	public static boolean hasDirectResource(EObject e) {
		Resource resource = e.eResource();
		return (resource != null && resource.getContents().contains(e));
	}

	/**
	 * Gets a specific type of adapter associated with a notifier.
	 * 
	 * @param eObj
	 *            a notifier
	 * @param cls
	 *            the adapter class
	 * @return an <code>Adapter<code> object or <code>null</code>
	 */
	public static Object getAdapter(EObject eObj, Class cls) {
		for (Iterator adapters = eObj.eAdapters().iterator(); adapters
				.hasNext();) {
			Adapter adapter = (Adapter) adapters.next();
			if (cls.isInstance(adapter)) {
				return adapter;
			}
		}
		return null;
	}

	/**
	 * Gets the method package with a specific name.
	 * 
	 * @param methodPackages
	 *            a list of method packages
	 * @param name
	 *            a method package name
	 * @return a method package with the matching name or <code>null</code>
	 */
	public static MethodPackage findMethodPackage(List methodPackages,
			String name) {
		for (int i = methodPackages.size() - 1; i > -1; i--) {
			Object obj = methodPackages.get(i);
			if (obj instanceof MethodPackage) {
				MethodPackage pkg = (MethodPackage) obj;
				if (name.equals(pkg.getName())) {
					return pkg;
				}
			}
		}
		return null;
	}

	/**
	 * Gets the method package with a specific path.
	 * 
	 * @param methodPlugin
	 *            a method plug-in
	 * @param path
	 *            an array of method element path fragments
	 * @return a method package with the matching path or <code>null</code>
	 */
	public static MethodPackage findMethodPackage(MethodPlugin methodPlugin,
			String[] path) {
		MethodPackage pkg = null;
		List list = methodPlugin.getMethodPackages();
		for (int i = 0; i < path.length; i++) {
			pkg = findMethodPackage(list, path[i]);
			if (pkg == null) {
				return null;
			}
			list = pkg.getChildPackages();
		}
		return pkg;
	}

	/**
	 * Gets the parent activity of a breakdown element.
	 * 
	 * @param e
	 *            a breakdown element
	 * @return the parent activity or <code>null</code>
	 */
	public static Activity getParentActivity(BreakdownElement e) {
		return e.getSuperActivities();
	}

	/**
	 * Gets the parent activity of a work order.
	 * 
	 * @param workOrder
	 *            a work order
	 * @return the parent activity or <code>null</code>
	 */
	public static Activity getOwningActivity(WorkOrder workOrder) {
		ProcessPackage pkg = (ProcessPackage) workOrder.eContainer();
		for (Iterator iter = pkg.getProcessElements().iterator(); iter
				.hasNext();) {
			Object element = iter.next();
			if (element instanceof Activity) {
				return (Activity) element;
			}
		}
		return null;
	}

	/**
	 * Gets the content package with a specific name.
	 * 
	 * @param methodPackages
	 *            a list of method packages
	 * @param name
	 *            a content package name
	 * @return a content package with the mathcing name or <code>null</code>
	 */
	public static ContentPackage findContentPackage(List methodPackages,
			String name) {
		for (int i = methodPackages.size() - 1; i > -1; i--) {
			Object obj = methodPackages.get(i);
			if (obj instanceof ContentPackage) {
				ContentPackage pkg = (ContentPackage) obj;
				if (name.equals(pkg.getName())) {
					return pkg;
				}
			}
		}
		return null;
	}

	/**
	 * Returns the content package with a specific path.
	 * 
	 * @param methodPlugin
	 *            a method plug-in
	 * @param path
	 *            an array of method element path fragments
	 * @return a content package with the matching path or <code>null</code>
	 */
	public static ContentPackage findContentPackage(MethodPlugin methodPlugin,
			String[] path) {
		ContentPackage pkg = null;
		List list = methodPlugin.getMethodPackages();
		for (int i = 0; i < path.length; i++) {
			pkg = findContentPackage(list, path[i]);
			if (pkg == null) {
				return null;
			}
			list = pkg.getChildPackages();
		}
		return pkg;
	}

	/**
	 * Gets the parent method plug-in of a method element.
	 * 
	 * @param element
	 *            a Method element
	 * @return the parent method plug-in or <code>null</code>
	 */
	public static MethodPlugin getMethodPlugin(EObject element) {
		for (EObject obj = element; obj != null; obj = obj.eContainer()) {
			if (obj instanceof MethodPlugin) {
				return (MethodPlugin) obj;
			}
		}
		return null;
	}

	/**
	 * Gets the parent method library of a method element.
	 * 
	 * @param element
	 *            a method element
	 * @return the parent method library or <code>null</code>
	 */
	public static MethodLibrary getMethodLibrary(EObject element) {
		for (EObject obj = element; obj != null; obj = obj.eContainer()) {
			if (obj instanceof MethodLibrary) {
				return (MethodLibrary) obj;
			}
		}
		return null;
	}
	
	public static EObject getTopContainer(EObject element) {
		EObject container = null;
		for (EObject obj = element.eContainer(); obj != null; obj = obj.eContainer()) {
			container = obj;
		}
		return container;		
	}

	/**
	 * Gets the parent content package of a content element.
	 * 
	 * @param element
	 *            a content element
	 * @return the parent content package or <code>null</code>
	 */
	public static ContentPackage getContentPackage(EObject element) {
		for (EObject obj = element; obj != null; obj = obj.eContainer()) {
			if (obj instanceof ContentPackage) {
				return (ContentPackage) obj;
			}
		}
		return null;
	}

	/**
	 * Gets the parent process package of a process element.
	 * 
	 * @param element
	 *            a Process element
	 * @return the parent process package or <code>null</code>
	 */
	public static ProcessPackage getProcessPackage(EObject element) {
		for (EObject obj = element; obj != null; obj = obj.eContainer()) {
			if (obj instanceof ProcessPackage) {
				return (ProcessPackage) obj;
			}
		}
		return null;
	}

	/**
	 * Gets the parent diagram of a diagram element.
	 * 
	 * @param element
	 *            a diagram element
	 * @return the parent diagram or <code>null</code>
	 */
	public static Diagram getDiagram(EObject element) {
		for (EObject obj = element; obj != null; obj = obj.eContainer()) {
			if (obj instanceof Diagram) {
				return (Diagram) obj;
			}
		}
		return null;
	}

	/**
	 * Checks whether a method element is contained by a specific content
	 * package.
	 * 
	 * @param element
	 *            a method element
	 * @param contentPackage
	 *            a content package
	 * @return <code>true</code> if the method element is contained by the
	 *         content package
	 */
	public static boolean isContainedByContentPackage(EObject element,
			ContentPackage contentPackage) {
		return isContainedBy(element, contentPackage);
	}

	/**
	 * Checks whether a model object is contained by a specific container.
	 * 
	 * @param eObj
	 *            a model object
	 * @param container
	 *            a container
	 * @return <code>true</code> if the model object is contained by the
	 *         container
	 */
	public static boolean isContainedBy(EObject eObj, Object container) {
		if (eObj == null) {
			return false;
		}
		for (EObject obj = eObj.eContainer(); obj != null; obj = obj
				.eContainer()) {
			if (obj == container) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Generates and returns a unique ID.
	 * 
	 * @return a unique ID
	 */
	public static String generateGUID() {
		return EcoreUtil.generateUUID();
	}

	/**
	 * Creates and returns the content description name of a given method
	 * element.
	 * 
	 * @param element
	 *            a method element
	 * @return a suitable content description name
	 */
	public static String createContentDescriptionName(MethodElement e) {
		return e.getName() + ',' + e.getGuid();
	}

	public static void getAllSupers(List supers, VariabilityElement e,
			VariabilityType type) {
		VariabilityElement base = e.getVariabilityBasedOnElement();
		if (base != null && e.getVariabilityType() == type
				&& !supers.contains(base)) {
			supers.add(base);
			getAllSupers(supers, base, type);
		}
	}

	public static void getAllSupersBoth(List supers, VariabilityElement e,
			VariabilityType type1, VariabilityType type2) {
		VariabilityElement base = e.getVariabilityBasedOnElement();
		if (base != null
				&& (e.getVariabilityType() == type1 || e.getVariabilityType() == type2)
				&& !supers.contains(base)) {
			supers.add(base);
			getAllSupersBoth(supers, base, type1, type2);
		}
	}

	/**
	 * Gets the class of a content element.
	 * 
	 * @param contentElement
	 *            a content element
	 * @return the content element class
	 */
	public static Class getClassOfContentElement(ContentElement contentElement) {
		if (contentElement instanceof Role)
			return Role.class;
		if (contentElement instanceof Task)
			return Task.class;
		if (contentElement instanceof WorkProduct)
			return WorkProduct.class;
		if (contentElement instanceof Guidance)
			return Guidance.class;
		if (contentElement instanceof Domain)
			return Domain.class;
		if (contentElement instanceof Discipline)
			return Discipline.class;
		if (contentElement instanceof DisciplineGrouping)
			return DisciplineGrouping.class;
		if (contentElement instanceof RoleSet)
			return RoleSet.class;
		if (contentElement instanceof RoleSetGrouping)
			return RoleSetGrouping.class;
		if (contentElement instanceof WorkProductType)
			return WorkProductType.class;
		return Object.class;
	}

	/**
	 * Creates a default work order for two work breakdown elements.
	 * 
	 * @param e
	 *            a work breakdown element
	 * @param predecessor
	 *            the predecessor work breakdown element
	 * @return the newly created work order
	 */
	public static WorkOrder createDefaultWorkOrder(WorkBreakdownElement succ,
			WorkBreakdownElement pred) {
		return createDefaultWorkOrder(succ, pred, true);
	}
	
	public static WorkOrder createDefaultWorkOrder(WorkBreakdownElement succ,
			WorkBreakdownElement pred, boolean link) {
		WorkOrder wo = UmaFactory.eINSTANCE.createWorkOrder();
		wo.setPred(pred);
		wo.setLinkType(WorkOrderType.FINISH_TO_FINISH_LITERAL);
		if(link) {
			succ.getLinkToPredecessor().add(wo);
		}
		return wo;
	}	

	/**
	 * Locates the work order associated with two work breakdown elements.
	 * 
	 * @param e
	 *            a work breakdown element
	 * @param predecessor
	 *            the predecessor work breakdown element
	 * @return a work order or <code>null</code>
	 */
	public static WorkOrder findWorkOrder(WorkBreakdownElement e,
			Object predecessor) {
		for (Iterator iter = e.getLinkToPredecessor().iterator(); iter
				.hasNext();) {
			WorkOrder workOrder = (WorkOrder) iter.next();
			if (workOrder.getPred() == predecessor)
				return workOrder;
		}

		return null;
	}

	/**
	 * Removes the work order associated with two work breakdown elements.
	 * 
	 * @param e
	 *            a work breakdown element
	 * @param predecessor
	 *            the predecessor work breakdown element
	 * @return the removed work order or <code>null</code>
	 */
	public static WorkOrder removeWorkOrder(WorkBreakdownElement e,
			Object predecessor) {
		for (Iterator iterator = e.getLinkToPredecessor().iterator(); iterator
				.hasNext();) {
			WorkOrder order = (WorkOrder) iterator.next();
			if (order.getPred() == predecessor) {
				iterator.remove();
				return order;
			}
		}
		return null;
	}

	/**
	 * Gets the parent process component of a method element.
	 * 
	 * @param e
	 *            a method element, typically a process element
	 * @return the parent process component or <code>null</code>
	 */
	public static ProcessComponent getProcessComponent(MethodElement e) {
		EObject container;
		for (container = e; container != null
				&& !(container instanceof ProcessComponent); container = container
				.eContainer())
			;
		if (container != null) {
			return ((ProcessComponent) container);
		}
		return null;
	}

	/**
	 * Gets the parent method unit of a method element.
	 * 
	 * @param e
	 *            a method element
	 * @return the parent method unit or <code>null</code>
	 */
	public static MethodUnit getMethodUnit(MethodElement e) {
		EObject container;
		for (container = e; container != null
				&& !(container instanceof MethodUnit); container = container
				.eContainer())
			;
		if (container != null) {
			return ((MethodUnit) container);
		}
		return null;

	}

	/**
	 * Checks whether a method plug-in has method elements that reference
	 * elements in a base plug-in.
	 * <p>
	 * Note: This is a expensive call to make for a large method plug-in.
	 * 
	 * @param plugin
	 *            a method plug-in
	 * @param base
	 *            a base method plug-in
	 * @return <code>true</code> if the specified method plug-in contain
	 *         method elements that reference elements in a base plug-in.
	 */
	public static boolean hasReference(MethodPlugin plugin, MethodPlugin base) {
		for (EContentsEList.FeatureIterator featureIterator = (EContentsEList.FeatureIterator) plugin
				.eCrossReferences().iterator(); featureIterator.hasNext();) {
			EObject ref = (EObject) featureIterator.next();
			EStructuralFeature f = featureIterator.feature();

			if (f != UmaPackage.eINSTANCE.getMethodPlugin_Bases()
					&& UmaUtil.getMethodPlugin(ref) == base) {
				return true;
			}
		}

		for (Iterator iter = plugin.eAllContents(); iter.hasNext();) {
			EObject element = (EObject) iter.next();

			// ignore ProcessElement b/c it can references anything
			//
			if (element instanceof ProcessElement) {
				continue;
			}

			for (Iterator iterator = element.eCrossReferences().iterator(); iterator
					.hasNext();) {
				EObject ref = (EObject) iterator.next();
				if (getMethodPlugin(ref) == base) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Removes all element references in a method plug-in that point to elements
	 * in a base plug-in.
	 * <p>
	 * Note: This is a expensive call to make for a large method plug-in.
	 * 
	 * @param plugin
	 *            a method plug-in
	 * @param base
	 *            the base method plug-in
	 * @return <code>true</code> if the operation is successful
	 */
	public static boolean removeReferences(MethodPlugin plugin,
			MethodPlugin base) {
		for (Iterator iter = plugin.eAllContents(); iter.hasNext();) {
			EObject element = (EObject) iter.next();

			// ignore ProcessElement b/c it can references anything
			//
			if (element instanceof ProcessElement) {
				continue;
			}

			for (EContentsEList.FeatureIterator featureIterator = (EContentsEList.FeatureIterator) element
					.eCrossReferences().iterator(); featureIterator.hasNext();) {
				EObject ref = (EObject) featureIterator.next();

				if (getMethodPlugin(ref) == base) {
					EStructuralFeature f = featureIterator.feature();
					if (f.isMany()) {
						((Collection) element.eGet(f)).remove(ref);
					} else {
						element.eSet(f, null);
					}
				}
			}
		}

		return false;
	}

	public static String getMessage(IStatus status) {
		String msg = status.getMessage();
		if (status.isMultiStatus()) {
			StringBuffer strBuf = new StringBuffer(msg);
			IStatus statuses[] = status.getChildren();
			for (int i = 0; i < statuses.length; i++) {
				strBuf.append('\n').append(statuses[i].getMessage());
			}
			msg = strBuf.toString();
		}
		if (msg != null && msg.trim().length() == 0) {
			msg = null;
		}
		return msg;
	}

	/**
	 * Generates a GUID using a base GUID.
	 * 
	 * @param baseGUID
	 *            a base GUID
	 * @return a unique ID
	 */
	public static final String generateGUID(String baseGUID) {
		return GUID.generate(baseGUID);
	}

	private static class GUID {
		private static MessageDigest md5 = null;

		private static MessageDigest getMD5() {
			if (md5 == null) {
				synchronized (GUID.class) {
					if (md5 == null) {
						try {
							md5 = MessageDigest.getInstance("MD5"); //$NON-NLS-1$
						} catch (NoSuchAlgorithmException e) {
							e.printStackTrace();
						}
					}
				}
			}
			return md5;
		}

		public static final String generate(String baseGUID) {
			MessageDigest md5 = getMD5();
			md5.update(baseGUID.getBytes());
			byte[] hash = md5.digest();
			char[] buffer = new char[23];
			buffer[0] = '-';

			// Do a base 64 conversion by turning every 3 bytes into 4 base 64
			// characters
			//
			for (int i = 0; i < 5; ++i) {
				buffer[4 * i + 1] = BASE64_DIGITS[(hash[i * 3] >> 2) & 0x3F];
				buffer[4 * i + 2] = BASE64_DIGITS[((hash[i * 3] << 4) & 0x30)
						| ((hash[i * 3 + 1] >> 4) & 0xF)];
				buffer[4 * i + 3] = BASE64_DIGITS[((hash[i * 3 + 1] << 2) & 0x3C)
						| ((hash[i * 3 + 2] >> 6) & 0x3)];
				buffer[4 * i + 4] = BASE64_DIGITS[hash[i * 3 + 2] & 0x3F];
			}

			// Handle the last byte at the end.
			//
			buffer[21] = BASE64_DIGITS[(hash[15] >> 2) & 0x3F];
			buffer[22] = BASE64_DIGITS[(hash[15] << 4) & 0x30];

			return new String(buffer);
		}

		private static final char[] BASE64_DIGITS = { 'A', 'B', 'C', 'D', 'E',
				'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
				'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
				'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
				'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
				'1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' };
	}
}