/*******************************************************************************
 * Copyright (c) 2014, 2015 Willink Transformations Ltd., University of York 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:
 *     Adolfo Sanchez-Barbudo Herrera (University of York) - initial API and implementation
 *******************************************************************************/
package org.eclipse.ocl.pivot.lookup;

import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.evaluation.Executor;
import org.eclipse.ocl.pivot.internal.lookup.LookupEnvironment;
import org.eclipse.ocl.pivot.internal.lookup.impl.LookupEnvironmentImpl;


/**
 * @since 1.1
 */
public class SingleResultLookupEnvironment extends LookupEnvironmentImpl implements SingleResultEnvironment {
	
	
	private static final Logger logger = Logger.getLogger(SingleResultLookupEnvironment.class);
	private @NonNull String name; 
	private @NonNull Executor executor;
	
	
	public SingleResultLookupEnvironment(@NonNull Executor executor, @NonNull String name) {
		this.executor = executor;
		this.name = name;
		//this.envFactory = executor.getEnvironmentFactory();
	}
	
	public SingleResultLookupEnvironment(@NonNull Executor executor, @NonNull String name, Boolean isLocal) {
		this(executor, name);
	}
	
	@Override
	@NonNull
	public LookupEnvironment addElement(@Nullable NamedElement namedElement) {
		if (namedElement != null) {
			if (name.equals(namedElement.getName())) {
				List<NamedElement> elements = getNamedElements();
				if (!elements.contains(namedElement)) {
					elements.add(namedElement);
				}
			}
		}
		return this;
	}
	
	
	@Override
	@NonNull
	public <NE extends NamedElement> LookupEnvironment addElements(
			@Nullable Collection<NE> elements) {
	
		if (elements != null) {
			for (NamedElement namedElement : elements) {
				addElement(namedElement);
			}	
		}
		return this;
	}


	@Override
	@Nullable
	public NamedElement getSingleResult() {
		List<NamedElement> elements = getNamedElements();
		int contentsSize = elements.size();
		if (contentsSize > 1) {
			logger.warn("Unhandled ambiguous content for '" + name + "'");
		}
		return  contentsSize == 0 ? null : elements.get(0);
	}

	@SuppressWarnings("null")
	@Override
	@NonNull
	public List<NamedElement> getAllResults() {
		return getNamedElements();
	}
	
	
	@Override
	public boolean hasFinalResult() {
		// Not thing found is not a final result
		return getNamedElements().size() == 0 ? false : true;
	}
	
	@Override
	@NonNull
	public Executor getExecutor() {
		return executor;
	}
	
/*	
	//
	// ADDITIONAL STUFF TO INTEGRATE WITH
	//
	
	public static abstract class Disambiguator<T> implements Comparator<T>
	{
	    @Override
		public int compare(T o1, T o2) {
		    throw new UnsupportedOperationException();
	    }
	    
	    public abstract int compare(@NonNull EnvironmentFactory environmentFactory, @NonNull T o1, @NonNull T o2);
	}
	
	private static final class ImplicitDisambiguator extends Disambiguator<Object>
	{
		@Override
		public int compare(@NonNull EnvironmentFactory environmentFactory, @NonNull Object match1, @NonNull Object match2) {
			boolean match1IsImplicit = (match1 instanceof Property) && ((Property)match1).isIsImplicit();
			boolean match2IsImplicit = (match2 instanceof Property) && ((Property)match2).isIsImplicit();
			if (!match1IsImplicit) {
				return match2IsImplicit ? 1 : 0;				// match2 inferior			
			}
			else {
				return match2IsImplicit ? 0 : -1;				// match1 inferior			
			}
		}
	}
	
	private static final class MetamodelMergeDisambiguator extends Disambiguator<Feature>
	{
		@Override
		public int compare(@NonNull EnvironmentFactory environmentFactory, @NonNull Feature match1, @NonNull Feature match2) {
			org.eclipse.ocl.pivot.Package p1 = PivotUtil.getContainingPackage(match1);
			org.eclipse.ocl.pivot.Package p2 = PivotUtil.getContainingPackage(match2);
			if (p1 == null) {
				return 0;
			}
			if (p2 == null) {
				return 0;
			}
			CompleteModel completeModel = environmentFactory.getCompleteModel();
			CompletePackage s1 = completeModel.getCompletePackage(p1);
			CompletePackage s2 = completeModel.getCompletePackage(p2);
			if (s1 != s2) {
				return 0;
			}
			int i1 = s1.getIndex(p1);
			int i2 = s2.getIndex(p2);
			return i2 - i1;
		}
	}

	private static final class OperationDisambiguator extends Disambiguator<Operation>
	{
		@Override
		public int compare(@NonNull EnvironmentFactory environmentFactory, @NonNull Operation match1, @NonNull Operation match2) {
			if (isRedefinitionOf(match1, match2)) {
				return 1;				// match2 inferior			
			}
			if (isRedefinitionOf(match2, match1)) {
				return -1;				// match1 inferior			
			}
			return 0;
		}

		protected boolean isRedefinitionOf(@NonNull Operation operation1, @NonNull Operation operation2) {
			List<Operation> redefinedOperations = operation1.getRedefinedOperations();
			for (Operation redefinedOperation : redefinedOperations) {
				if (redefinedOperation != null) {
					if (redefinedOperation == operation2) {
						return true;
					}
					if (isRedefinitionOf(redefinedOperation, operation2)) {
						return true;
					}
				}
			}
			return false;
		}
	}

	private static final class MergedPackageDisambiguator extends Disambiguator<org.eclipse.ocl.pivot.Package>
	{
		@Override
		public int compare(@NonNull EnvironmentFactory environmentFactory, org.eclipse.ocl.pivot.@NonNull Package match1, org.eclipse.ocl.pivot.@NonNull Package match2) {
			CompleteModel completeModel = environmentFactory.getCompleteModel();
			CompletePackage completePackage1 = completeModel.getCompletePackage(match1);
			CompletePackage completePackage2 = completeModel.getCompletePackage(match2);
			if (completePackage1 == completePackage2) {
				return 1;				// match2 inferior			
			}
			return 0;
		}
	}

	private static final class PropertyDisambiguator extends Disambiguator<Property>
	{
		@Override
		public int compare(@NonNull EnvironmentFactory environmentFactory, @NonNull Property match1, @NonNull Property match2) {
			if (isRedefinitionOf(match1, match2)) {
				return 1;				// match2 inferior			
			}
			if (isRedefinitionOf(match2, match1)) {
				return -1;				// match1 inferior			
			}
			return 0;
		}

		protected boolean isRedefinitionOf(@NonNull Property property1, @NonNull Property property2) {
			List<Property> redefinedProperties = property1.getRedefinedProperties();
			for (Property redefinedProperty : redefinedProperties) {
				if (redefinedProperty != null) {
					if (redefinedProperty == property2) {
						return true;
					}
					if (isRedefinitionOf(redefinedProperty, property2)) {
						return true;
					}
				}
			}
			return false;
		}
	}
			
	private static @NonNull LinkedHashMap<Class<?>, List<Comparator<Object>>> disambiguatorMap =	// FIXME narrow API to Disambiguator
			new LinkedHashMap<Class<?>, List<Comparator<Object>>>();

	static {
		addDisambiguator(Object.class, new ImplicitDisambiguator());
		addDisambiguator(Feature.class, new MetamodelMergeDisambiguator());
		addDisambiguator(Operation.class, new OperationDisambiguator());
		addDisambiguator(org.eclipse.ocl.pivot.Package.class, new MergedPackageDisambiguator());
		addDisambiguator(Property.class, new PropertyDisambiguator());
	}
	
	public static synchronized <T> void addDisambiguator(@NonNull Class<T> targetClass, @NonNull Comparator<T> disambiguator) {
		List<Comparator<Object>> disambiguators = disambiguatorMap.get(targetClass);
		if (disambiguators == null) {
			disambiguators = new ArrayList<Comparator<Object>>();
			disambiguatorMap.put(targetClass, disambiguators);
		}
		@SuppressWarnings("unchecked")
		Comparator<Object> castDisambiguator = (Comparator<Object>) disambiguator;
		disambiguators.add(castDisambiguator);
	}

	@SuppressWarnings("null")
	public static @NonNull Iterable<Class<?>> getDisambiguatorKeys() {
		return disambiguatorMap.keySet();
	}

	public static @Nullable List<Comparator<Object>> getDisambiguators(@NonNull Class<?> key) {
		return disambiguatorMap.get(key);
	}
	
	
	protected final @NonNull EnvironmentFactory envFactory;
	private List<ScopeFilter> matchers = null;	// Prevailing filters for matching
	private Set<ScopeFilter> resolvers = null;	// Successful filters for resolving
	
	public void addFilter(@NonNull ScopeFilter filter) {
		if (matchers == null) {
			matchers = new ArrayList<ScopeFilter>();
		}
		matchers.add(filter);
	}
	
	public void removeFilter(@NonNull ScopeFilter filter) {
		if (matchers != null) {
			matchers.remove(filter);
		}
	}
	
	@NonNull
	public SingleResultLookupEnvironment resolveDuplicates() {
		if (elements.size() > 1)  {
			// FIXME this WAS done while "adding" elements. Adding here where they are supposed
			// to be used. Talk with ED about this.
			if (matchers != null) {
				if (resolvers == null) {
					resolvers = new HashSet<ScopeFilter>();
				}
				resolvers.addAll(matchers);
			}
			for (int i = 0; i < elements.size()-1;) {
				boolean iRemoved = false;
				@SuppressWarnings("null") @NonNull Object iValue = elements.get(i);
				for (int j = i + 1; j < elements.size();) {
					Class<?> iClass = iValue.getClass();
					@SuppressWarnings("null") @NonNull Object jValue = elements.get(j);
					Class<?> jClass = jValue.getClass();
					int verdict = 0;
					for (Class<?> key : disambiguatorMap.keySet()) {
						if (key.isAssignableFrom(iClass) && key.isAssignableFrom(jClass)) {
							for (Comparator<Object> comparator : disambiguatorMap.get(key)) {
								if (comparator instanceof Disambiguator<?>) {
									verdict = ((Disambiguator<Object>)comparator).compare(envFactory, iValue, jValue);
								} else {
									verdict = comparator.compare(iValue, jValue);
								}
								if (verdict != 0) {
									break;
								}
							}
							if (verdict != 0) {
								break;
							}
						}
					}
					if (verdict == 0) {
						j++;
					} else if (verdict < 0) {
						elements.remove(i);
						iRemoved = true;
						break;
					} else {
						elements.remove(j);
					}
				}
				if (!iRemoved) {
					i++;
				}				
			}
		}
		return this;
	}
*/
}
