package org.eclipse.epf.library.edit.util;

import java.util.ArrayList;
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.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.edit.realization.IRealizationManager;
import org.eclipse.epf.uma.CapabilityPattern;
import org.eclipse.epf.uma.DeliveryProcess;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.Guidance;
import org.eclipse.epf.uma.MethodConfiguration;
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.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;
import org.eclipse.epf.uma.util.AssociationHelper;

public class LibraryEditUtil {
	
	private static boolean debug = false;
	private static LibraryEditUtil instance = new LibraryEditUtil();
	private IRealizationManager defaultRealizationManager;
	private ILibraryEditUtilProvider provider;
	private boolean junitTest = false;
	
	private static Map<EReference, EReference> taskGuidanceRefMap;
	private static Map<EReference, EReference> roleGuidanceRefMap;
	private static Map<EReference, EReference> workproductGuidanceRefMap;
	private static UmaPackage up = UmaPackage.eINSTANCE;
	private static Set<EReference> autoSynReferences;

	public static LibraryEditUtil getInstance() {
		return instance;
	}
	
	private LibraryEditUtil() {		
	}
	
	public ILibraryEditUtilProvider getProvider() {
		if (provider == null) {
			provider = ExtensionManager.getLibraryEditUtilProvider();
		}
		return provider;
	}
	
	public IRealizationManager getDefaultRealizationManager() {
		return ProcessUtil.isSynFree() ? defaultRealizationManager : null;
	}

	public void setDefaultRealizationManager(
			IRealizationManager defaultRealizationManager) {
		this.defaultRealizationManager = defaultRealizationManager;
	}
	
	public Set<Descriptor> collectDescriptors(Process process) {			
		Set<Descriptor> descriptors = new HashSet<Descriptor>();
		
		EObject container = process.eContainer();
		if (! (container instanceof ProcessComponent)) {
			return descriptors;
		}
		
		for (Iterator iter = container.eAllContents(); iter.hasNext();) {
			EObject element = (EObject) iter.next();
			if (element instanceof Descriptor) {
				descriptors.add((Descriptor) element);
			}
		}
		return descriptors;
	}
	

	public Set<Process> collectProcesses(MethodElement libOrPlugin) {
		Set<Process> processes = new HashSet<Process>();
		if (! (libOrPlugin instanceof MethodLibrary ||
				libOrPlugin instanceof MethodPlugin)) {
			return processes;
		}
		for (Iterator iter = libOrPlugin.eAllContents(); iter.hasNext();) {
			EObject element = (EObject) iter.next();
			if (element instanceof Process) {				
				collectProcess((Process) element, processes);
			}
		}
		return processes;
	}

	private void collectProcess(Process process, Set<Process> processes) {
		if (process instanceof CapabilityPattern ||
				process instanceof DeliveryProcess) {
			if (process.eContainer() instanceof ProcessComponent) {
				processes.add(process);
			}
		}
	}

	public Set<Process> collectProcessesFromConfig(MethodConfiguration config) {
		Set<Process> result = new HashSet<Process>();
		List<MethodPlugin> plugins = config.getMethodPluginSelection();
		for (int i = 0; i < plugins.size(); i++) {
			Set<Process> set = collectProcesses(plugins.get(i));
			result.addAll(set);
		}
		return result;
	}

	public boolean isSynFree() {
		ILibraryEditUtilProvider p = getProvider();				
		return p == null ? true : p.isSynFree();
	}
	
	public MethodElement getMethodElement(String guid) {
		ILibraryEditUtilProvider p = getProvider();				
		return p == null ? null : p.getMethodElement(guid);
	}
	
	
	public String getPresentationName(MethodElement element,
			MethodConfiguration config) {
		String pName = element.getPresentationName();
		if (! StrUtil.isBlank(pName)) {
			return pName;
		}		
		ILibraryEditUtilProvider p = getProvider();
		if (p == null) {
			return pName;
		}
		return p.getPresentationName(element, config);
	}
	
	public boolean isDynamicAndExclude(Object obj, Descriptor desc,
			EReference ref, MethodConfiguration config) {
		return getProvider().isDynamicAndExclude(obj, desc, ref, config);
	}

	public boolean isDynamic(Object obj, Descriptor desc, EReference ref) {
		return getProvider().isDynamic(obj, desc, ref);
	}
	
	public MethodLibrary getCurrentMethodLibrary() {
		return getProvider().getCurrentMethodLibrary();
	}
	
	public boolean isGuidanceDynamic(Object obj, Descriptor desc,
			MethodConfiguration config) {
		return getProvider().isGuidanceDynamic(obj, desc, config);
	}
		
	public EReference getExcludeFeature(EReference ref) {
		if (ref == up.getTaskDescriptor_PerformedPrimarilyBy()) {
			return up.getTaskDescriptor_PerformedPrimarilyByExcluded();
		}
		
		if (ref == up.getTaskDescriptor_AdditionallyPerformedBy()) {
			return up.getTaskDescriptor_AdditionallyPerformedByExclude();				
		}
		
		if (ref == up.getTaskDescriptor_MandatoryInput()) {
			return up.getTaskDescriptor_MandatoryInputExclude();
		}
		
		if (ref == up.getTaskDescriptor_OptionalInput()) {
			return up.getTaskDescriptor_OptionalInputExclude();
		}
		
		if (ref == up.getTaskDescriptor_Output()) {
			return up.getTaskDescriptor_OutputExclude();
		}
		
		if (ref == up.getTaskDescriptor_SelectedSteps()) {
			return up.getTaskDescriptor_SelectedStepsExclude();
		}
		
		if (ref == up.getRoleDescriptor_ResponsibleFor()) {
			return up.getRoleDescriptor_ResponsibleForExclude();
		}
		
		if (ref == up.getWorkProductDescriptor_DeliverableParts()) {
			return up.getWorkProductDescriptor_DeliverablePartsExclude();
		}
		
		if (ref == up.getBreakdownElement_Checklists() || ref == up.getBreakdownElement_Concepts()
				|| ref == up.getBreakdownElement_Examples() || ref == up.getBreakdownElement_SupportingMaterials()
				|| ref == up.getBreakdownElement_Guidelines() || ref == up.getBreakdownElement_ReusableAssets()
				|| ref == up.getBreakdownElement_Templates() || ref == up.getBreakdownElement_Reports()
				|| ref == up.getBreakdownElement_Toolmentor() || ref == up.getBreakdownElement_Estimationconsiderations()) {
			return up.getDescriptor_GuidanceExclude();
		}
		
		//...		
		return null;
	}
	
	public EReference getLinkedElementFeature(EReference descriptorRef) {
		if (descriptorRef == up.getTaskDescriptor_PerformedPrimarilyBy()) {
			return up.getTask_PerformedBy();
		}
		
		if (descriptorRef == up.getTaskDescriptor_AdditionallyPerformedBy()) {
			return up.getTask_AdditionallyPerformedBy();				
		}
		
		if (descriptorRef == up.getTaskDescriptor_MandatoryInput()) {
			return up.getTask_MandatoryInput();
		}
		
		if (descriptorRef == up.getTaskDescriptor_OptionalInput()) {
			return up.getTask_OptionalInput();
		}
		
		if (descriptorRef == up.getTaskDescriptor_Output()) {
			return up.getTask_Output();
		}
		
		if (descriptorRef == up.getTaskDescriptor_SelectedSteps()) {
			return up.getTask_Steps();
		}
		
		if (descriptorRef == up.getRoleDescriptor_ResponsibleFor()) {
			return up.getRole_ResponsibleFor();
		}
		
		if (descriptorRef == up.getWorkProductDescriptor_DeliverableParts()) {
			return up.getDeliverable_DeliveredWorkProducts();
		}
		
		//To do: guidances need to be handled differently
//		if (descriptorRef == up.getBreakdownElement_Checklists() || descriptorRef == up.getBreakdownElement_Concepts()
//				|| descriptorRef == up.getBreakdownElement_Examples() || descriptorRef == up.getBreakdownElement_SupportingMaterials()
//				|| descriptorRef == up.getBreakdownElement_Guidelines() || descriptorRef == up.getBreakdownElement_ReusableAssets()
//				|| descriptorRef == up.getBreakdownElement_Templates() || descriptorRef == up.getBreakdownElement_Reports()
//				|| descriptorRef == up.getBreakdownElement_Toolmentor() || descriptorRef == up.getBreakdownElement_Estimationconsiderations()) {
//			return up.getDescriptor_GuidanceExclude();
//		}
		
		//...		
		return null;
	}
	
	
	public boolean isJunitTest() {
		return junitTest;
	}

	public void setJunitTest(boolean junitTest) {
		this.junitTest = junitTest;
	}
	
	public List<EReference> getExcludeRefList(Descriptor des) {
		List<EReference> list = new ArrayList<EReference>();

		if (des instanceof TaskDescriptor) {
			list.add(up.getTaskDescriptor_PerformedPrimarilyByExcluded());
			list.add(up.getTaskDescriptor_AdditionallyPerformedByExclude());
			list.add(up.getTaskDescriptor_MandatoryInputExclude());
			list.add(up.getTaskDescriptor_OptionalInputExclude());
			list.add(up.getTaskDescriptor_OutputExclude());

		} else if (des instanceof RoleDescriptor) {
			list.add(up.getRoleDescriptor_ResponsibleForExclude());

		} else if (des instanceof WorkProductDescriptor) {
			list.add(up.getWorkProductDescriptor_DeliverablePartsExclude());
		}

		return list;
	}
	
	public boolean isGuidanceListReference(EReference ref) {
		if (ref.isContainment() || !ref.isMany()) {
			return false;
		}
		if (ref == UmaPackage.eINSTANCE.getDescriptor_GuidanceAdditional()
				|| ref == UmaPackage.eINSTANCE.getDescriptor_GuidanceExclude()) {
			return false;
		}
		if (ref.getEType() instanceof EClass) {
			Object obj = UmaFactory.eINSTANCE.create((EClass) ref.getEType());
			return obj instanceof Guidance;
		}
		return false;
	}
	
	public Map<EReference, EReference> getGuidanceRefMap(EClass cls) {
		if (cls == up.getTask()) {
			if (taskGuidanceRefMap == null) {
				taskGuidanceRefMap = buildGuidanceMap(cls, up.getTaskDescriptor());
			}
			return taskGuidanceRefMap;
		}
		if (cls == up.getRole()) {
			if (roleGuidanceRefMap == null) {
				roleGuidanceRefMap = buildGuidanceMap(cls, up.getRoleDescriptor());
			}
			return roleGuidanceRefMap;
		}
		if (cls == up.getWorkProduct()) {
			if (workproductGuidanceRefMap == null) {
				workproductGuidanceRefMap = buildGuidanceMap(cls, up.getWorkProductDescriptor());
			}
			return workproductGuidanceRefMap;
		}
		return null;
	}
	
	private  Map<EReference, EReference> buildGuidanceMap(EClass cls, EClass desCls) {
		Map<EReference, EReference> resultMap = new HashMap<EReference, EReference>();
		
		Map<EClassifier, EReference> map = new HashMap<EClassifier, EReference>();
		for (EReference ref : desCls.getEAllReferences()) {
			if (isGuidanceListReference(ref)) {
				map.put(ref.getEType(), ref);
			}
		}
		
		for (EReference ref : cls.getEAllReferences()) {
			if (isGuidanceListReference(ref)) {
				EReference value = map.get(ref.getEType());
				if (value != null) {
					resultMap.put(ref, value);
				}
			}
		}
		
		return resultMap;
	}
	
	public void addOppositeFeature(MethodElement referencing,
			MethodElement referenced, EStructuralFeature feature) {
		if (referencing == null || referenced == null) {
			return;
		}
		OppositeFeature oppositeFeature = OppositeFeature
				.getOppositeFeature(feature);
		if (oppositeFeature == null) {
			return;
		}		
		MultiResourceEObject mreferenced = (MultiResourceEObject) referenced;
		mreferenced.oppositeAdd(oppositeFeature, referencing);
	}
	
	public void removeOppositeFeature(MethodElement referencing,
			MethodElement referenced, EStructuralFeature feature) {
		if (referencing == null || referenced == null) {
			return;
		}
		OppositeFeature oppositeFeature = OppositeFeature
				.getOppositeFeature(feature);
		if (oppositeFeature == null) {
			return;
		}
		MultiResourceEObject mreferenced = (MultiResourceEObject) referenced;
		mreferenced.oppositeRemove(oppositeFeature, referencing);
	}
	
	public Set<? extends VariabilityElement> collectVariabilityRelatives(VariabilityElement element) {
		Set<VariabilityElement> results = new HashSet<VariabilityElement>();
		collectVariabilityRelatives(element, results);
		return results;
	}
	
	private void collectVariabilityRelatives(VariabilityElement element,
			Set<VariabilityElement> results) {
		if (element == null || results.contains(element)) {
			return;
		}
		results.add(element);
		
		VariabilityElement base = element.getVariabilityBasedOnElement();
		if (base != null) {
			collectVariabilityRelatives(base, results);
		}
		for (VariabilityElement v : (List<VariabilityElement>) AssociationHelper
				.getImmediateVarieties(element)) {
			collectVariabilityRelatives(v, results);
		}
	}
	
	public IRealizationManager getRealizationManager(MethodConfiguration config) {
		ILibraryEditUtilProvider p = getProvider();				
		return p == null ? null : p.getRealizationManager(config);
	}
	
	public void removeAutoSynReferences(Process proc) {
		Set<Descriptor> desSet = LibraryEditUtil.getInstance().collectDescriptors(proc);
		for (Descriptor des : desSet) {
			removeAutoSynReferences(des);
		}
	}
		
	private void removeAutoSynReferences(Descriptor des) {
		if (autoSynReferences == null) {
			autoSynReferences = new HashSet<EReference>();
			autoSynReferences.add(up.getTaskDescriptor_PerformedPrimarilyByExcluded());
			autoSynReferences.add(up.getTaskDescriptor_AdditionallyPerformedByExclude());
			autoSynReferences.add(up.getTaskDescriptor_MandatoryInputExclude());
			autoSynReferences.add(up.getTaskDescriptor_OptionalInputExclude());
			autoSynReferences.add(up.getTaskDescriptor_OutputExclude());
			autoSynReferences.add(up.getRoleDescriptor_ResponsibleForExclude());
			autoSynReferences.add(up.getWorkProductDescriptor_DeliverablePartsExclude());
			autoSynReferences.add(up.getDescriptor_GuidanceExclude());
		}
		
		boolean oldDeliver = des.eDeliver();
		try {
			des.eSetDeliver(false);		
			for (EReference ref : des.eClass().getEAllReferences()) {
				if(autoSynReferences.contains(ref)) {
					List list = (List) des.eGet(ref);
					if (list != null && !list.isEmpty()) {
						list.clear();
					}
				}
			}
			DescriptorPropUtil.getDesciptorPropUtil().clearAllAutoSynProps(des);
		} finally {
			des.eSetDeliver(oldDeliver);
		}
		
		
	}
	
	public MethodElement getCalcualtedElement(MethodElement element, MethodConfiguration config) {
		ILibraryEditUtilProvider p = getProvider();				
		return p == null ? element : p.getCalculatedElement(element, config);
	}
	
	public boolean inConfig(MethodElement element, MethodConfiguration config) {
		ILibraryEditUtilProvider p = getProvider();				
		return p == null ? false : p.inConfig(element, config);
	}
	
	public class CollectElementFilter {
		public boolean accept(MethodElement element) {
			return true;
		}
		
		public boolean skipChildren(MethodElement element) {
			if (element instanceof MethodPlugin) {
				return false;
			}
			if (element instanceof MethodPackage) {
				return false;
			}
			
			return true;
		}
		
	}
	
	private void collectElements(MethodElement element,
			CollectElementFilter filter, Set<MethodElement> collected,
			Set<MethodElement> processed) {
		if (processed.contains(element)) {
			return;
		}
		processed.add(element);

		if (filter.accept(element)) {
			collected.add(element);
		}
		if (filter.skipChildren(element)) {
			return;
		}

		EList<EReference> refList = element.eClass().getEAllContainments();
		if (refList == null || refList.isEmpty()) {
			return;
		}
		for (EReference ref : refList) {
			Object obj = element.eGet(ref);
			if (obj instanceof MethodElement) {
				collectElements((MethodElement) obj, filter, collected,
						processed);

			} else if (obj instanceof List) {
				List list = (List) obj;
				for (Object itemObj : list) {
					if (itemObj instanceof MethodElement) {
						collectElements((MethodElement) itemObj, filter,
								collected, processed);
					}
				}
			}
		}
	}
		
	public Set<? extends MethodElement> getElementsUnder(MethodElement topElement, CollectElementFilter filter) {
		Set<MethodElement> set = new HashSet<MethodElement>();
		collectElements(topElement, filter, set, new HashSet<MethodElement>());
		return set;
	}
	
	public Set<WorkProduct> getAllWorkProducts(MethodElement topElement) {
		CollectElementFilter filter = new CollectElementFilter() {
			public boolean accept(MethodElement element) {
				return element instanceof WorkProduct;
			}
			
			public boolean skipChildren(MethodElement element) {
				if (element instanceof ProcessPackage) {
					return true;
				}
				
				return super.skipChildren(element);
			}
		};
		return (Set<WorkProduct> ) getElementsUnder(topElement, filter);
	}
	
	
}