//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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.library.edit.validation;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.Deliverable;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.util.AssociationHelper;

/**
 * This class handles upward reachable info for circular dependency checking
 * 
 * @author Weiping Lu
 * @since 1.2
 */
public class UpwardReachableInfo implements IDependencyInfo {

	private DependencyInfoMgr mgr;
	private MethodElement element;
	private HashMap parentMap;
	private boolean complete = false;
	private boolean debug = false;
	
	protected UpwardReachableInfo(DependencyInfoMgr mgr, MethodElement element) {
		this.mgr = mgr;
		this.element = element;
	}
	
	public boolean isComplete() {
		return complete;
	}
	
	public void build(boolean checkCircular) {
		if (debug) {
			System.out.println("LD> build: " + this);	//$NON-NLS-1$
		}
		buildInner(checkCircular);
	}
	
	private void buildInner(boolean checkCircular) {
		Object info = mgr.getProcessedInfo(element);
		if (info != null) {
			if (info == this && complete) {
				return;
			}
			throw new RuntimeException("Internal error in buildInner: " + info);		//$NON-NLS-1$
		}
		mgr.addToProcessed(this);
		if (debug) {
			System.out.println("LD> buildInner: " + this);	//$NON-NLS-1$
			System.out.println("");							//$NON-NLS-1$
		}
		buildInner_(checkCircular);
	}
	
	private void buildInner_(boolean checkCircular) {
		List parents = getMixedParentList();
		int sz = parents == null ? 0 : parents.size();
		if (sz == 0) {
			complete = true;
			return;
		}
		
		parentMap = new HashMap();
		List processedParents = null;
		for (int i = 0; i< sz; i++) {
			MethodElement parentElem = (MethodElement) parents.get(i);
			UpwardReachableInfo pinfo = (UpwardReachableInfo) mgr.getProcessedInfo(parentElem);
			if (pinfo == null){
				pinfo = new UpwardReachableInfo(mgr, parentElem);
				parentMap.put(parentElem.getGuid(), pinfo);
				pinfo.buildInner(checkCircular);
			} else {
				parentMap.put(parentElem.getGuid(), pinfo);
				if (checkCircular) {
					if (processedParents == null) {
						processedParents = new ArrayList();
					}
					processedParents.add(pinfo);
				}
			}
		}
		complete = true;
			
		if (checkCircular && processedParents != null) {
			for (int i=0; i<processedParents.size(); i++) {
				reachableBy((IDependencyInfo) processedParents.get(i));
			}
		}
	}
	
	public boolean reachableBy(IDependencyInfo info)  {
		if (! (info instanceof UpwardReachableInfo)) {
			throw new UnsupportedOperationException();
		}
		if (debug) {
			System.out.println("LD> Entry reachableBy: this -> " + this);	//$NON-NLS-1$
			System.out.println("LD> Entry reachableBy: info -> " + info);	//$NON-NLS-1$
			System.out.println("");											//$NON-NLS-1$
		}
		return reachableBy((UpwardReachableInfo) info, new Stack(), new HashMap());
	}
	
	private boolean reachableBy(UpwardReachableInfo info, Stack stack, Map seen)  {
		stack.push(info);
		if (debug) {
			System.out.println("LD> reachableBy: this -> " + this);		//$NON-NLS-1$
			System.out.println("LD> reachableBy: info -> " + info);		//$NON-NLS-1$
			System.out.println("");										//$NON-NLS-1$
		}
		boolean ret =  reachableBy_(info, stack, seen);
		stack.pop();
		return ret;
	}
	
	private boolean reachableBy_(UpwardReachableInfo info, Stack stack, Map seen)  {
		Map testMap = info.parentMap;		
		if (testMap == null || testMap.isEmpty()) {
			return false;
		}
		
		if (testMap.containsKey(element.getGuid())) {
			if (debug) {
				System.out.println("LD> Contained in parentMap of: " + info);		//$NON-NLS-1$									
			}
			stack.push(this);
			mgr.logCircularDependency((Stack) stack.clone());
			stack.pop();
			return true;
		}
		
		if (seen.containsKey(info.getElement().getGuid())) {
			return false;
		}
		
		
		seen.put(info.getElement().getGuid(), info);
		
		for (Iterator it = testMap.values().iterator(); it.hasNext();) {
			UpwardReachableInfo parentInfo = (UpwardReachableInfo) it.next();
			if (parentInfo.containedIn(stack)) {
				if (debug) {
					System.out.println("LD> containedIn stack: " + info);		//$NON-NLS-1$									
				}
				stack.push(parentInfo);
				mgr.logCircularDependency((Stack) stack.clone());
				stack.pop();
				return true;
			}
			if  (reachableBy(parentInfo, stack, seen)) {
				return true;
			}
		}	
		
		return false;
	}
	
	public MethodElement getElement() {
		return element;
	}
	
	private List getMixedParentList() {
		List list = new ArrayList();
		collectParentList(element, list);
		VariabilityElement ve = (VariabilityElement) element;
		collectParentListByVariantPaths(ve, list);
		if (ve.getVariabilityType() == VariabilityType.REPLACES_LITERAL ) {
			mgr.addToReplacerMap(this);
		}
		return list;
	}
	
	private void collectParentList(MethodElement elem, List list) {
		List parentList = getParentList(elem);
		
		int sz = parentList == null ? 0 : parentList.size();
		if (mgr.isMoveElement(elem)) {
			if (sz > 1 && !(elem instanceof CustomCategory)) {
				throw new UnsupportedOperationException();	
			}
		} else if (sz > 0) {
			list.addAll(parentList);
		}

	}

	public static List getParentList(MethodElement elem) {
		List parentList = null;
		
		if (elem instanceof CustomCategory) {
			parentList = AssociationHelper.getCustomCategories((CustomCategory) elem);
		} else if (elem instanceof Deliverable) {
			parentList = AssociationHelper.getDeliverables((Deliverable) elem);			
		} else {	
			Object parent = getSameTypeParent(elem);
			if (parent != null) {
				parentList = new ArrayList();
				parentList.add(parent);
			}
		}
		return parentList;
	}
	
	private void collectParentListByVariantPaths(VariabilityElement ve, List list) {
		if (! mgr.isFilterElement(ve)) {
			VariabilityElement parentVe = ve.getVariabilityBasedOnElement();
			VariabilityType type = parentVe == null ? null : ve.getVariabilityType();
			if (type == VariabilityType.CONTRIBUTES_LITERAL || type == VariabilityType.REPLACES_LITERAL) {
				list.add(parentVe);
			}
		}

		if (mgr.isDndElement(ve)) {
			return;
		}
				
		for (Iterator it = TngUtil.getImmediateVarieties(ve, VariabilityType.EXTENDS_LITERAL) ; it.hasNext();) {
			VariabilityElement extender = (VariabilityElement) it.next();
			if (! mgr.isFilterElement(extender)) {
				list.add(extender);
			}
		}
		
	}
	
	private static MethodElement getSameTypeParent(MethodElement elem) {
		if (elem instanceof Activity) {
			return ((Activity) elem).getSuperActivities();
		}
			
		MethodElement parent = (MethodElement) elem.eContainer();
		return parent.getType() == elem.getType() ? parent : null;
	}		
	
	public String toString() {
		return TngUtil.getLabelWithPath(element);
	}
	
	public boolean inheritAncestor(VariabilityType type) {
		VariabilityElement parentVe = ((VariabilityElement) element).getVariabilityBasedOnElement();
		if (parentVe == null) {
			return false;
		}
		if (((VariabilityElement) element).getVariabilityType() != type) {
			return false;
		}
		ArrayList mixParentList = new ArrayList();	
		collectParentList(element, mixParentList);
		if (mixParentList != null && mixParentList.contains(parentVe)) {
			return true;
		}

		UpwardReachableInfo parentVeInfo = (UpwardReachableInfo) parentMap.get(parentVe.getGuid());
		for (Iterator it = parentMap.values().iterator(); it.hasNext();) {
			UpwardReachableInfo parentInfo = (UpwardReachableInfo) it.next();
			if  (parentVeInfo == parentInfo) {
				continue;
			}
			if (parentVeInfo.reachableBy(parentInfo)) {
				return true;
			}
		}
				
		return false;
	}
	
	//This would scale up for performance when infoList gets large
	private boolean containedIn(List infoList) {
		int sz = infoList == null ? 0 : infoList.size();
		if (sz == 0) {
			return false;
		}
		String guid = getElement().getGuid();
		if (sz == 1) {
			return guid.equals(((IDependencyInfo) infoList.get(0)).getElement().getGuid());
		}
		Map listMap = new HashMap();
		for (int i=0; i<sz; i++) {
			IDependencyInfo info = (IDependencyInfo) infoList.get(i);
			listMap.put(info.getElement().getGuid(), info);
		}
		
		return listMap.containsKey(guid);
	}
	
}
