//------------------------------------------------------------------------------
// 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.validation.constraints;

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

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.ecore.util.EcoreUtil.ContentTreeIterator;
import org.eclipse.emf.validation.service.AbstractTraversalStrategy;
import org.eclipse.emf.validation.service.ITraversalStrategy;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.Constraint;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.DiagramElement;
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.ProcessComponent;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.util.UmaUtil;

/**
 * @author Phong Nguyen Le
 * @since  1.1
 */
public class LibraryTraversalStrategy extends AbstractTraversalStrategy {
	public static final String TRAVERSAL_TYPE = "TRAVERSAL_TYPE"; //$NON-NLS-1$
	/**
	 * Traversal strategy type constant for shadow traversal
	 */
	public static final int SHADOW = 0;
	
	/**
	 * Traversal strategy type constant for deep traversal
	 */
	public static final int DEEP = 1;
	
	public static final ITraversalStrategy deepTraversalStrategy = new LibraryTraversalStrategy(DEEP);
	
	public static class LibraryIterator extends ContentTreeIterator {
		private static final long serialVersionUID = -1175428027503440970L;
		private int traversalType = DEEP;
		
		protected LibraryIterator(Collection emfObjects) {
			super(emfObjects);
		}
		
		/**
		 * @param object
		 * @param isResolveProxies
		 */
		public LibraryIterator(Collection eObjects, boolean isResolveProxies, int traversalType, boolean disjoint) {
			super(disjoint ? makeTargetsDisjoint(eObjects) : eObjects, isResolveProxies);
			this.traversalType  = traversalType;
		}
		
		@Override
		protected Iterator<?> getEObjectChildren(EObject object) {
			if(traversalType == DEEP) {
				if(!(object instanceof MethodElement)
						|| (object instanceof Constraint || object instanceof DiagramElement)) 
				{
					return Collections.EMPTY_LIST.iterator();
				}
				return super.getEObjectChildren(object);
			}
			
			if(object instanceof CustomCategory) {
				return getEObjectChildren((CustomCategory)object, UmaPackage.Literals.CUSTOM_CATEGORY__CATEGORIZED_ELEMENTS,
						UmaPackage.Literals.CUSTOM_CATEGORY);
			}
			else if (object instanceof ProcessComponent
					|| object instanceof MethodConfiguration
					|| object instanceof ContentElement
			) {
				return Collections.EMPTY_LIST.iterator();
			}
			else if (object instanceof MethodPackage) {
				MethodPackage pkg = (MethodPackage) object;
				if(TngUtil.isPredefined(pkg) && ModelStructure.CUSTOM_CATEGORY_PACKAGE_NAME.equals(pkg.getName())) {
					// this is the content package that contains all the custom categories
					// return root custom category as its only child
					//
					ContentPackage hiddenPkg = UmaUtil.findContentPackage(pkg
							.getChildPackages(), ModelStructure.HIDDEN_PACKAGE_NAME);
					if (hiddenPkg != null && !hiddenPkg.getContentElements().isEmpty()) {
						return hiddenPkg.getContentElements().iterator();
					}
					else {
						return Collections.EMPTY_LIST.iterator();
					}
				}
				else {
					return getEObjectChildren(pkg, UmaPackage.Literals.METHOD_PACKAGE__CHILD_PACKAGES, null);
				}
			}
			else if (object instanceof MethodLibrary) {
				return getEObjectChildren(
						(MethodLibrary) object,
						new EStructuralFeature[] {
								UmaPackage.Literals.METHOD_LIBRARY__METHOD_PLUGINS,
								UmaPackage.Literals.METHOD_LIBRARY__PREDEFINED_CONFIGURATIONS });
			}
			else if (object instanceof MethodPlugin) {
				return getEObjectChildren((EObject) object, UmaPackage.Literals.METHOD_PLUGIN__METHOD_PACKAGES, null);
			}
			else if (object == this.object) {
				return ((Collection)object).iterator();
			}
			
			return Collections.EMPTY_LIST.iterator();
		}
		
		private Iterator getEObjectChildren(EObject eObject, EStructuralFeature[] features) {
			EContentsEList list = new EContentsEList(eObject, features);
			return isResolveProxies() ? list.iterator() : list.basicIterator();
		}
		
		private Iterator getEObjectChildren(EObject eObject, EReference reference, EClass eClass) {
			Iterator iter;
			if(reference.isMany()) {
				boolean resolve = isResolveProxies();
				List list = (List) eObject.eGet(reference, resolve);
				iter = !resolve && (list instanceof InternalEList) ? ((InternalEList)list).basicIterator() : list.iterator();
			}
			else {
				Object value = eObject.eGet(reference, isResolveProxies());
				iter = value != null ? Collections.singletonList(value).iterator() : Collections.EMPTY_LIST.iterator();
			}
			if(eClass == null) {
				return iter;
			}
			else {
				ArrayList list = new ArrayList();
				while(iter.hasNext()) {
					Object o = iter.next();
					if(eClass.isInstance(o)) {
						list.add(o);
					}
				}
				if(list.isEmpty()) {
					return Collections.EMPTY_LIST.iterator();
				}
				else {
					return list.iterator();
				}
			}
		}
	}
	
	public static int countElements(Collection traversalRoots, int traversalType) {
		return countElements(traversalRoots, true, traversalType);
	}
	
	private static int countElements(Collection traversalRoots, boolean makeDisjoint, int traversalType) {
		int count = 0;
		for(Iterator iter = new LibraryIterator(traversalRoots, true, traversalType, makeDisjoint); iter.hasNext(); count++) {
			iter.next();
		}
		return count;
	}

	private Collection roots;
	private boolean contextChanged = true;

	private int type = DEEP;
	
	/**
	 * Initializes me.
	 */
	public LibraryTraversalStrategy() {
		super();
	}
	
	public LibraryTraversalStrategy(int traversalType) {
		this.type  = traversalType;
	}
	
	public void startTraversal(
			Collection traversalRoots,
			IProgressMonitor progressMonitor) {
		
		roots = makeTargetsDisjoint(traversalRoots);
		
		super.startTraversal(traversalRoots, progressMonitor);
	}
	
	private Collection getRoots() {
		return roots;
	}
	
	/* (non-Javadoc)
	 * Implements the inherited method.
	 */
	protected int countElements(Collection ignored) {
		return countElements(getRoots(), false, type);
	}
	
	/* (non-Javadoc)
	 * Implements the inherited method.
	 */
	protected Iterator createIterator(Collection ignored) {
		return new LibraryIterator(getRoots(), true, type, false) {
			private static final long serialVersionUID = -5653134989235663973L;

			public Iterator getChildren(Object obj) {
				if (obj == getRoots()) {
					return new Iterator() {
						private final Iterator delegate =
							getRoots().iterator();
						
						public boolean hasNext() {
							return delegate.hasNext();
						}

						public Object next() {
							// if I'm being asked for my next element, then
							//    we are stepping to another traversal root
							contextChanged = true;
							
							return delegate.next();
						}

						public void remove() {
							delegate.remove();
						}};
				} else {
					return super.getChildren(obj);
				}
			}
			
			public Object next() {
				// this will be set to true again the next time we test hasNext() at
				//    the traversal root level
				contextChanged = false;
				
				return super.next();
			}};
	}
	
	public boolean isClientContextChanged() {
		return contextChanged;
	}
	
	public static Set makeTargetsDisjoint(Collection objects) {
		Set result = new java.util.HashSet();
		
		// ensure that any contained (descendent) elements of other elements
		//    that we include are not included, because they will be
		//    traversed by recursion, anyway
		
		for (Iterator outer = objects.iterator(); outer.hasNext();) {
			EObject outerNext = (EObject)outer.next();
			
			for (Iterator inner = result.iterator(); inner.hasNext();) {
				EObject innerNext = (EObject)inner.next();
				
				if (EcoreUtil.isAncestor(innerNext, outerNext)) {
					outerNext = null;  // forget this one
					break;
				}
			}
			
			if (outerNext != null) {
				result.add(outerNext);
			}
		}
		
		return result;
	}	
}
