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.configuration.ConfigurationHelper;
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;
			}
		}
		if (! canBeAutoSyned(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) {
		if (act instanceof Process) {
			if (! canBeAutoSyned((Process) act)) {
				return;
			}			
		}

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

	private boolean canBeAutoSyned(Process proc) {
		boolean ret = ConfigurationHelper.getDelegate().canBeConfigFree(proc);
		return ret;
	}
	
}
