/*******************************************************************************
 * Copyright (c) 2005, 2016 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
 *
 *******************************************************************************/
package org.eclipse.dltk.ruby.typeinference;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
import org.eclipse.dltk.ast.declarations.MethodDeclaration;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.declarations.TypeDeclaration;
import org.eclipse.dltk.ast.expressions.Expression;
import org.eclipse.dltk.ast.references.VariableReference;
import org.eclipse.dltk.ast.statements.Block;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IField;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IParameter;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ISourceRange;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.mixin.MixinModel;
import org.eclipse.dltk.core.search.IDLTKSearchConstants;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.SearchEngine;
import org.eclipse.dltk.core.search.SearchMatch;
import org.eclipse.dltk.core.search.SearchParticipant;
import org.eclipse.dltk.core.search.SearchPattern;
import org.eclipse.dltk.core.search.SearchRequestor;
import org.eclipse.dltk.evaluation.types.AmbiguousType;
import org.eclipse.dltk.internal.core.MethodParameterInfo;
import org.eclipse.dltk.internal.core.ModelElement;
import org.eclipse.dltk.ruby.core.RubyLanguageToolkit;
import org.eclipse.dltk.ruby.core.RubyPlugin;
import org.eclipse.dltk.ruby.core.model.FakeMethod;
import org.eclipse.dltk.ruby.internal.parser.mixin.ExactMixinSearchPattern;
import org.eclipse.dltk.ruby.internal.parser.mixin.IRubyMixinElement;
import org.eclipse.dltk.ruby.internal.parser.mixin.PrefixMixinSearchPattern;
import org.eclipse.dltk.ruby.internal.parser.mixin.RubyMixin;
import org.eclipse.dltk.ruby.internal.parser.mixin.RubyMixinClass;
import org.eclipse.dltk.ruby.internal.parser.mixin.RubyMixinMethod;
import org.eclipse.dltk.ruby.internal.parser.mixin.RubyMixinModel;
import org.eclipse.dltk.ruby.internal.parser.mixin.RubyMixinVariable;
import org.eclipse.dltk.ruby.internal.parser.mixin.RubyObjectMixinClass;
import org.eclipse.dltk.ruby.typeinference.BuiltinMethodsDatabase.ClassMetaclass;
import org.eclipse.dltk.ruby.typeinference.BuiltinMethodsDatabase.Metaclass;
import org.eclipse.dltk.ruby.typeinference.BuiltinMethodsDatabase.MethodInfo;
import org.eclipse.dltk.ruby.typeinference.BuiltinMethodsDatabase.ModuleMetaclass;
import org.eclipse.dltk.ti.types.IEvaluatedType;

public class RubyModelUtils {

	public static IType getModelTypeByAST(TypeDeclaration astNode,
			ISourceModule sourceModule) throws ModelException {
		IType[] types = sourceModule.getAllTypes();
		int astStart = astNode.sourceStart();
		int astEnd = astNode.sourceEnd();
		int bestScore = Integer.MAX_VALUE;
		IType bestType = null;
		for (int i = 0; i < types.length; i++) {
			IType type = types[i];
			ISourceRange sourceRange = type.getSourceRange();
			int modelStart = sourceRange.getOffset();
			int modelEnd = modelStart + sourceRange.getLength();
			if (modelStart == astStart && modelEnd == astEnd)
				// XXX modelEnd == astEnd + 1 currently, so this never happens
				return type;
			if (type.getElementName().equals(astNode.getName())) {
				int diff1 = modelStart - astStart;
				int diff2 = modelEnd - astEnd;
				int score = diff1 * diff1 + diff2 * diff2;
				if (score < bestScore) {
					bestScore = score;
					bestType = type;
				}
			}
		}
		return bestType;
	}

	public static MethodDeclaration getNodeByMethod(ModuleDeclaration rootNode,
			IMethod method) throws ModelException {

		ISourceRange sourceRange = method.getSourceRange();
		final int modelStart = sourceRange.getOffset();
		final int modelEnd = modelStart + sourceRange.getLength();
		final int modelCutoffStart = modelStart - 100;
		final int modelCutoffEnd = modelEnd + 100;
		final String methodName = method.getElementName();

		final MethodDeclaration[] bestResult = new MethodDeclaration[1];

		ASTVisitor visitor = new ASTVisitor() {

			int bestScore = Integer.MAX_VALUE;

			private boolean interesting(ASTNode s) {
				if (s.sourceStart() < 0 || s.sourceEnd() < s.sourceStart())
					return true;
				if (modelCutoffEnd < s.sourceStart()
						|| modelCutoffStart >= s.sourceEnd())
					return false;
				return true;
			}

			@Override
			public boolean visit(Expression s) throws Exception {
				if (!interesting(s))
					return false;
				return true;
			}

			@Override
			public boolean visit(MethodDeclaration s) throws Exception {
				if (!interesting(s))
					return false;
				if (s.getName().equals(methodName)) {
					int astStart = s.sourceStart();
					int astEnd = s.sourceEnd();
					int diff1 = modelStart - astStart;
					int diff2 = modelEnd - astEnd;
					int score = diff1 * diff1 + diff2 * diff2;
					if (score < bestScore) {
						bestScore = score;
						bestResult[0] = s;
					}

				}
				return true;
			}

			@Override
			public boolean visit(ModuleDeclaration s) throws Exception {
				if (!interesting(s))
					return false;
				return true;
			}

			@Override
			public boolean visit(TypeDeclaration s) throws Exception {
				if (!interesting(s))
					return false;
				return true;
			}

			@Override
			public boolean endvisit(TypeDeclaration s) throws Exception {
				if (!interesting(s))
					return false;
				return false /* dummy */;
			}

			@Override
			public boolean visitGeneral(ASTNode s) throws Exception {
				if (s instanceof Block)
					return true;
				if (!interesting(s))
					return false;
				return true;
			}

		};

		try {
			rootNode.traverse(visitor);
		} catch (Exception e) {
			RubyPlugin.log(e);
		}

		return bestResult[0];

	}

	public static IField[] findFields(RubyMixinModel rubyModel,
			ISourceModule modelModule, ModuleDeclaration parsedUnit,
			String prefix, int position) {
		Assert.isNotNull(prefix);
		List<IField> result = new ArrayList<IField>();

		String[] keys = RubyTypeInferencingUtils.getModelStaticScopesKeys(
				rubyModel.getRawModel(), parsedUnit, position);

		IRubyMixinElement innerElement = null;
		RubyMixinClass selfClass = new RubyObjectMixinClass(rubyModel, true);

		if (keys != null && keys.length > 0) {
			String inner = keys[keys.length - 1];
			if (prefix.length() > 0 && !prefix.startsWith("@")) { //$NON-NLS-1$ // locals & constants
				String varkey = inner + MixinModel.SEPARATOR + prefix;
				String[] keys2 = rubyModel.getRawModel().findKeys(varkey + "*", new NullProgressMonitor()); //$NON-NLS-1$
				for (int i = 0; i < keys2.length; i++) {
					IRubyMixinElement element = rubyModel
							.createRubyElement(keys2[i]);
					if (element instanceof RubyMixinVariable) {
						RubyMixinVariable variable = (RubyMixinVariable) element;
						IField field = variable.getSourceFields()[0];
						if (field.getElementName().startsWith(prefix))
							result.add(field);
					}
				}
			} else {
				innerElement = rubyModel.createRubyElement(inner);
				if (innerElement instanceof RubyMixinMethod) {
					RubyMixinMethod method = (RubyMixinMethod) innerElement;
					selfClass = method.getSelfType();
					RubyMixinVariable[] fields2 = method.getVariables();
					addVariablesFrom(fields2, prefix, result);
				} else if (innerElement instanceof RubyMixinClass) {
					selfClass = (RubyMixinClass) innerElement;
				}
			}
		}

		if (selfClass != null) {
			RubyMixinVariable[] fields2 = selfClass.getFields();
			addVariablesFrom(fields2, prefix, result);
			if (selfClass.getKey().equals("Object")) { //$NON-NLS-1$
				// variables
				try {
					IModelElement[] children = modelModule.getChildren();
					for (int i = 0; i < children.length; i++) {
						if (children[i] instanceof IField) {
							IField field = (IField) children[i];
							if (field.getElementName().startsWith(prefix))
								result.add(field);
						}
					}
				} catch (ModelException e) {
					e.printStackTrace();
				}
			}
		}

		return result.toArray(new IField[result.size()]);
	}

	/**
	 * Handling for "new" method
	 * 
	 * @param method
	 * @param selfKlass
	 * @return
	 */
	private static List<IMethod> handleSpecialMethod(RubyMixinMethod method,
			RubyMixinClass selfKlass) {
		if (method.getKey().equals("Class%{new")) { //$NON-NLS-1$
			RubyMixinMethod init = selfKlass.getInstanceClass() != null ? selfKlass
					.getInstanceClass().getMethod("initialize") //$NON-NLS-1$
					: null;
			if (init != null) {
				IMethod[] initMethods = init.getSourceMethods();
				List<IMethod> result = new ArrayList<IMethod>();
				for (int i = 0; i < initMethods.length; i++) {
					try {
						IParameter[] parameters = initMethods[i]
								.getParameters();
						int flags = initMethods[i].getFlags();
						ISourceRange sourceRange = initMethods[i]
								.getSourceRange();
						ISourceRange nameRange = initMethods[i].getNameRange();
						IModelElement parent = initMethods[i].getParent();
						FakeMethod newMethod = new FakeMethod(
								(ModelElement) parent,
								"new", //$NON-NLS-1$
								sourceRange.getOffset(), sourceRange
										.getLength(), nameRange.getOffset(),
								nameRange.getLength());
						newMethod.setParameters(parameters);
						newMethod.setFlags(flags);
						String receiver = ""; //$NON-NLS-1$
						if (parent instanceof IType) {
							IType type = (IType) parent;
							receiver = type.getTypeQualifiedName("::"); //$NON-NLS-1$
						}
						newMethod.setReceiver(receiver);
						result.add(newMethod);
					} catch (ModelException e) {
						e.printStackTrace();
					}
				}
				return result;
			}
		}
		return null;
	}

	public static List<IMethod> getAllSourceMethods(RubyMixinMethod[] methods,
			RubyMixinClass selfKlass) {
		List<IMethod> result = new ArrayList<IMethod>();
		for (int i = 0; i < methods.length; i++) {
			if (selfKlass != null) {
				List<IMethod> m = handleSpecialMethod(methods[i], selfKlass);
				if (m != null) {
					result.addAll(m);
					continue;
				}
			}
			IMethod[] sourceMethods = methods[i].getSourceMethods();
			for (int j = 0; j < sourceMethods.length; j++) {
				if (sourceMethods[j] != null/*
											 * &&
											 * sourceMethods[j].getElementName()
											 * .startsWith(prefix)
											 */) {
					result.add(sourceMethods[j]);
				}
			}
		}
		return result;
	}

	public static IMethod[] searchClassMethods(final RubyMixinModel mixinModel,
			org.eclipse.dltk.core.ISourceModule modelModule,
			ModuleDeclaration moduleDeclaration, IEvaluatedType type,
			String prefix) {
		List<IMethod> result = new ArrayList<IMethod>();
		if (type instanceof RubyClassType) {
			RubyClassType rubyClassType = (RubyClassType) type;
			RubyMixinClass rubyClass = mixinModel
					.createRubyClass(rubyClassType);
			if (rubyClass != null) {
				RubyMixinMethod[] methods = rubyClass
						.findMethods(new PrefixMixinSearchPattern(prefix));
				result.addAll(getAllSourceMethods(methods, rubyClass));
			}

		} else if (type instanceof AmbiguousType) {
			AmbiguousType type2 = (AmbiguousType) type;
			IEvaluatedType[] possibleTypes = type2.getPossibleTypes();
			for (int i = 0; i < possibleTypes.length; i++) {
				IMethod[] m = searchClassMethods(mixinModel, modelModule,
						moduleDeclaration, possibleTypes[i], prefix);
				for (int j = 0; j < m.length; j++) {
					result.add(m[j]);
				}
			}
		}
		return result.toArray(new IMethod[result.size()]);
	}

	public static IMethod[] searchClassMethodsExact(
			final RubyMixinModel mixinModel,
			org.eclipse.dltk.core.ISourceModule modelModule,
			ModuleDeclaration moduleDeclaration, IEvaluatedType type,
			String methodName) {
		List<IMethod> result = new ArrayList<IMethod>();
		if (type instanceof RubyClassType) {
			RubyClassType rubyClassType = (RubyClassType) type;
			RubyMixinClass rubyClass = mixinModel
					.createRubyClass(rubyClassType);
			if (rubyClass != null) {
				RubyMixinMethod[] methods = rubyClass
						.findMethods(new ExactMixinSearchPattern(methodName));
				result.addAll(getAllSourceMethods(methods, rubyClass));
			}

		} else if (type instanceof AmbiguousType) {
			AmbiguousType type2 = (AmbiguousType) type;
			IEvaluatedType[] possibleTypes = type2.getPossibleTypes();
			for (int i = 0; i < possibleTypes.length; i++) {
				IMethod[] m = searchClassMethodsExact(mixinModel, modelModule,
						moduleDeclaration, possibleTypes[i], methodName);
				for (int j = 0; j < m.length; j++) {
					result.add(m[j]);
				}
			}
		}
		return result.toArray(new IMethod[result.size()]);
	}

	private static void addVariablesFrom(RubyMixinVariable[] fields2,
			String prefix, List<IField> resultList) {
		for (int i = 0; i < fields2.length; i++) {
			IField[] sourceFields = fields2[i].getSourceFields();
			if (sourceFields != null) {
				for (int j = 0; j < sourceFields.length; j++) {
					if (sourceFields[j] != null) {
						if (sourceFields[j].getElementName().startsWith(prefix)) {
							resultList.add(sourceFields[j]);
							break;
						}

					}

				}
			}
		}
	}

	public static IMethod[] getSingletonMethods(
			final RubyMixinModel mixinModel, VariableReference receiver,
			ModuleDeclaration parsedUnit, ISourceModule modelModule,
			String methodName) {
		IMethod[] res = null;
		String[] scopesKeys = RubyTypeInferencingUtils
				.getModelStaticScopesKeys(mixinModel.getRawModel(), parsedUnit,
						receiver.sourceStart());
		if (scopesKeys != null && scopesKeys.length > 0) {
			String possibleName;
			if (scopesKeys.length == 1) {
				possibleName = receiver.getName() + RubyMixin.VIRTUAL_SUFFIX;
			} else {
				String last = scopesKeys[scopesKeys.length - 1];
				possibleName = last + MixinModel.SEPARATOR + receiver.getName()
						+ RubyMixin.VIRTUAL_SUFFIX;
			}
			IRubyMixinElement element = mixinModel
					.createRubyElement(possibleName);
			if (element instanceof RubyMixinClass) {
				RubyMixinClass rubyMixinClass = (RubyMixinClass) element;
				res = RubyModelUtils.searchClassMethodsExact(mixinModel,
						modelModule, parsedUnit, new RubyClassType(
								rubyMixinClass.getKey()), methodName);
			}
		}
		return res;
	}

	// public static RubyClassType getSuperType(IType type) {
	// String[] superClasses;
	// try {
	// superClasses = type.getSuperClasses();
	// } catch (ModelException e) {
	// e.printStackTrace();
	// return null;
	// }
	// if (superClasses != null && superClasses.length == 1) {
	// String name = superClasses[0];
	// IType[] types;
	// if (name.startsWith("::")) {
	// types = DLTKModelUtil.getAllTypes(type.getScriptProject(), name, "::");
	// } else {
	// String scopeFQN = type.getTypeQualifiedName("::");
	// types = DLTKModelUtil.getAllScopedTypes(type.getScriptProject(), name,
	// "::", scopeFQN);
	// }
	// if (types != null && types.length > 0) {
	// String typeQualifiedName =
	// types[0].getTypeQualifiedName("::").substring(2);
	// String[] FQN = typeQualifiedName.split("::");
	// return new RubyClassType(FQN, types, null);
	// } else {
	// FakeMethod[] fakeMethods = getFakeMethods((ModelElement) type, name);
	// if (fakeMethods != null) {
	// return new RubyClassType(new String[]{name}, null, fakeMethods);
	// }
	// }
	// }
	// FakeMethod[] fakeMethods = getFakeMethods((ModelElement) type, "Object");
	// return new RubyClassType(new String[]{"Object"}, null, fakeMethods);
	// }

	public static FakeMethod[] getFakeMethods(ModelElement parent, String klass) {
		Metaclass metaclass = BuiltinMethodsDatabase.get(klass);
		if (metaclass != null) {
			List<FakeMethod> fakeMethods = new ArrayList<FakeMethod>();
			addFakeMethods(parent, metaclass, fakeMethods);
			return fakeMethods.toArray(new FakeMethod[fakeMethods.size()]);
		}
		// XXX the following code is legacy
		String[] names = getBuiltinMethodNames(klass);
		if (names == null)
			return new FakeMethod[0];
		List<FakeMethod> methods = new ArrayList<FakeMethod>();
		for (int i = 0; i < names.length; i++) {
			FakeMethod method = new FakeMethod(parent, names[i]);
			method.setReceiver(klass);
			methods.add(method);
		}
		return methods.toArray(new FakeMethod[methods.size()]);
	}

	private static void addFakeMethods(ModelElement parent,
			Metaclass metaclass, List<FakeMethod> fakeMethods) {
		// process included modules first, to allow the class to override
		// some of the methods
		ModuleMetaclass[] includedModules = metaclass.getIncludedModules();
		for (int i = 0; i < includedModules.length; i++) {
			ModuleMetaclass module = includedModules[i];
			addFakeMethods(parent, module, fakeMethods);
		}
		MethodInfo[] methods = metaclass.getMethods();
		for (int i = 0; i < methods.length; i++) {
			MethodInfo info = methods[i];
			FakeMethod method = createFakeMethod(parent, metaclass, info);
			fakeMethods.add(method);
		}
		if (metaclass instanceof BuiltinMethodsDatabase.ClassMetaclass) {
			BuiltinMethodsDatabase.ClassMetaclass classMeta = (BuiltinMethodsDatabase.ClassMetaclass) metaclass;
			ClassMetaclass superClass = classMeta.getSuperClass();
			if (superClass != null)
				addFakeMethods(parent, superClass, fakeMethods);
		}
	}

	private static FakeMethod createFakeMethod(ModelElement parent,
			Metaclass metaclass, MethodInfo info) {
		FakeMethod method = new FakeMethod(parent, info.getName());
		method.setFlags(info.getFlags());
		int arity = info.getArity();
		IParameter[] parameters;
		if (arity > 0) {
			parameters = new IParameter[arity];
			for (int i = 0; i < arity; i++)
				parameters[i] = new MethodParameterInfo("arg" + (i + 1)); //$NON-NLS-1$
		} else if (arity < 0) {
			parameters = new IParameter[-arity];
			for (int i = 0; i < -arity - 1; i++)
				parameters[i] = new MethodParameterInfo("arg" + (i + 1)); //$NON-NLS-1$
			parameters[-arity - 1] = new MethodParameterInfo("..."); //$NON-NLS-1$
		} else {
			parameters = new IParameter[0];
		}
		method.setParameters(parameters);
		method.setReceiver(metaclass.getName());
		return method;
	}

	public static FakeMethod[] getFakeMetaMethods(ModelElement parent,
			String klass) {
		Metaclass metaclass = BuiltinMethodsDatabase.get(klass);
		if (metaclass != null) {
			ClassMetaclass metaMetaclass = metaclass.getMetaClass();
			List<FakeMethod> fakeMethods = new ArrayList<FakeMethod>();
			addFakeMethods(parent, metaMetaclass, fakeMethods);
			return fakeMethods.toArray(new FakeMethod[fakeMethods.size()]);
		}
		String[] names = getBuiltinMetaMethodNames(klass);
		if (names == null)
			return new FakeMethod[0];
		List<FakeMethod> methods = new ArrayList<FakeMethod>();
		for (int i = 0; i < names.length; i++) {
			FakeMethod method = new FakeMethod(parent, names[i]);
			method.setReceiver(klass);
			methods.add(method);
		}
		return methods.toArray(new FakeMethod[methods.size()]);
	}

	public static String[] getBuiltinMethodNames(String klass) {
		if (klass.equals("Object")) { //$NON-NLS-1$
			return BuiltinTypeMethods.objectMethods;
		} else if (klass.equals("String")) { //$NON-NLS-1$
			return BuiltinTypeMethods.stringMethods;
		} else if (klass.equals("Fixnum")) { //$NON-NLS-1$
			return BuiltinTypeMethods.fixnumMethods;
		} else if (klass.equals("Float")) { //$NON-NLS-1$
			return BuiltinTypeMethods.floatMethods;
		} else if (klass.equals("Regexp")) { //$NON-NLS-1$
			return BuiltinTypeMethods.regexpMethods;
		} else if (klass.equals("Array")) { //$NON-NLS-1$
			return BuiltinTypeMethods.arrayMethods;
		}
		return null;
	}

	public static String[] getBuiltinMetaMethodNames(String klass) {
		if (klass.equals("Object")) { //$NON-NLS-1$
			return BuiltinMethodsDatabase.objectMethods;
		}
		return null;
	}

	public static IType[] findTopLevelTypes(ISourceModule module,
			String namePrefix) {
		List<IType> result = new ArrayList<IType>();

		try {
			// TODO: add handling of "require"
			IModelElement[] children = module.getChildren();
			for (int i = 0; i < children.length; i++) {
				if (children[i] instanceof IType
						&& children[i].getElementName().startsWith(namePrefix))
					result.add((IType) children[i]);
			}
		} catch (ModelException e) {
			e.printStackTrace();
		}

		return result.toArray(new IType[result.size()]);
	}

	public static IField[] findTopLevelFields(ISourceModule module,
			String namePrefix) {
		List<IField> result = new ArrayList<IField>();

		try {
			IModelElement[] children = module.getChildren();
			for (int i = 0; i < children.length; i++) {
				if (children[i] instanceof IField
						&& children[i].getElementName().startsWith(namePrefix))
					result.add((IField) children[i]);
			}
		} catch (ModelException e) {
			e.printStackTrace();
		}

		return result.toArray(new IField[result.size()]);
	}

	public static IMethod[] findTopLevelMethods(IScriptProject project,
			String namePattern) {
		final List<IMethod> result = new ArrayList<IMethod>();
		SearchRequestor requestor = new SearchRequestor() {

			@Override
			public void acceptSearchMatch(SearchMatch match)
					throws CoreException {
				Object element = match.getElement();
				if (element instanceof IMethod) {
					IMethod meth = (IMethod) element;
					if (meth.getParent() instanceof ISourceModule) {
						result.add(meth);
					}
				}
			}

		};
		SearchPattern pattern = SearchPattern.createPattern(namePattern,
				IDLTKSearchConstants.METHOD, IDLTKSearchConstants.DECLARATIONS,
				SearchPattern.R_PATTERN_MATCH | SearchPattern.R_EXACT_MATCH,
				DLTKLanguageManager.getLanguageToolkit(project));
		IDLTKSearchScope scope;
		if (project != null)
			scope = SearchEngine.createSearchScope(project);
		else
			scope = SearchEngine.createWorkspaceScope(RubyLanguageToolkit
					.getDefault());
		try {
			SearchEngine engine = new SearchEngine();
			engine.search(pattern, new SearchParticipant[] { SearchEngine
					.getDefaultSearchParticipant() }, scope, requestor, null);
		} catch (CoreException e) {
			if (DLTKCore.DEBUG)
				e.printStackTrace();
		}

		return result.toArray(new IMethod[result.size()]);
	}

	/**
	 * Should return mixin-key of superclass
	 * 
	 * @param type
	 * @return
	 */
	public static String evaluateSuperClass(IType type) {
		String superclass = null;
		String[] superClasses;
		try {
			superClasses = type.getSuperClasses();
		} catch (ModelException e) {
			e.printStackTrace();
			return null;
		}
		if (superClasses != null && superClasses.length > 0) {
			superclass = superClasses[0];
			if (superclass.startsWith("::")) //$NON-NLS-1$
				superclass = superclass.substring(2);
			superclass = superclass.replaceAll("::", "{"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		// TODO: add appropriate evaluation here

		return superclass;
	}

}
