/*******************************************************************************
 * 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.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 + "*"); //$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;
	}

}
