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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.epf.common.utils.XMLUtil;
import org.eclipse.epf.library.edit.LibraryEditPlugin;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.edit.command.MethodElementSetPropertyCommand;
import org.eclipse.epf.library.edit.meta.TypeDefUtil;
import org.eclipse.epf.library.edit.uma.ExtendReferenceMap;
import org.eclipse.epf.library.edit.uma.MethodElementExt;
import org.eclipse.epf.library.edit.uma.MethodElementExt.WorkProductStateExt;
import org.eclipse.epf.uma.Constraint;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodElementProperty;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Practice;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject.ExtendObject;
import org.eclipse.epf.uma.util.UmaUtil;
import org.w3c.dom.Element;

public class MethodElementPropUtil {
	
	public static final String infoSeperator = "/"; 							//$NON-NLS-1$
	
	public static final String CONSTRAINT_WPStates = "constraint_wpStates";		//$NON-NLS-1$
	public static final String Package_supporting = "pakage_supporting";		//$NON-NLS-1$
	public static final String Me_references = "me_references";					//$NON-NLS-1$

	private static MethodElementPropUtil methodElementPropUtil = new MethodElementPropUtil();
	public static MethodElementPropUtil getMethodElementPropUtil(IActionManager actionManager) {
		return new MethodElementPropUtil(actionManager);
	}
	
	public static MethodElementPropUtil getMethodElementPropUtil() {
		return methodElementPropUtil;
	}
	
	private IActionManager actionManager;
	
	protected MethodElementPropUtil() {		
	}
	
	protected MethodElementPropUtil(IActionManager actionManager) {
		this.actionManager = actionManager;
	}	
	
	public IActionManager getActionManager() {
		return actionManager;
	}
	
	public String getStringValue(MethodElement element, String propName) {		
		MethodElementProperty prop = MethodElementPropertyHelper.getProperty(element, propName);
		if (prop == null) {
			return null;
		}
		return prop.getValue();
	}
	
	public void setStringValue(MethodElement element, String propName, String value) {	
		setProperty(element, propName, value);
	}
	
	public boolean isSupporting(ContentPackage pkg) {
		 Boolean value = getBooleanValue(pkg, Package_supporting);
		 return value == null ? false : value.booleanValue();
	}
	
	public boolean ancestorIsSupporting(ContentPackage pkg) {
		EObject parent = pkg.eContainer();
		while(parent != null) {
			if (parent instanceof MethodPlugin) { 
				return ((MethodPlugin) parent).isSupporting();
			}
			if (parent instanceof ContentPackage && isSupporting((ContentPackage) parent)) {
				return true;
			}
			parent = parent.eContainer();
		}
		return false;
	}
		
	public void updatePackageSupportingBits(Collection<? extends MethodPackage> pkgs, boolean supporting) {
		for (MethodPackage mpkg : pkgs) {
			if (! (mpkg instanceof ContentPackage)) {
				continue;
			}
			ContentPackage pkg = (ContentPackage) mpkg;
			boolean pkgIsSupporting = isSupporting(pkg);
			if (pkgIsSupporting && supporting) {
				continue;	
			}
			if (pkgIsSupporting != supporting) {
				setBooleanValue(pkg, Package_supporting, supporting);
			}
			updatePackageSupportingBits(pkg.getChildPackages(), supporting);
		}
	}
	
	public void setSupporting(ContentPackage pkg, boolean value) {
		 setBooleanValue(pkg, Package_supporting, value);
	}
	
	protected Boolean getBooleanValue(MethodElement element, String propName) {		
		MethodElementProperty prop = MethodElementPropertyHelper.getProperty(element, propName);
		if (prop == null) {
			return null;
		}
		String value = prop.getValue();
		return Boolean.parseBoolean(value);
	}
	
	protected void setBooleanValue(MethodElement element, String propName, boolean value) {	
		String strValue = value ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
		setProperty(element, propName, strValue);
	}
	
	protected Integer getIntValue(MethodElement element, String propName) {		
		MethodElementProperty prop = MethodElementPropertyHelper.getProperty(element, propName);
		if (prop == null) {
			return null;			
		}
		String value = prop.getValue();
		return Integer.parseInt(value);
	}
	
	protected void setIntValue(MethodElement element, String propName, int value) {	
		String strValue = Integer.toString(value);
		setProperty(element, propName, strValue);
	}
	
	private void setProperty(MethodElement e, String propName, String propValue) {
		if (getActionManager() == null) {
			MethodElementPropertyHelper.setProperty(e, propName, propValue);
		} else {
			MethodElementSetPropertyCommand cmd = new MethodElementSetPropertyCommand(
					e, propName, propValue);
			getActionManager().execute(cmd);
		}
	}
	
	protected void removeProperty(MethodElement e, String propName) {
		MethodElementPropertyHelper.removeProperty(e, propName);
	}
	
	public final MethodElementExt getExtendObject(MethodElement element, boolean create) {
		if (element == null) {
			return null;
		}
		MultiResourceEObject mobj = (MultiResourceEObject) element;		
		ExtendObject obj = mobj.getExtendObject();
		if (create) {
			ExtendObject newObj = createExtendObjectIfNeeded(element, obj);
			if (newObj != obj) {
				obj = newObj;
				mobj.setExtendObject(obj);
			}
		}
		return (MethodElementExt) obj;
	}
	
	public Map<Object, Object> getExtendedPropertyMap(MethodElement element, boolean create) {
		MethodElementExt ext = getExtendObject(element, create);
		return ext == null ? null : ext.getExtendedPropertyMap(create);
	}
	
	protected MethodElementExt createExtendObjectIfNeeded(MethodElement element, ExtendObject oldObj) {
		if (isWorkProductState(element)) {
			if (oldObj instanceof WorkProductStateExt) {
				return (WorkProductStateExt) oldObj;
			}
			return new WorkProductStateExt((Constraint) element, oldObj);
		}
		if (oldObj instanceof MethodElementExt) {
			return (MethodElementExt) oldObj;
		}
		return new MethodElementExt(element, oldObj);
	}
	
	public boolean isWorkProductState(MethodElement element) {
		if (!(element instanceof Constraint)) {
			return false;
		}
		Constraint c = (Constraint) element;
		return ConstraintManager.Plugin_wpState.equals(c.getName());
	}
	
	public void addReferenceInfo(MethodElement owner, MethodElement reference, String propName, String refName) {
		String oldValue = getStringValue(owner, propName);
		String newValue = reference.getGuid().concat(infoSeperator).concat(refName);

		if (oldValue != null && oldValue.length() > 0) {			
			String[] infos = oldValue.split(infoSeperator); 
			
			int sz = infos.length / 2; 		
			for (int i = 0; i < sz; i++) {
				int i1 = i*2;
				int i2 = i1 + 1;
				String iGuid = infos[i1];
				String iFeature = infos[i2];
				if (iGuid.equals(reference.getGuid()) && iFeature.equals(refName)) {
					return;
				} 
			}
			
			newValue = oldValue.concat(infoSeperator).concat(newValue);
		}				
		setStringValue(owner, propName, newValue);
	}
	
	public void removeReferenceInfo(MethodElement owner, MethodElement reference, String propName, String refName) {
		String oldValue = getStringValue(owner, propName);
		if (oldValue == null || oldValue.length() == 0) {
			return;
		}
		boolean removed = false;
		String newValue = ""; //$NON-NLS-1$

		if (oldValue != null && oldValue.length() > 0) {			
			String[] infos = oldValue.split(infoSeperator); 
			
			int sz = infos.length / 2; 		
			for (int i = 0; i < sz; i++) {
				int i1 = i*2;
				int i2 = i1 + 1;
				String iGuid = infos[i1];
				String iFeature = infos[i2];
				if (iGuid.equals(reference.getGuid()) && iFeature.equals(refName)) {
					removed = true;		
				} else {
					if (newValue.length() > 0) {
						newValue = newValue.concat(infoSeperator);
					}
					newValue = newValue.concat(iGuid.concat(infoSeperator).concat(iFeature));
				}
			}

		}
		
		if (removed) {
			setStringValue(owner, propName, newValue);
		}

	}
	
	public List<? extends MethodElement> extractElements(MethodElement propertyOwner, String propName, String refName,
			Set<? extends MethodElement> validSet) {
		List<MethodElement> elements = new ArrayList<MethodElement>();
		
		String value = getStringValue(propertyOwner, propName);
		if (value == null || value.length() == 0) {
			return elements;
		}
		
		String[] infos = value.split(infoSeperator);
		if (infos == null || infos.length == 0) {
			return elements;
		}
		
		boolean modified = false;
		String newValue = ""; //$NON-NLS-1$
		int sz = infos.length / 2; 		
		for (int i = 0; i < sz; i++) {
			int i1 = i*2;
			int i2 = i1 + 1;
			String iGuid = infos[i1];
			String iRefName = infos[i2];			
			if (refName.equals(iRefName)) {
				MethodElement element = LibraryEditUtil.getInstance().getMethodElement(iGuid);
				if (element != null && validSet.contains(element)) {
					elements.add(element);
					if (newValue.length() > 0) {
						newValue = newValue.concat(infoSeperator);
					}
					newValue = newValue.concat(iGuid.concat(infoSeperator).concat(iRefName));
				} else {
					modified = true;
				}
			} else {
				if (newValue.length() > 0) {
					newValue = newValue.concat(infoSeperator);
				}
				newValue = newValue.concat(iGuid.concat(infoSeperator).concat(iRefName));
			}
		}		
		if (modified) {
			setStringValue(propertyOwner, propName, newValue);
		}
		
		return elements;
	}

	public boolean isTransientElement(MethodElement element) {
		MethodElementExt extObj = getExtendObject(element, false);
		return extObj == null ? false : extObj.isTransientElement();
	}

	public void setTransientElement(MethodElement element,
			boolean transientElement) {
		if (!transientElement && getExtendObject(element, false) == null) {
			return;
		}
		MethodElementExt extObj = getExtendObject(element, true);
		extObj.setTransientElement(transientElement);

	}
	
	//-> For work product state objects
	public void addToAssignedToWps(WorkProduct wp, Constraint state) {
		if (! isWorkProductState(state)) {
			return;
		}
		MethodElementExt extObj = getExtendObject(state, true);
		if (! (extObj instanceof WorkProductStateExt)) {
			return;
		}
		((WorkProductStateExt) extObj).addToAssignedToWps(wp);
	}
	
	public void removeFromAssignedToWps(WorkProduct wp, Constraint state) {
		MethodElementExt extObj = getExtendObject(state, false);
		if (! (extObj instanceof WorkProductStateExt)) {
			return;
		}
		((WorkProductStateExt) extObj).removeFromAssignedToWps(wp);
	}
	
	public List<WorkProduct> getAssignedToWorkProducts(Constraint state) {
		MethodPlugin plugin = UmaUtil.getMethodPlugin(state);
		if (plugin != null) {
			MethodPluginPropUtil.getMethodPluginPropUtil().loadWpStates(plugin);
		}	
		
		MethodElementExt extObj = getExtendObject(state, false);
		if (! (extObj instanceof WorkProductStateExt)) {
			return Collections.EMPTY_LIST;
		}
		return ((WorkProductStateExt) extObj).getAssignedToWorkProducts();
	}
	//<- For work product state objects
	
	//Get elements stored as guids in the property specified by propName
	protected Set<? extends MethodElement> getElements(MethodElement owner, String propName, EClass type) {
		Set<MethodElement> elements = new HashSet<MethodElement>();
		if (owner == null) {
			return elements;
		}
		
		String value = getStringValue(owner, propName);
		String[] guids = value == null || value.trim().length() == 0 ? null : value.split(infoSeperator);

		if (guids == null || guids.length == 0) {
			return elements;
		}

		for (int i = 0; i < guids.length; i++) {
			MethodElement element = LibraryEditUtil.getInstance()
					.getMethodElement(guids[i]);
			if (element != null && (type == null || type.isSuperTypeOf(element.eClass()))) {
				elements.add(element);
			}
		}

		return elements;

	}
	
	//Store elements as guids in the property specified by propName
	protected void setElements(MethodElement owner, String propName, Set<? extends MethodElement> elements, EClass type) {
		if (owner == null) {
			return;
		}
		
		String value = "";	//$NON-NLS-1$
		List<String> guidList = new ArrayList<String>();
		if (elements != null) {
			for (MethodElement element : elements) {
				if (element != null && (type == null || type.isSuperTypeOf(element.eClass()))) {
					guidList.add(element.getGuid());
				}
			}
			Collections.sort(guidList);
			for (String guid : guidList) {
				if (value.length() != 0) {
					value += infoSeperator;
				}
				value += guid;
			}
		}
		setStringValue(owner, propName, value);
	}
	
	public XmlEditUtil newXmlEditUtil() {
		return new XmlEditUtil(this);
	}
	
	public void storeReferences(MethodElement element, boolean rollback)  throws Exception  {
		MeXmlEditUtil meXmlEditUtil = new MeXmlEditUtil(element, this);
		meXmlEditUtil.storeReferences(rollback);
	}
	
	public String getReferencesXml(MethodElement element, boolean rollback) throws Exception  {
		MeXmlEditUtil meXmlEditUtil = new MeXmlEditUtil(element, this);
		return meXmlEditUtil.getReferencesXml(rollback);
	}
	
	public boolean hasUdtList(MethodElement element) {
		return hasReferences(element);
	}
	
	public boolean hasReferences(MethodElement element) {
		String value = getStringValue(element, Me_references);
		return value != null && value.length() > 0;
	}
	
	public List<Practice> getUdtList(MethodElement element, boolean toModify) {
		List<Practice> value = (List<Practice>) getReferenceValue(UmaUtil.MethodElement_UdtList.getName(), element, toModify);
		if (value == null) {
			return new ArrayList<Practice>();
		}
		return value;
	}
	
	public List<MethodElement> getQReferenceListById(MethodElement element, String qualifierId, boolean toModify) {
		String referenceName = qualifierId;
		List<MethodElement> value = (List<MethodElement>) getReferenceValue(
				referenceName, element, toModify);
		if (value == null) {
			return new ArrayList<MethodElement>();
		}
		return value;
	}	
	
	public void notifyElemetSaved(MethodElement element) {
		ExtendReferenceMap map = getCachedExtendReferenceMap(element, false);
		if (map == null) {
			return;
		}
		map.notifyOwnerElementSaved();
	}
	
	public void addOpposite(String referenceName, MethodElement thisElement, MethodElement otherElement) {
		ExtendReferenceMap map = getCachedExtendReferenceMap(thisElement, false);
		if (map == null) {
			return;
		}
		map.addOpposite(referenceName, otherElement);
	}
	
	public void removeOpposite(String referenceName, MethodElement thisElement, MethodElement otherElement) {
		ExtendReferenceMap map = getCachedExtendReferenceMap(thisElement, false);
		if (map == null) {
			return;
		}
		map.removeOpposite(referenceName, otherElement);
	}
	
	protected Object getReferenceValue(String referenceName, MethodElement element, boolean toModify) {
		MeXmlEditUtil meXmlEditUtil = new MeXmlEditUtil(element, this);
		return meXmlEditUtil.getReferenceValue(referenceName, element, toModify);
	}
	
	protected ExtendReferenceMap getCachedExtendReferenceMap(MethodElement element, boolean toModify) {
		MethodElementExt extendObject = getExtendObject(element, toModify);
		if (extendObject == null) {
			return null;
		}
		return extendObject.getExtendReferenceMap(toModify);
	}
	
	public ExtendReferenceMap getExtendReferenceMap(MethodElement element, boolean toModify) {
		MeXmlEditUtil meXmlEditUtil = new MeXmlEditUtil(element, this);
		return meXmlEditUtil.getExtendReferenceMap(element, toModify);
	}
	
	private static class MeXmlEditUtil extends XmlEditUtil {
		
		private MethodElement element;
		
		public MeXmlEditUtil(MethodElement element, MethodElementPropUtil propUtil) {
			super(propUtil);
			this.element = element;
		}
		
		public void storeReferences(boolean rollback) throws Exception  {
			if (! buildReferencesElement(rollback)) {
				return;
			}			
			storeToOwner(element, Me_references);
		}
		
		public Object getReferenceValue(String referenceName, MethodElement element, boolean toModify) {
			ExtendReferenceMap map = getExtendReferenceMap(element, toModify);
			return map == null ? null : map.get(referenceName, toModify);
		}
		
		public ExtendReferenceMap getExtendReferenceMap(MethodElement element, boolean toModify) {
			ExtendReferenceMap map = getPropUtil().getCachedExtendReferenceMap(element, toModify);
			if (map != null && map.isRetrieved() || ! getPropUtil().hasUdtList(element)) {
				return map;
			}

			String xmlString = getPropUtil().getStringValue(element, Me_references);
			Element firstElement = null;
			try {
				firstElement = loadDocumentAndGetFirstElement(xmlString);
			} catch (Exception e) {
				LibraryEditPlugin.getDefault().getLogger().logError(e);
				firstElement = null;
			}
			if (firstElement != null) {
//				map = getExtendReferenceMap(element, true);	
				map = getPropUtil().getCachedExtendReferenceMap(element, true);
				map.retrieveReferencesFromElement(firstElement);
			}

			return map;
		}
		
		private boolean buildReferencesElement(boolean rollback) throws Exception {
			ExtendReferenceMap map = getExtendReferenceMap(element, false);
			if (map == null) {
				return false;
			}
			Element firstElement = createFirstElement(Me_references);
			map.storeReferencesToElement(firstElement, rollback);
			return true;
		}		
		
		public String getReferencesXml(boolean rollback) throws Exception  {
			if (! buildReferencesElement(rollback)) {
				return null;
			}			
			return XMLUtil.toXmlString(getDocument());
		}
		
	}
	
	public Object eGet(EObject eobj, EStructuralFeature feature, boolean toModify) {
		return TypeDefUtil.getInstance().eGet(eobj, feature, toModify);
	}
	
}
