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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.emf.edit.ui.action.ValidateAction.EclipseResourcesUtil;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.LibraryServiceListener;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.TransientGroupItemProvider;
import org.eclipse.epf.library.edit.element.TransientContentPackageItemProvider;
import org.eclipse.epf.library.edit.navigator.ContentItemProvider;
import org.eclipse.epf.library.edit.navigator.MethodPackagesItemProvider;
import org.eclipse.epf.library.edit.navigator.ProcessesItemProvider;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.persistence.FileManager;
import org.eclipse.epf.persistence.util.PersistenceUtil;
import org.eclipse.epf.uma.ContentCategory;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.Discipline;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.RoleSet;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.ui.ide.IDE;

/**
 * @author Phong Nguyen Le
 * @since  1.1
 */
public class LibraryValidationMarkerHelper extends EclipseResourcesUtil {	
	public static final LibraryValidationMarkerHelper INSTANCE = new LibraryValidationMarkerHelper();
	public static final String GUID = "guid"; //$NON-NLS-1$
	
	private static interface IParentProvider {
		final IParentProvider containerProvider = new IParentProvider() {

			public Collection<?> getParents(Object object) {
				if(object instanceof EObject) {
				return Collections.singleton(((EObject)object).eContainer());
				}
				return Collections.emptyList();
			}
			
		};
		
		final IParentProvider parentCustomCategoryProvider = new IParentProvider() {

			public Collection<?> getParents(Object object) {
				if(object instanceof CustomCategory) {
					return AssociationHelper.getCustomCategories((CustomCategory)object);
				}
				return Collections.emptyList();
			}
			
		};
		
		final IParentProvider parentStandardCategoryProvider = new IParentProvider() {

			public Collection<?> getParents(Object object) {
				if(object instanceof Discipline) {
					Discipline discipline = (Discipline) object;
					List parentDisciplines = AssociationHelper.getDiscipline(discipline);
					List disciplineGroupings = AssociationHelper.getDisciplineGroups(discipline);
					if(!parentDisciplines.isEmpty() && !disciplineGroupings.isEmpty()) {
						Collection<Object> parents = new ArrayList<Object>(disciplineGroupings);
						parents.addAll(parentDisciplines);
						return parents;
					}
					else {
						return parentDisciplines.isEmpty() ? disciplineGroupings : parentDisciplines;
					}
				}
				else if(object instanceof RoleSet) {
					return AssociationHelper.getRoleSetGroups((RoleSet) object);
				}
				return Collections.emptyList();
			}
			
		};
		
		Collection<?> getParents(Object object);
	}
	
	private static class ErrorCalculator extends HashMap<MethodPlugin, Set<MethodElement>> {		
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public ErrorCalculator() {
			super();
			initialize();
			LibraryService.getInstance().addListener(new LibraryServiceListener() {
				public void libraryOpened(MethodLibrary library) {
					initialize();
				}
				
				public void libraryClosed(MethodLibrary library) {
					clear();
				}
				
				public void libraryReopened(MethodLibrary library) {
					initialize();
				}				
			});
		}
		
		private void initialize() {
			clear();
			
			// fill this set with containers of marked objects
			//
			MethodLibrary lib = LibraryService.getInstance().getCurrentMethodLibrary();
			if(lib != null) {
				IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
				try {
					IMarker[] markers = wsRoot.findMarkers(INSTANCE.getMarkerID(), false, IResource.DEPTH_INFINITE);
					for (int i = 0; i < markers.length; i++) {
						IMarker marker = markers[i];
						String guid = (String) marker.getAttribute(GUID);
						MethodElement e = LibraryService.getInstance().getCurrentLibraryManager().getMethodElement(guid);
						if(e != null) {
							if(e.eIsProxy()) {
								e = (MethodElement) PersistenceUtil.resolve(e,
										LibraryService.getInstance()
												.getCurrentMethodLibrary()
												.eResource().getResourceSet());
							}
							// add the element to this set
							//
							addError(e);
						}
					}
				} catch (CoreException e) {
				}
			}
		}
		
		public void addError(MethodElement e) {
			MethodPlugin plugin = UmaUtil.getMethodPlugin(e);
			if(plugin != null) {
				Set<MethodElement> elements = get(plugin);
				if(elements == null) {
					elements = new HashSet<MethodElement>();
					put(plugin, elements);
				}
				elements.add(e);
			}
		}
		
		public void removeError(MethodElement e) {
			MethodPlugin plugin = UmaUtil.getMethodPlugin(e);
			if(plugin != null) {
				Set<MethodElement> elements = get(plugin);
				if(elements != null) {
					elements.remove(e);
					if(elements.isEmpty()) {
						remove(plugin);
					}
				}
			}
		}
		
		public boolean hasErrors(MethodElement e) {
			MethodPlugin plugin = UmaUtil.getMethodPlugin(e);
			if(plugin != null) {
				Set<MethodElement> elements = get(plugin);
				if(elements != null) {
					if(elements.contains(e)) {
						return true;
					}

					// check if e is container of any error element
					//
					HashSet<Object> processedChildren = null;
					for (MethodElement me : elements) {
						if(UmaUtil.isContainedBy(me, e)) {
							return true;
						}
						if(me instanceof CustomCategory) {
							if(processedChildren == null) {
								processedChildren = new HashSet<Object>();
							}
							else {
								processedChildren.clear();
							}
							if(isParentOf(me, e, IParentProvider.parentCustomCategoryProvider, processedChildren)) {
								return true;
							}
						}
						else if(me instanceof ContentCategory) {
							// me must be a standard category
							// currently all content packages that contain
							// standard categories are not contained by
							// predefined content package "Standard Categories"
							// we need to handle this specially here
							//
							if(e instanceof ContentPackage && e == UmaUtil.findContentPackage(plugin, ModelStructure.DEFAULT.standardCategoryPath)) {
								return true;
							}
							if(processedChildren == null) {
								processedChildren = new HashSet<Object>();
							}
							else {
								processedChildren.clear();
							}
							if(isParentOf(me, e, IParentProvider.parentStandardCategoryProvider, processedChildren)) {
								return true;
							}
						}
					}
				}
			}
			return false;
		}
		
		private static boolean isParentOf(Object child, Object parent, IParentProvider parentProvider, Set<Object> processedChildren) {
			processedChildren.add(child);
			for (Object myParent : parentProvider.getParents(child)) {				
				if(myParent == parent) {
					return true;
				}
				if(!processedChildren.contains(myParent) && isParentOf(myParent, parent, parentProvider, processedChildren)) {
					return true;
				}				
			}
			return false;
		}
	}
	
	private static ErrorCalculator errorCalculator = new ErrorCalculator();	
	
	/* (non-Javadoc)
	 * @see org.eclipse.emf.common.ui.MarkerHelper#getFile(org.eclipse.emf.common.util.URI)
	 */
	protected IFile getFile(URI uri) {
		if(uri.isFile()) {
			return (IFile) FileManager.getResourceForLocation(uri.toFileString());
		}
		return super.getFile(uri);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.emf.edit.ui.util.EditUIMarkerHelper#adjustMarker(org.eclipse.core.resources.IMarker, org.eclipse.emf.common.util.Diagnostic)
	 */
	protected boolean adjustMarker(IMarker marker, Diagnostic diagnostic) throws CoreException {
		boolean ret = super.adjustMarker(marker, diagnostic);
		if(!diagnostic.getData().isEmpty()) {
			Object o = diagnostic.getData().get(0);
			if(o instanceof MethodElement) {
				marker.setAttribute(GUID, ((MethodElement)o).getGuid());
				marker.setAttribute(IMarker.LOCATION, TngUtil.getLabelWithPath(o));
	    		marker.setAttribute(IDE.EDITOR_ID_ATTR, "org.eclipse.epf.authoring.ui.editors.MethodElementEditor"); //$NON-NLS-1$
	    		errorCalculator.addError((MethodElement) o);
			}
		}
		return ret;
	}
	
	public static boolean isInvalid(Object object) {
		if(object instanceof ProcessesItemProvider) {
			// this is an UI object: Processes
			//
			ProcessesItemProvider ip = (ProcessesItemProvider) object;
			MethodElement o;			
			return ((o = ip.getCapabilityPatternPackage()) != null && errorCalculator.hasErrors(o))
				|| ((o = ip.getDeliveryProcessPackage()) != null && errorCalculator.hasErrors(o));
		}
		else if(object instanceof MethodPackagesItemProvider) {
			// this is an UI object
			//
			object = ((ItemProviderAdapter)object).getTarget();			
		}
		else if(object instanceof ContentItemProvider) {
			ContentPackage coreContentPkg = ((ContentItemProvider)object).getCoreContentPackage();
			if(coreContentPkg != null) {
				object = coreContentPkg.eContainer();
			}
		}
		else if(object instanceof TransientContentPackageItemProvider) {
			// this is an UI object: either Tasks, Roles, Work Products, or Guidance
			//
			Collection<?> children = ((TransientContentPackageItemProvider)object).getChildren(object);
			for (Iterator<?> iter = children.iterator(); iter.hasNext();) {
				Object child = TngUtil.unwrap(iter.next());
				if(child instanceof MethodElement && errorCalculator.hasErrors((MethodElement) child)) {
					return true;
				}				
			}
			return false;
		}
		else if(object instanceof TransientGroupItemProvider) {
			object = ((TransientGroupItemProvider)object).getTarget();
		}
		return ((object = TngUtil.unwrap(object)) instanceof MethodElement && errorCalculator
				.hasErrors((MethodElement) object));
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.emf.common.ui.MarkerHelper#hasMarkers(java.lang.Object)
	 */
	public boolean hasMarkers(Object object) {
		if(object instanceof MethodElement) {			
			IResource resource = getFile(object);
			if (resource != null && resource.exists())
			{
				try
				{
					String guid = ((MethodElement)object).getGuid();
					IMarker[] markers = resource.findMarkers(getMarkerID(), false, IResource.DEPTH_ZERO);
					for (int i = 0; i < markers.length; i++) {
						IMarker marker = markers[i];
						if(guid.equals(marker.getAttribute(GUID))) {
							return true;
						}
					}
				}
				catch (CoreException e)
				{
				}
			}
			return false;
		}

		return super.hasMarkers(object);
	}
	
	@Override
	protected IFile getFile(Object datum) {
		try {
			return super.getFile(datum);
		}
		catch(Exception e) {
			return null;
		}
	}
	
	public void deleteMarkers(Object object) {
		if(object instanceof MethodElement) {
			IResource resource = getFile(object);
			if (resource != null && resource.exists())
			{
				try
				{
					MethodElement e = (MethodElement) object;
					String guid = e.getGuid();
					IMarker[] markers = resource.findMarkers(getMarkerID(), false, IResource.DEPTH_ZERO);
					for (int i = 0; i < markers.length; i++) {
						IMarker marker = markers[i];						
						if(guid.equals(marker.getAttribute(GUID))) {
							marker.delete();
							errorCalculator.removeError(e);
						}
					}
				}
				catch (CoreException e)
				{
				}
			}
			return;
		}
		
		super.deleteMarkers(object);
	}

	protected void deleteMarkers(IResource resource, boolean includeSubtypes, int depth) {
		if (resource != null && resource.exists()) {
			try {				
				IMarker[] markers = resource.findMarkers(getMarkerID(), false, IResource.DEPTH_ZERO);
				for (int i = 0; i < markers.length; i++) {
					IMarker marker = markers[i];
					String guid = (String) marker.getAttribute(GUID);
					MethodElement e = LibraryService.getInstance().getCurrentLibraryManager().getMethodElement(guid);
					if(e != null) {
						errorCalculator.removeError(e);
					}
				}

			} catch (CoreException e) {
				
			}			
		}
			
		super.deleteMarkers(resource, includeSubtypes, depth);
	}

	//Override to seperate error message in error dialog and problems view (bug 174351)
	//Note: better fix is to extend BasicDiagnostic to encapsulate both types of msgs -> to do later
	protected String composeMessage(Diagnostic diagnostic, Diagnostic parentDiagnostic) {
		int ix = diagnostic.getMessage().indexOf(LibraryEditResources.duplicateElementNameError_msg2);
		if (ix > 0) {
			return diagnostic.getMessage().substring(0, ix);
		}
		return super.composeMessage(diagnostic, parentDiagnostic);
	}

}