package org.eclipse.epf.library.realization.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.ecore.EReference;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.edit.process.command.CustomizeDescriptorCommand;
import org.eclipse.epf.library.edit.process.command.ProcessCommandUtil;
import org.eclipse.epf.library.edit.realization.IRealizationManager;
import org.eclipse.epf.library.edit.realization.IRealizedDescriptor;
import org.eclipse.epf.library.edit.realization.IRealizedElement;
import org.eclipse.epf.library.edit.util.DescriptorPropUtil;
import org.eclipse.epf.library.edit.util.LibraryEditUtil;
import org.eclipse.epf.library.edit.util.ProcessScopeUtil;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.Process;
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.TaskDescriptor;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.util.Scope;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

public class RealizationManager implements IRealizationManager {

	private Map<MethodElement, IRealizedElement> elementMap;
	private MethodConfiguration config;
	private MethodConfiguration dynamicConfig;

	private boolean caching = false;
	private IPerspectiveListener perspectiveListener;
	private boolean localTiming = true;	
	
	public boolean isCaching() {
		return caching;
	}

	public void setCaching(boolean caching) {
		this.caching = caching;
	}

	private Map<MethodElement, IRealizedElement> getElementMap() {
		if (elementMap == null) {
			elementMap = new HashMap<MethodElement, IRealizedElement>();
		}
		return elementMap;
	}
	
	public RealizationManager(MethodConfiguration config) {
		this.config = config;
		init();
	}
	
	public void clearCacheData() {
		for (IRealizedElement element : getElementMap().values()) {
			((RealizedElement) element).dispose();
		}		
		elementMap = null;
	}
	
	public void dispose() {
		clearCacheData();
		
		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		if (window != null) {
			window.removePerspectiveListener(perspectiveListener);
		}
	}
	
	public MethodConfiguration getConfig() {
		if (config == null) {	//Default RealizationManager instance would not have a null config
			return dynamicConfig;
		}
		return config;
	}	

	public IRealizedElement getRealizedElement(MethodElement element) {
		IRealizedElement rElement = getElementMap().get(element);
		if (rElement == null) {
			rElement = newRealizedElement(element);
			getElementMap().put(element, rElement);
		}
		return rElement;
	}
	
	public IRealizedElement removeRealizedElement(MethodElement element) {
		return getElementMap().remove(element);
	}
	
	private void init() {
		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		if (window != null) {
			perspectiveListener = new IPerspectiveListener() {
				public void perspectiveActivated(IWorkbenchPage page,
						IPerspectiveDescriptor desc) {
					clearCacheData();
				}

				public void perspectiveChanged(IWorkbenchPage page,
						IPerspectiveDescriptor desc, String id) {
					clearCacheData();
				}
			};
			window.addPerspectiveListener(perspectiveListener);
		}
	}
	
	private IRealizedElement newRealizedElement(MethodElement element) {
		RealizedElement rElement = null;
		if (element instanceof TaskDescriptor) {
			rElement = new RealizedTaskDescriptor((TaskDescriptor) element);
			
		} else if (element instanceof RoleDescriptor) {
			rElement = new RealizedRoleDescriptor((RoleDescriptor) element);
			
		} else if (element instanceof WorkProductDescriptor) {
			rElement = new RealizedWorkProductDescriptor((WorkProductDescriptor) element);
			
		}
					
		rElement.setMgr(this);
		
		return rElement;
	}
	
	private MethodElement getLinkedElement(MethodElement element) {
		if (element instanceof RoleDescriptor) {
			return ((RoleDescriptor) element).getRole();
		}
		
		if (element instanceof WorkProductDescriptor) {
			return ((WorkProductDescriptor) element).getWorkProduct();
		}
		
		if (element instanceof TaskDescriptor) {
			return ((TaskDescriptor) element).getTask();
		}
		
		return null;
	}

	public Descriptor getDescriptor(Descriptor referencingDes, Activity parentAct, MethodElement element, EReference feature) {
		Descriptor descriptor = getDescriptor_(referencingDes, parentAct, element, feature);
		if (feature == IRealizedDescriptor.ArtifactDescriptor_ContainedArtifacts) {
			return descriptor;
		}		
		
		boolean oldDeliver = referencingDes.eDeliver();
		referencingDes.eSetDeliver(false);
		LibraryEditUtil libEditUtil = LibraryEditUtil.getInstance();
		try {
			if (feature.isMany()) {
				List listValue = (List) referencingDes.eGet(feature);
				if (listValue != null) {
					listValue.add(descriptor);
					libEditUtil.addOppositeFeature(referencingDes, descriptor, feature);
				}
			} else {
				referencingDes.eSet(feature, descriptor);
				libEditUtil.addOppositeFeature(referencingDes, descriptor, feature);
			}
		} finally {
			referencingDes.eSetDeliver(oldDeliver);
		}

		return descriptor;
	}
	
	private Descriptor getDescriptor_(Descriptor referencingDes, Activity parentAct, MethodElement element, EReference feature) {
		if (parentAct == null) {
			return null;
		}
		
		Object foundDes = ProcessCommandUtil.getBestDescriptor(element, parentAct, getConfig());
		if (foundDes instanceof Descriptor) {
			return (Descriptor) foundDes;
		}
		
		foundDes = ProcessCommandUtil.getInheritedDescriptor(element, parentAct, getConfig());
		if (foundDes instanceof Descriptor) {
			return (Descriptor) foundDes;
		}
		
		Descriptor descriptor = null;
		if (element instanceof Role) {
			RoleDescriptor rd = UmaFactory.eINSTANCE.createRoleDescriptor();
			rd.setRole((Role) element);
			descriptor = rd;
			
		} else if (element instanceof Task) {
			TaskDescriptor td = UmaFactory.eINSTANCE.createTaskDescriptor();
			td.setTask((Task) element);
			descriptor = td;
			
		} else if (element instanceof WorkProduct) {
			WorkProductDescriptor wpd = UmaFactory.eINSTANCE.createWorkProductDescriptor();
			wpd.setWorkProduct((WorkProduct) element);
			descriptor = wpd;
		}
		
		if (debug) {
			System.out.println("LD> Creating descriptor: " + descriptor); //$NON-NLS-1$
		}
		
		if (descriptor == null) {
			return null;
		}
		
		DescriptorPropUtil.getDesciptorPropUtil().setCreatedByReference(descriptor, true);
			
		String presentationName = element.getPresentationName();
		descriptor.setName(element.getName());
		descriptor.setPresentationName(StrUtil.isBlank(presentationName) ? element
				.getName() : presentationName);
		String guid = UmaUtil.generateGUID();
		descriptor.setBriefDescription(element.getBriefDescription());

		addToProcess(parentAct, descriptor, feature);	
		
		return descriptor;
	}
	
	private void addToProcess(Activity parent, Descriptor referencedDes,
			EReference feature) {
		UmaPackage up = UmaPackage.eINSTANCE;
		ProcessPackage pkg = (ProcessPackage) parent.eContainer();

		boolean oldParentDeliver = parent.eDeliver();
		boolean oldPkgDeliver = pkg.eDeliver();
		boolean oldReferencedDesDeliver = referencedDes.eDeliver();
		parent.eSetDeliver(false);
		pkg.eSetDeliver(false);

		try {
			parent.getBreakdownElements().add(referencedDes);
			pkg.getProcessElements().add(referencedDes);

			if (feature == up.getWorkProductDescriptor_DeliverableParts()) {
				referencedDes.eSetDeliver(false);
				referencedDes.setSuperActivities(null);
			}
		} finally {
			parent.eSetDeliver(oldParentDeliver);
			pkg.eSetDeliver(oldPkgDeliver);
			if (referencedDes.eDeliver() != oldReferencedDesDeliver) {
				referencedDes.eSetDeliver(oldReferencedDesDeliver);
			}
		}

	}
	
	public void updateProcessModel(Process proc) {
		clearCacheData();
		setCaching(true);
		updateProcessModel(proc, new HashSet<Activity>());
		clearCacheData();
		setCaching(false);
	}
	
	public void elementUpdateProcessModel(Process proc,
			Set<MethodElement> changedElementSet) {

		Set<Activity> actCollectedSet = new HashSet<Activity>();
		collectActivitiesToUpdate(proc, actCollectedSet,
				new HashSet<Activity>(), changedElementSet);
		Set<Activity> updatedActSet = new HashSet<Activity>();
		clearCacheData();
		setCaching(true);
		for (Activity act : actCollectedSet) {
			this.updateModelImpl(act, updatedActSet, false);
		}
		clearCacheData();
		setCaching(false);		
	}
	
	private void collectActivitiesToUpdate(Activity act,
			Set<Activity> actCollectedSet, Set<Activity> actProcessedSet,
			Set<MethodElement> changedElementSet) {
		if (actProcessedSet.contains(act)) { // extra precaution to prevent infinite loop
			return;
		}
		actProcessedSet.add(act);
		
		Activity baseAct = (Activity) act.getVariabilityBasedOnElement();
		if (baseAct != null) {
			collectActivitiesToUpdate(baseAct, actCollectedSet, actProcessedSet, changedElementSet);
		}

		List<BreakdownElement> beList = act.getBreakdownElements();
		for (int i = 0; i < beList.size(); i++) {
			BreakdownElement be = beList.get(i);
			if (be instanceof Descriptor && !actCollectedSet.contains(act)) {
				MethodElement element = getLinkedElement((Descriptor) be);
				if (changedElementSet.contains(element)) {
					actCollectedSet.add(act);

				} else if (be instanceof Descriptor) {
					if (changedElementSet.contains(be)) {
						actCollectedSet.add(act);
					}
				}
			} else if (be instanceof Activity) {
				collectActivitiesToUpdate((Activity) be, actCollectedSet,
						actProcessedSet, changedElementSet);
			}
		}
	}

	private void updateProcessModel(Process proc, Set<Activity> updatedActSet) {
		if (! ProcessUtil.isSynFree()) {
			if (! ProcessScopeUtil.getInstance().isConfigFree(proc)) {
				return;
			}
		}
		long time = 0;
		if (timing && localTiming) {
			time = System.currentTimeMillis();
		}
		updateModelImpl(proc, updatedActSet, true);
		if (timing && localTiming) {
			time = System.currentTimeMillis() - time;
			System.out.println("LD> updateModel: " + time); //$NON-NLS-1$
		}
	}
	
	public void updateActivityModel(Activity act) {
		clearCacheData();
		setCaching(true);
		updateModelImpl(act, new HashSet<Activity>(), false);
		clearCacheData();
		setCaching(false);
	}
	
	private void updateModelImpl(Activity act, Set<Activity> updatedActSet, boolean recursive) {
		if (updatedActSet.contains(act)) {
			return;
		}
		//System.out.println("LD> updateModelImpl, act: " + act);
		
		updatedActSet.add(act);
		Activity baseAct = (Activity) act.getVariabilityBasedOnElement();
		if (baseAct != null) {
			updateModelImpl(baseAct, updatedActSet, recursive);
		}
		if (! ProcessUtil.isSynFree()) {
			Process proc = ProcessUtil.getProcess(act);
			if (proc == null || ! ProcessScopeUtil.getInstance().isConfigFree(proc)) {
				return;
			}
		}
				
		if (config == null) {
			Process proc = ProcessUtil.getProcess(act);
			Scope scope = ProcessScopeUtil.getInstance().getScope(proc);
			if (scope != null) {
				dynamicConfig = scope;
			} else {
				dynamicConfig = LibraryService.getInstance()
						.getCurrentMethodConfiguration();
			}
		}
		
		DescriptorPropUtil propUtil = DescriptorPropUtil.getDesciptorPropUtil();
		
		Set<Descriptor> tdReferencedSet = new HashSet<Descriptor>();
		Set<Descriptor> seenSet = new HashSet<Descriptor>();
		List<Descriptor> rdwpdList = new ArrayList<Descriptor>();
		List<BreakdownElement> beList =  act.getBreakdownElements();
		Set<Descriptor> localUseSet = new HashSet<Descriptor>(); 
		for (int i = 0; i < beList.size(); i++) {
			BreakdownElement be = beList.get(i);
			if (be instanceof Activity) {
				if (recursive) {
					updateModelImpl((Activity) be, updatedActSet, recursive);
				}
				
			} else if (be instanceof TaskDescriptor) {
				TaskDescriptor td = (TaskDescriptor) be;
				Descriptor greenParent = propUtil.getGreenParentDescriptor(td);
				if (greenParent != null) {
					CustomizeDescriptorCommand.updateFromGreenParent(greenParent, td, false);
				}
				
				collectAllReferences(td, tdReferencedSet, seenSet);

			} else if (be instanceof RoleDescriptor) {
				RoleDescriptor rd = (RoleDescriptor) be;
				rdwpdList.add(rd);
				
			} else if (be instanceof WorkProductDescriptor) {
				WorkProductDescriptor wpd = (WorkProductDescriptor) be;
				rdwpdList.add(wpd);
			}
			
			if (be instanceof Descriptor) {
				localUseSet.addAll(propUtil.getLocalUsedDescriptors((Descriptor) be));
			}
		}
		
		Set<Descriptor> toRemovedSet = new HashSet<Descriptor>();
		for (Descriptor des : rdwpdList) {
			collectAllReferences(des, null, seenSet);
			
			if (des instanceof TaskDescriptor || localUseSet.contains(des) ||
					! propUtil.isCreatedByReference(des)) {
				continue;
			}
			if (!tdReferencedSet.contains(des)) {
//				act.getBreakdownElements().remove(des);
				toRemovedSet.add(des);
			}
		}
		for (Descriptor des : toRemovedSet) {
			if (! ProcessUtil.checkDescriptorReferences(toRemovedSet, des)) {
				act.getBreakdownElements().remove(des);
			}
		}
		
		beList =  act.getBreakdownElements();
		for (int i = 0; i < beList.size(); i++) {
			BreakdownElement be = beList.get(i);
			if (be instanceof Descriptor) {
				RealizedDescriptor rdes = (RealizedDescriptor) getRealizedElement(be);	
				rdes.updateStringValues();
			}
		}
				
	}
	
	private void collectAllReferences(Descriptor des, Set<Descriptor> collectingSet, Set<Descriptor> seenSet) {
		if (seenSet.contains(des)) {
			return;
		}
		seenSet.add(des);
		
		RealizedDescriptor rdes = (RealizedDescriptor) getRealizedElement(des);
		Set<Descriptor> references = rdes.updateAndGetAllReferenced();
		if (collectingSet != null) {
			collectingSet.addAll(references);
		}
		for (Descriptor ref : references) {
			collectAllReferences(ref, collectingSet, seenSet);
		}
	}
	
	public void updateAllProcesseModels() {		
		boolean oldLocalTiming = localTiming;
		long time = 0;
		if (timing) {
			time = System.currentTimeMillis();
			localTiming = false;
		}

		Set<Activity> updatedActSet = new HashSet<Activity>();
		clearCacheData();
		setCaching(true);
		for (Process proc : LibraryEditUtil.getInstance().collectProcessesFromConfig(
				getConfig())) {
			updateProcessModel(proc, updatedActSet);
		}
		clearCacheData();
		setCaching(false);
		if (timing) {
			time = System.currentTimeMillis() - time;
			System.out.println("LD> beginPublish: " + time); //$NON-NLS-1$
			localTiming = oldLocalTiming;
		}
	}

	
}
