/*
 * <copyright>
 *
 * Copyright (c) 2005-2008 Sven Efftinge 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:
 *     Sven Efftinge - Initial API and implementation
 *     Alexander Shatalin (Borland)
 *
 * </copyright>
 */
package org.eclipse.gmf.internal.xpand.expression;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.gmf.internal.xpand.BuiltinMetaModel;
import org.eclipse.gmf.internal.xpand.ResourceManager;
import org.eclipse.gmf.internal.xpand.ResourceMarker;
import org.eclipse.gmf.internal.xpand.eval.EvaluationListener;
import org.eclipse.gmf.internal.xpand.migration.Activator;
import org.eclipse.gmf.internal.xpand.util.ClassLoadContext;
import org.eclipse.gmf.internal.xpand.xtend.ast.Extension;
import org.eclipse.gmf.internal.xpand.xtend.ast.XtendResource;

/**
 * @author Sven Efftinge
 * @author Arno Haase
 */
public class ExecutionContextImpl implements ExecutionContext {

    private final Map<String, Variable> variables = new HashMap<String, Variable> ();

    private final Map<String, Variable> globalVars = new HashMap<String, Variable> ();

    private ClassLoadContext contextClassLoader;

    private EvaluationListener evaluationListener;

    /**
     * this field is conceptually final, i.e. it is set only at object construction time. To simplify implementation, it is however technically not
     *  final. This is done so that the cloneWith/WithoutResource methods can delegate to cloneContext and afterwards modify the instance. That 
     *  provides cloneContext as a single method for subclasses to override.
     */
    private ResourceMarker currentResource;

	private final ResourceManager resourceManager;

	private Collection<EPackage> fallbackVisibleModels = new LinkedHashSet<EPackage>();

    public ExecutionContextImpl(ResourceManager resourceManager, EPackage... fallbackVisibleModels) {
        this (resourceManager, (Collection<Variable>) null);
        for (EPackage ePackage : fallbackVisibleModels) {
			this.fallbackVisibleModels.add(ePackage);
		}
    }
    
    public ExecutionContextImpl(ResourceManager resourceManager, Collection<Variable> globalVars) {
        this (resourceManager, null, null, globalVars);
    }

    public ExecutionContextImpl(ResourceManager resourceManager, ResourceMarker resource, Collection<Variable> variables, Collection<Variable> globalVars) {
        this.resourceManager = resourceManager;
		this.currentResource = resource;
		if (variables != null) {
			for (Variable v : variables) {
				this.variables.put(v.getName(), v);
			}
		}
        if (globalVars != null) {
        	for (Variable v : globalVars) {
        		this.globalVars.put(v.getName(), v);
        	}
		}
        fallbackVisibleModels.add(EcorePackage.eINSTANCE);
    }

    // copy constuctor
    protected ExecutionContextImpl(ExecutionContextImpl original) {
    	this.resourceManager = original.resourceManager;
    	this.currentResource = original.currentResource;
    	this.variables.putAll(original.variables);
    	this.globalVars.putAll(original.globalVars);
    	this.contextClassLoader = original.contextClassLoader;
    	this.evaluationListener = original.evaluationListener;
    	this.fallbackVisibleModels = original.fallbackVisibleModels;
    }

    /*
     * Need this for code completion only? move to proposal computer than
     */
    @SuppressWarnings("unchecked")
	public EClassifier[] findTypesForPrefix(final String prefix) {
    	final EPackage[] importedNamespaces;
    	final String typeName = TypeNameUtil.getTypeName(prefix);
    	final String typesMetamodelName = TypeNameUtil.getMetaModelName(typeName);
        // TODO filter importedNamespaces with metamodel name (use ePackage.nsPrefix for metamodel name? 
    	final String collectionTypeName = TypeNameUtil.getCollectionTypeName(prefix);
    	final String simpleTypeName;
    	// XXX handle cases like "metamodelName!" and "List[" as prefixes
        if (TypeNameUtil.isQualifiedName(typeName)) {
        	EPackage exactNamespace = findImportedNamespace(TypeNameUtil.withoutLastSegment(typeName));
        	if (exactNamespace == null) {
        		return new EClassifier[0];
        	} else {
        		importedNamespaces = new EPackage[] { exactNamespace };
        	}
            simpleTypeName = TypeNameUtil.getLastSegment(typeName);
        } else {
        	importedNamespaces = getAllVisibleModels();
        	simpleTypeName = TypeNameUtil.toCanonicalNameFromAlias(typeName);
        }
        if (collectionTypeName != null) {
            if (!BuiltinMetaModel.isCollectionMetaType(collectionTypeName)) {
				return new EClassifier[0];
			}
        }
        final List<EClassifier> result = new ArrayList<EClassifier>();
        for (final EPackage namespace : importedNamespaces) {
        	if (simpleTypeName == null || simpleTypeName.trim().length() == 0) {
        		result.addAll(namespace.getEClassifiers());
        	} else {
        		result.addAll(filterByNamePrefix(simpleTypeName, namespace.getEClassifiers()));
        	}
        }
        if (collectionTypeName == null) {
            return result.toArray(new EClassifier[result.size()]);
        }
        EClassifier[] rv = new EClassifier[result.size()];
        final Iterator<EClassifier> iterator = result.iterator();
        for (int i = 0; i < rv.length; i++) {
        	rv[i] = BuiltinMetaModel.getCollectionType(collectionTypeName, iterator.next());
        }
        return rv;
    }

	private EPackage findImportedNamespace(String namespace) {
    	assert namespace != null;
    	LinkedList<EPackage> potentialMatches = new LinkedList<EPackage>();
    	potentialMatches.addAll(Arrays.asList(getAllVisibleModels()));
    	String[] namespaceChain = namespace.split(SyntaxConstants.NS_DELIM);
    	EPackage returnValue = null;
		for (String namespacePart : namespaceChain) {
			LinkedList<EPackage> subPackages = new LinkedList<EPackage>();
			returnValue = null;
			for (EPackage candidate : potentialMatches) {
				if (candidate.getName().equals(namespacePart)) {
					subPackages.addAll(candidate.getESubpackages());
					returnValue = candidate;
					break; // no more than one package with specified namespacePart 
				}
			}
			potentialMatches = subPackages;
		}
		return returnValue;
	}

    private static <T extends ENamedElement> Collection<T> filterByNamePrefix(final String namePrefix, final Collection<? extends T> knownNamedElements) {
        final Set<T> result = new HashSet<T>();
        for (T t : knownNamedElements) {
            if (t.getName().startsWith(namePrefix)) {
            	result.add(t);
            }
        }
        return result;
    }

    /**
     * {@link ClassLoadContext} to use in {@link #loadClass(String)}.
     * @param classLoader loader to use or null to use default system-wide
     */
    public void setContextClassLoader(ClassLoadContext classLoadContext) {
    	this.contextClassLoader = classLoadContext;
    }

    public Class<?> loadClass(String value) {
    	// FIXME delegate to resourcemanager or Environment
    	try {
    		if (contextClassLoader != null) {
    			Class<?> c = contextClassLoader.load(value);
    			if (c != null) {
    				return c;
    			}
    		}
    		return Class.forName(value);
    	} catch (ClassNotFoundException ex) {
    		ex.getMessage();
    		// IGNORE?
    	}
    	return null;
    }

	protected EPackage[] getAllVisibleModels() {
		String[] importedNamespaces = getImportedNamespaces();
		assert importedNamespaces != null;
		// TODO respect meta-models imported not only with nsURI
		LinkedList<EPackage> result = new LinkedList<EPackage>();
		for (String namespace : importedNamespaces) {
			EPackage pkg = Activator.findMetaModel(namespace);
			if (pkg != null) {
				result.add(pkg);
			}
		}
		if (result.isEmpty()) {
			// hack for tests
			result.addAll(fallbackVisibleModels);
		}
//		result.add(BuiltinMetaModel.VOID.getEPackage());
		return result.toArray(new EPackage[result.size()]);
	}

    public EClassifier getTypeForName(String name) {
    	final String simpleTypeName = TypeNameUtil.toCanonicalNameFromAlias(TypeNameUtil.getSimpleName(TypeNameUtil.getTypeName(name)));
    	final String collectionTypeName = TypeNameUtil.getCollectionTypeName(name);
    	for (EClassifier potentialMatch : findTypesForPrefix(name)) {
    		// we don't know the order types get returned from #findTypesForPrefix, thus, need to 
    		// look for exact match
    		if (collectionTypeName != null) {
    			assert  BuiltinMetaModel.isParameterizedType(potentialMatch);
    			if (BuiltinMetaModel.getInnerType(potentialMatch).getName().equals(simpleTypeName)) {
    				return potentialMatch;
    			}
    		} else {
    			if (potentialMatch.getName().equals(simpleTypeName)) {
    				return potentialMatch;
    			}
    		}
       	}
    	return null;
    }

    protected String[] getImportedNamespaces() {
    	if (currentResource() instanceof XtendResource) {
    		return ((XtendResource) currentResource()).getImportedNamespaces();
    	}
    	return new String[0];
    }

    protected String[] getImportedExtensions() {
    	if (currentResource() instanceof XtendResource) {
    		return ((XtendResource) currentResource()).getImportedExtensions();
    	}
    	return new String[0];
    }

    public ExecutionContext cloneContext() {
        return new ExecutionContextImpl(this);
    }

    protected final ResourceManager getResourceManager() {
    	return resourceManager;
    }

    public Variable getVariable(final String name) {
        return variables.get(name);
    }

    public Collection<Variable> getVisibleVariables() {
        return Collections.unmodifiableCollection(variables.values());
    }

    public Collection<Variable> getGlobalVariables() {
        return Collections.unmodifiableCollection(globalVars.values());
    }

    public Variable getGlobalVariable(String name) {
    	return globalVars.get(name);
    }

	@SuppressWarnings("unchecked")
	public ExecutionContext cloneWithVariable(final Variable... vars) {
        final ExecutionContextImpl result = (ExecutionContextImpl) cloneContext();
        for (Variable v : vars) {
        	result.variables.put(v.getName(), v);
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public <T extends ExecutionContext> T cloneWithVariable(Collection<Variable> v) {
    	return (T) cloneWithVariable(v.toArray(new Variable[v.size()]));
    }

    @SuppressWarnings("unchecked")
    public ExecutionContext cloneWithoutVariables() {
        final ExecutionContextImpl result = (ExecutionContextImpl) cloneContext();
        result.variables.clear();
        return result;
    }

    @SuppressWarnings("unchecked")
    public ExecutionContext cloneWithResource(final ResourceMarker ns) {
        final ExecutionContextImpl ctx = (ExecutionContextImpl) cloneContext();
        ctx.currentResource = ns;
        return ctx;
    }

    public ResourceMarker currentResource() {
        return currentResource;
    }

    private Set<Extension> allExtensions = null;

	public Set<Extension> getAllExtensions() {
        if (allExtensions == null) {
            allExtensions = new HashSet<Extension>();
            final ResourceMarker res = currentResource();
            if (res != null) {
                final String[] extensions = getImportedExtensions();
                for (String extension : extensions) {
                    final XtendResource extFile = resourceManager.loadXtendResource(extension);
                    if (extFile == null) {
						throw new RuntimeException("Unable to load extension file : " + extension);
					}
                    final ExecutionContext ctx = cloneWithResource(extFile);
                    final List<Extension> extensionList = extFile.getPublicExtensions(resourceManager);
                    for (Extension element : extensionList) {
                        element.init(ctx);
                        allExtensions.add(element);
                    }
                }
                if (res instanceof XtendResource) {
                    final List<Extension> extensionList = ((XtendResource) res).getExtensions();
                    for (Extension element : extensionList) {
                        element.init(this);
                        allExtensions.add(element);
                    }
                }
            }
        }
        return allExtensions;
    }

    public Extension getExtension(final String functionName, final EClassifier[] parameterTypes) {
        return PolymorphicResolver.getExtension(getAllExtensions(), functionName, Arrays.asList(parameterTypes));
    }

    public EvaluationListener getEvaluationListener() {
    	return evaluationListener;
    }

    public void setEvaluationListener(EvaluationListener listener) {
    	this.evaluationListener = listener;
    }
}
