/*******************************************************************************
 * Copyright (c) 2000, 2006 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 API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jdt.core.BindingKey;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTRequestor;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;



public class TypeEnvironment {
	
	private static class ProjectKeyPair {
		private final IJavaProject fProject;
		private final String fBindingKey;
		
		public ProjectKeyPair(IJavaProject project, String bindingKey) {
			fProject= project;
			fBindingKey= bindingKey;
		}
		
		public boolean equals(Object other) {
			if (this == other)
				return true;
			if (! (other instanceof ProjectKeyPair))
				return false;
			ProjectKeyPair otherPair= (ProjectKeyPair) other;
			return fProject.equals(otherPair.fProject) && fBindingKey.equals(otherPair.fBindingKey);
		}
		
		public int hashCode() {
			return fProject.hashCode() + fBindingKey.hashCode();
		}
	}
	
	/** Type code for the primitive type "int". */
	public final PrimitiveType INT= new PrimitiveType(this, PrimitiveType.INT, BindingKey.createTypeBindingKey("int")); //$NON-NLS-1$
	/** Type code for the primitive type "char". */
	public final PrimitiveType CHAR = new PrimitiveType(this, PrimitiveType.CHAR, BindingKey.createTypeBindingKey("char")); //$NON-NLS-1$
	/** Type code for the primitive type "boolean". */
	public final PrimitiveType BOOLEAN = new PrimitiveType(this, PrimitiveType.BOOLEAN, BindingKey.createTypeBindingKey("boolean")); //$NON-NLS-1$
	/** Type code for the primitive type "short". */
	public final PrimitiveType SHORT = new PrimitiveType(this, PrimitiveType.SHORT, BindingKey.createTypeBindingKey("short")); //$NON-NLS-1$
	/** Type code for the primitive type "long". */
	public final PrimitiveType LONG = new PrimitiveType(this, PrimitiveType.LONG, BindingKey.createTypeBindingKey("long")); //$NON-NLS-1$
	/** Type code for the primitive type "float". */
	public final PrimitiveType FLOAT = new PrimitiveType(this, PrimitiveType.FLOAT, BindingKey.createTypeBindingKey("float")); //$NON-NLS-1$
	/** Type code for the primitive type "double". */
	public final PrimitiveType DOUBLE = new PrimitiveType(this, PrimitiveType.DOUBLE, BindingKey.createTypeBindingKey("double")); //$NON-NLS-1$
	/** Type code for the primitive type "byte". */
	public final PrimitiveType BYTE = new PrimitiveType(this, PrimitiveType.BYTE, BindingKey.createTypeBindingKey("byte")); //$NON-NLS-1$
	
	/** Type code for the primitive type "null". */
	public final NullType NULL= new NullType(this);
	
	public final VoidType VOID= new VoidType(this); 
	
	final PrimitiveType[] PRIMITIVE_TYPES= {INT, CHAR, BOOLEAN, SHORT, LONG, FLOAT, DOUBLE, BYTE};
	
	private static final String[] BOXED_PRIMITIVE_NAMES= new String[] {
		"java.lang.Integer",  //$NON-NLS-1$
		"java.lang.Character",  //$NON-NLS-1$
		"java.lang.Boolean",  //$NON-NLS-1$
		"java.lang.Short",  //$NON-NLS-1$
		"java.lang.Long",  //$NON-NLS-1$
		"java.lang.Float",  //$NON-NLS-1$
		"java.lang.Double",  //$NON-NLS-1$
		"java.lang.Byte"};  //$NON-NLS-1$
	
	private TType OBJECT_TYPE= null;
	
	private Map[] fArrayTypes= new Map[] { new HashMap() };
	private Map fStandardTypes= new HashMap();
	private Map fGenericTypes= new HashMap();
	private Map fParameterizedTypes= new HashMap();
	private Map fRawTypes= new HashMap();
	private Map fTypeVariables= new HashMap();
	private Map fCaptureTypes= new HashMap();
	private Map fExtendsWildcardTypes= new HashMap();
	private Map fSuperWildcardTypes= new HashMap();
	private UnboundWildcardType fUnboundWildcardType= null;
	
	private static final int MAX_ENTRIES= 1024;
	private Map/*<TypeTuple, Boolean>*/ fSubTypeCache= new LinkedHashMap(50, 0.75f, true) {
		private static final long serialVersionUID= 1L;
		protected boolean removeEldestEntry(Map.Entry eldest) {
			return size() > MAX_ENTRIES;
		}
	};
	
	/**
	 * Map from TType to its known subtypes, or <code>null</code> iff subtype
	 * information was not requested in the constructor.
	 */
	private Map/*<TType, List<TType>>*/ fSubTypes;
	
	public static ITypeBinding[] createTypeBindings(TType[] types, IJavaProject project) {
		final Map mapping= new HashMap();
		List keys= new ArrayList();
		for (int i= 0; i < types.length; i++) {
			TType type= types[i];
			String bindingKey= type.getBindingKey();
			mapping.put(bindingKey, type);
			keys.add(bindingKey);
		}
		ASTParser parser= ASTParser.newParser(AST.JLS3);
		parser.setProject(project);
		parser.setResolveBindings(true);
		parser.createASTs(new ICompilationUnit[0], (String[])keys.toArray(new String[keys.size()]), 
			new ASTRequestor() {
				public void acceptBinding(String bindingKey, IBinding binding) {
					mapping.put(bindingKey, binding);
				}
			}, null);
		ITypeBinding[] result= new ITypeBinding[types.length];
		for (int i= 0; i < types.length; i++) {
			TType type= types[i];
			String bindingKey= type.getBindingKey();
			Object value= mapping.get(bindingKey);
			if (value instanceof ITypeBinding) {
				result[i]= (ITypeBinding)value;
			}
		}
		return result;
	}
	
	private boolean fIdentityTest;
	
	public TypeEnvironment() {
		this(false);
	}
	
	public TypeEnvironment(boolean rememberSubtypes) {
		if (rememberSubtypes) {
			fSubTypes= new HashMap();
		}
	}
	
	public boolean isIdentityTest() {
		return fIdentityTest;
	}
	
	Map/*<TypeTuple, Boolean>*/ getSubTypeCache() {
		return fSubTypeCache;
	}
	
	public TType create(ITypeBinding binding) {
		if (binding.isPrimitive()) {
			return createPrimitiveType(binding);
		} else if (binding.isArray()) {
			return createArrayType(binding);
		} else if (binding.isRawType()) {
			return createRawType(binding);
		} else if (binding.isGenericType()) {
			return createGenericType(binding);
		} else if (binding.isParameterizedType()) {
			return createParameterizedType(binding);
		} else if (binding.isTypeVariable()) {
			return createTypeVariable(binding);
		} else if (binding.isWildcardType()) {
			if (binding.getBound() == null) {
				return createUnboundWildcardType(binding);
			} else if (binding.isUpperbound()) {
				return createExtendsWildCardType(binding);
			} else {
				return createSuperWildCardType(binding);
			}
		} else if (binding.isCapture()) {
			return createCaptureType(binding);
		}
		if ("null".equals(binding.getName())) //$NON-NLS-1$
			return NULL;
		return createStandardType(binding);
	}
	
	public TType[] create(ITypeBinding[] bindings) {
		TType[] result= new TType[bindings.length];
		for (int i= 0; i < bindings.length; i++) {
			result[i]= create(bindings[i]);
		}
		return result;
	}
	
	/**
	 * Returns the TType for java.lang.Object.
	 * <p>
	 * Warning: currently returns <code>null</code> unless this type environment
	 * has already created its first hierarchy type.
	 * 
	 * @return the TType for java.lang.Object
	 */
	public TType getJavaLangObject() {
		return OBJECT_TYPE;
	}
	
	void initializeJavaLangObject(ITypeBinding object) {
		if (OBJECT_TYPE != null)
			return;
		
		TType objectType= createStandardType(object);
		Assert.isTrue(objectType.isJavaLangObject());
	}
	
	PrimitiveType createUnBoxed(StandardType type) {
		String name= type.getPlainPrettySignature();
		for (int i= 0; i < BOXED_PRIMITIVE_NAMES.length; i++) {
			if (BOXED_PRIMITIVE_NAMES[i].equals(name))
				return PRIMITIVE_TYPES[i];
		}
		return null;
	}
	
	StandardType createBoxed(PrimitiveType type, IJavaProject focus) {
		String fullyQualifiedName= BOXED_PRIMITIVE_NAMES[type.getId()];
		try {
			IType javaElementType= focus.findType(fullyQualifiedName);
			StandardType result= (StandardType)fStandardTypes.get(javaElementType);
			if (result != null)
				return result;
			ASTParser parser= ASTParser.newParser(AST.JLS3);
			parser.setProject(focus);
			IBinding[] bindings= parser.createBindings(new IJavaElement[] {javaElementType} , null);
			return createStandardType((ITypeBinding)bindings[0]);
		} catch (JavaModelException e) {
			// fall through
		}
		return null;
	}
	
	Map/*<TType, List<TType>>*/ getSubTypes() {
		return fSubTypes;
	}
	
	private void cacheSubType(TType supertype, TType result) {
		if (fSubTypes == null)
			return;
		if (supertype == null)
			supertype= OBJECT_TYPE;
		
		ArrayList subtypes= (ArrayList) fSubTypes.get(supertype);
		if (subtypes == null) {
			subtypes= new ArrayList(5);
			fSubTypes.put(supertype, subtypes);
		} else {
			Assert.isTrue(! subtypes.contains(result));
		}
		subtypes.add(result);
	}

	private void cacheSubTypes(TType[] interfaces, TType result) {
		for (int i= 0; i < interfaces.length; i++) {
			cacheSubType(interfaces[i], result);
		}
	}

	private TType createPrimitiveType(ITypeBinding binding) {
		String name= binding.getName();
		String[] names= PrimitiveType.NAMES;
		for (int i= 0; i < names.length; i++) {
			if (name.equals(names[i])) {
				return PRIMITIVE_TYPES[i];
			}
		}
		Assert.isTrue(false, "Primitive type " + name + "unkown");  //$NON-NLS-1$//$NON-NLS-2$
		return null;
	}

	private ArrayType createArrayType(ITypeBinding binding) {
		int index= binding.getDimensions() - 1;
		TType elementType= create(binding.getElementType());
		Map arrayTypes= getArrayTypesMap(index);
		ArrayType result= (ArrayType)arrayTypes.get(elementType);
		if (result != null)
			return result;
		result= new ArrayType(this);
		arrayTypes.put(elementType, result);
		result.initialize(binding, elementType);
		return result;
	}
	
	public ArrayType createArrayType(TType elementType, int dimensions) {
		Assert.isTrue(! elementType.isArrayType());
		Assert.isTrue(! elementType.isAnonymous());
		Assert.isTrue(dimensions > 0);
		
		int index= dimensions - 1;
		Map arrayTypes= getArrayTypesMap(index);
		ArrayType result= (ArrayType)arrayTypes.get(elementType);
		if (result != null)
			return result;
		result= new ArrayType(this, BindingKey.createArrayTypeBindingKey(elementType.getBindingKey(), dimensions));
		arrayTypes.put(elementType, result);
		result.initialize(elementType, dimensions);
		return result;
	}

	private Map getArrayTypesMap(int index) {
		int oldLength= fArrayTypes.length;
		if (index >= oldLength) {
			Map[] newArray= new Map[index + 1];
			System.arraycopy(fArrayTypes, 0, newArray, 0, oldLength);
			fArrayTypes= newArray;
		}
		Map arrayTypes= fArrayTypes[index];
		if (arrayTypes == null) {
			arrayTypes= new HashMap();
			fArrayTypes[index]= arrayTypes;
		}
		return arrayTypes;
	}
	
	private StandardType createStandardType(ITypeBinding binding) {
		IJavaElement javaElement= binding.getJavaElement();
		StandardType result= (StandardType)fStandardTypes.get(javaElement);
		if (result != null)
			return result;
		result= new StandardType(this);
		fStandardTypes.put(javaElement, result);
		result.initialize(binding, (IType)javaElement);
		if (OBJECT_TYPE == null && result.isJavaLangObject())
			OBJECT_TYPE= result;
		return result;
	}
	
	private GenericType createGenericType(ITypeBinding binding) {
		IJavaElement javaElement= binding.getJavaElement();
		GenericType result= (GenericType)fGenericTypes.get(javaElement);
		if (result != null)
			return result;
		result= new GenericType(this);
		fGenericTypes.put(javaElement, result);
		result.initialize(binding, (IType)javaElement);
		cacheSubType(result.getSuperclass(), result);
		cacheSubTypes(result.getInterfaces(), result);
		return result;
	}
	
	private ParameterizedType createParameterizedType(ITypeBinding binding) {
		ParameterizedType key= new ParameterizedType(this);
		key.initialize(binding, (IType)binding.getJavaElement());
		fIdentityTest= false;
		ParameterizedType result= null;
		try {
			result= (ParameterizedType)fParameterizedTypes.get(key);
		} finally {
			fIdentityTest= true;
		}
		if (result != null)
			return result;
		result= key;
		fParameterizedTypes.put(key, result);
		cacheSubType(result.getSuperclass(), result);
		cacheSubTypes(result.getInterfaces(), result);
		return result;
	}
	
	private RawType createRawType(ITypeBinding binding) {
		IJavaElement javaElement= binding.getJavaElement();
		RawType result= (RawType)fRawTypes.get(javaElement);
		if (result != null)
			return result;
		result= new RawType(this);
		fRawTypes.put(javaElement, result);
		result.initialize(binding, (IType)javaElement);
		cacheSubType(result.getSuperclass(), result);
		cacheSubTypes(result.getInterfaces(), result);
		return result;
	}
	
	private TType createUnboundWildcardType(ITypeBinding binding) {
		if (fUnboundWildcardType == null) {
			fUnboundWildcardType= new UnboundWildcardType(this);
			fUnboundWildcardType.initialize(binding);
		}
		return fUnboundWildcardType;
	}
	
	private TType createExtendsWildCardType(ITypeBinding binding) {
		TType bound= create(binding.getBound());
		ExtendsWildcardType result= (ExtendsWildcardType)fExtendsWildcardTypes.get(bound);
		if (result != null)
			return result;
		result= new ExtendsWildcardType(this);
		fExtendsWildcardTypes.put(bound, result);
		result.initialize(binding);
		return result;
	}	
	
	private TType createSuperWildCardType(ITypeBinding binding) {
		TType bound= create(binding.getBound());
		SuperWildcardType result= (SuperWildcardType)fSuperWildcardTypes.get(bound);
		if (result != null)
			return result;
		result= new SuperWildcardType(this);
		fSuperWildcardTypes.put(bound, result);
		result.initialize(binding);
		return result;
	}	
	
	private TypeVariable createTypeVariable(ITypeBinding binding) {
		IJavaElement javaElement= binding.getJavaElement();
		TypeVariable result= (TypeVariable)fTypeVariables.get(javaElement);
		if (result != null)
			return result;
		result= new TypeVariable(this);
		fTypeVariables.put(javaElement, result);
		result.initialize(binding, (ITypeParameter)javaElement);
		return result;
	}
	
	private CaptureType createCaptureType(ITypeBinding binding) {
		IJavaProject javaProject= binding.getDeclaringClass().getJavaElement().getJavaProject();
		String bindingKey= binding.getKey();
		ProjectKeyPair pair= new ProjectKeyPair(javaProject, bindingKey);
		CaptureType result= (CaptureType)fCaptureTypes.get(pair);
		if (result != null)
			return result;
		result= new CaptureType(this);
		fCaptureTypes.put(pair, result);
		result.initialize(binding, javaProject);
		return result;
	}
}
