/*******************************************************************************
 * Copyright (c) 2006, 2009 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.codeassist;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
import org.eclipse.jdt.internal.core.SearchableEnvironment;

public class MissingTypesGuesser extends ASTVisitor {
	public static interface GuessedTypeRequestor {
		public void accept(
				TypeBinding guessedType,
				Binding[] missingElements,
				int[] missingElementsStarts,
				int[] missingElementsEnds,
				boolean hasProblems);

	}

	private static class ResolutionCleaner extends ASTVisitor {
		private HashtableOfObjectToInt bitsMap = new HashtableOfObjectToInt();
		private boolean firstCall = true;

		public ResolutionCleaner(){
			super();
		}

		private void cleanUp(TypeReference typeReference) {
			if (this.firstCall) {
				this.bitsMap.put(typeReference, typeReference.bits);
			} else {
				typeReference.bits = this.bitsMap.get(typeReference);
			}
			typeReference.resolvedType = null;
		}

		private void cleanUp(ParameterizedSingleTypeReference typeReference) {
			this.cleanUp((TypeReference)typeReference);
			typeReference.bits &= ~ASTNode.DidResolve;
		}

		private void cleanUp(ParameterizedQualifiedTypeReference typeReference) {
			this.cleanUp((TypeReference)typeReference);
			typeReference.bits &= ~ASTNode.DidResolve;
		}

		public void cleanUp(TypeReference convertedType, BlockScope scope) {
			convertedType.traverse(this, scope);
			this.firstCall = false;
		}

		public void cleanUp(TypeReference convertedType, ClassScope scope) {
			convertedType.traverse(this, scope);
			this.firstCall = false;
		}

		public boolean visit(SingleTypeReference singleTypeReference, BlockScope scope) {
			this.cleanUp(singleTypeReference);
			return true;
		}

		public boolean visit(SingleTypeReference singleTypeReference, ClassScope scope) {
			this.cleanUp(singleTypeReference);
			return true;
		}

		public boolean visit(Wildcard wildcard, BlockScope scope) {
			this.cleanUp(wildcard);
			return true;
		}

		public boolean visit(Wildcard wildcard, ClassScope scope) {
			this.cleanUp(wildcard);
			return true;
		}

		public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
			this.cleanUp(arrayTypeReference);
			return true;
		}

		public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
			this.cleanUp(arrayTypeReference);
			return true;
		}

		public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, BlockScope scope) {
			this.cleanUp(parameterizedSingleTypeReference);
			return true;
		}

		public boolean visit(ParameterizedSingleTypeReference parameterizedSingleTypeReference, ClassScope scope) {
			this.cleanUp(parameterizedSingleTypeReference);
			return true;
		}

		public boolean visit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope) {
			this.cleanUp(qualifiedTypeReference);
			return true;
		}

		public boolean visit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope) {
			this.cleanUp(qualifiedTypeReference);
			return true;
		}

		public boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope) {
			this.cleanUp(arrayQualifiedTypeReference);
			return true;
		}

		public boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope) {
			this.cleanUp(arrayQualifiedTypeReference);
			return true;
		}

		public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, BlockScope scope) {
			this.cleanUp(parameterizedQualifiedTypeReference);
			return true;
		}

		public boolean visit(ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference, ClassScope scope) {
			this.cleanUp(parameterizedQualifiedTypeReference);
			return true;
		}

	}

	private CompletionEngine.CompletionProblemFactory problemFactory ;
	private  SearchableEnvironment nameEnvironment;

	private HashMap substituedTypes;
	private HashMap originalTypes;
	private int combinationsCount;

	public MissingTypesGuesser(CompletionEngine completionEngine) {
		this.problemFactory = completionEngine.problemFactory;
		this.nameEnvironment = completionEngine.nameEnvironment;
	}

	private boolean computeMissingElements(
			QualifiedTypeReference[] substituedTypeNodes,
			char[][][] originalTypeNames,
			Binding[] missingElements,
			int[] missingElementsStarts,
			int[] missingElementsEnds) {
		int length = substituedTypeNodes.length;

		for (int i = 0; i < length; i++) {
			TypeReference substituedType = substituedTypeNodes[i];
			if (substituedType.resolvedType == null) return false;
			ReferenceBinding erasure = (ReferenceBinding)substituedType.resolvedType.leafComponentType().erasure();
			Binding missingElement;
			int depthToRemove = originalTypeNames[i].length - 1 ;
			if (depthToRemove == 0) {
				missingElement = erasure;
			} else {
				int depth = erasure.depth() + 1;

				if (depth > depthToRemove) {
					missingElement = erasure.enclosingTypeAt(depthToRemove);
				} else {
					return false;
					///////////////////////////////////////////////////////////
					//// Uncomment the following code to return missing package
					///////////////////////////////////////////////////////////
					//depthToRemove -= depth;
					//PackageBinding packageBinding = erasure.getPackage();
					//while(depthToRemove > 0) {
					//	packageBinding = packageBinding.parent;
					//	depthToRemove--;
					//}
					//missingElement = packageBinding;
				}
			}

			missingElements[i] = missingElement;
			missingElementsStarts[i] = substituedType.sourceStart;
			missingElementsEnds[i] = substituedType.sourceEnd + 1;

		}

		return true;
	}

	private TypeReference convert(ArrayQualifiedTypeReference typeRef) {
		if (typeRef.resolvedType != null) {
			if (typeRef.resolvedType.isValidBinding()) {
				ArrayQualifiedTypeReference convertedType =
					new ArrayQualifiedTypeReference(
							typeRef.tokens,
							typeRef.dimensions(),
							typeRef.sourcePositions);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = typeRef.sourceEnd;
				return convertedType;
			} else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
				// only the first token must be resolved
				if(((ReferenceBinding)typeRef.resolvedType.leafComponentType()).compoundName.length != 1) return null;

				char[][] typeName = typeRef.getTypeName();
				char[][][] typeNames = findTypeNames(typeName);
				if(typeNames == null || typeNames.length == 0) return null;
				ArrayQualifiedTypeReference convertedType =
					new ArrayQualifiedTypeReference(
							typeNames[0],
							typeRef.dimensions(),
							new long[typeNames[0].length]);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = (int)(typeRef.sourcePositions[0] & 0x00000000FFFFFFFFL);
				this.substituedTypes.put(convertedType, typeNames);
				this.originalTypes.put(convertedType, typeName);
				this.combinationsCount *= typeNames.length;
				return convertedType;
			}
		}
		return null;
	}

	private TypeReference convert(ArrayTypeReference typeRef) {
		if (typeRef.resolvedType != null) {
			if (typeRef.resolvedType.isValidBinding()) {
				ArrayTypeReference convertedType =
					new ArrayTypeReference(
							typeRef.token,
							typeRef.dimensions,
							0);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = typeRef.originalSourceEnd;
				return convertedType;
			} else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
				char[][] typeName = typeRef.getTypeName();
				char[][][] typeNames = findTypeNames(typeName);
				if(typeNames == null || typeNames.length == 0) return null;
				ArrayQualifiedTypeReference convertedType =
					new ArrayQualifiedTypeReference(
							typeNames[0],
							typeRef.dimensions,
							new long[typeNames[0].length]);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = typeRef.originalSourceEnd;
				this.substituedTypes.put(convertedType, typeNames);
				this.originalTypes.put(convertedType, typeName);
				this.combinationsCount *= typeNames.length;
				return convertedType;
			}
		}
		return null;
	}

	private TypeReference convert(ParameterizedQualifiedTypeReference typeRef) {
		if (typeRef.resolvedType != null) {
			TypeReference[][] typeArguments = typeRef.typeArguments;
			int length = typeArguments.length;
			TypeReference[][] convertedTypeArguments = new TypeReference[length][];
			next : for (int i = 0; i < length; i++) {
				if (typeArguments[i] == null) continue next;
				int length2 = typeArguments[i].length;
				convertedTypeArguments[i] = new TypeReference[length2];
				for (int j = 0; j < length2; j++) {
					convertedTypeArguments[i][j] = convert(typeArguments[i][j]);
					if (convertedTypeArguments[i][j] == null) return null;
				}
			}

			if (typeRef.resolvedType.isValidBinding()) {
				ParameterizedQualifiedTypeReference convertedType =
					new ParameterizedQualifiedTypeReference(
							typeRef.tokens,
							convertedTypeArguments,
							typeRef.dimensions(),
							new long[typeRef.tokens.length]);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = typeRef.sourceEnd;
				return convertedType;
			} else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
				// only the first token must be resolved
				if(((ReferenceBinding)typeRef.resolvedType.leafComponentType()).compoundName.length != 1) return null;

				char[][] typeName = typeRef.getTypeName();
				char[][][] typeNames = findTypeNames(typeName);
				if(typeNames == null || typeNames.length == 0) return null;

				TypeReference[][] newConvertedTypeArguments = new TypeReference[typeNames[0].length][];
				for (int k = newConvertedTypeArguments.length - 1, l = convertedTypeArguments.length -1; k > -1 && l > -1;) {
					newConvertedTypeArguments[k] = convertedTypeArguments[l];
					k--;
					l--;
				}

				ParameterizedQualifiedTypeReference convertedType =
					new ParameterizedQualifiedTypeReference(
							typeNames[0],
							newConvertedTypeArguments,
							typeRef.dimensions(),
							new long[typeNames[0].length]);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = (int)(typeRef.sourcePositions[0] & 0x00000000FFFFFFFFL);
				this.substituedTypes.put(convertedType, typeNames);
				this.originalTypes.put(convertedType, typeName);
				this.combinationsCount *= typeNames.length;
				return convertedType;
			}
		}
		return null;
	}

	private TypeReference convert(ParameterizedSingleTypeReference typeRef) {
		if (typeRef.resolvedType != null) {
			TypeReference[] typeArguments = typeRef.typeArguments;
			int length = typeArguments.length;
			TypeReference[] convertedTypeArguments = new TypeReference[length];
			for (int i = 0; i < length; i++) {
				convertedTypeArguments[i] = convert(typeArguments[i]);
				if(convertedTypeArguments[i] == null) return null;
			}

			if (typeRef.resolvedType.isValidBinding()) {
				ParameterizedSingleTypeReference convertedType =
					new ParameterizedSingleTypeReference(
							typeRef.token,
							convertedTypeArguments,
							typeRef.dimensions,
							0);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = typeRef.sourceEnd;
				return convertedType;
			} else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
				char[][] typeName = typeRef.getTypeName();
				char[][][] typeNames = findTypeNames(typeName);
				if(typeNames == null || typeNames.length == 0) return null;

				TypeReference[][] allConvertedTypeArguments = new TypeReference[typeNames[0].length][];
				allConvertedTypeArguments[allConvertedTypeArguments.length - 1] = convertedTypeArguments;

				ParameterizedQualifiedTypeReference convertedType =
					new ParameterizedQualifiedTypeReference(
							typeNames[0],
							allConvertedTypeArguments,
							typeRef.dimensions,
							new long[typeNames[0].length]);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = typeRef.sourceEnd;
				this.substituedTypes.put(convertedType, typeNames);
				this.originalTypes.put(convertedType, typeName);
				this.combinationsCount *= typeNames.length;
				return convertedType;
			}
		}
		return null;
	}

	private TypeReference convert(QualifiedTypeReference typeRef) {
		if (typeRef.resolvedType != null) {
			if (typeRef.resolvedType.isValidBinding()) {
				QualifiedTypeReference convertedType = new QualifiedTypeReference(typeRef.tokens, typeRef.sourcePositions);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = typeRef.sourceEnd;
				return convertedType;
			} else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
				// only the first token must be resolved
				if(((ReferenceBinding)typeRef.resolvedType).compoundName.length != 1) return null;

				char[][] typeName = typeRef.getTypeName();
				char[][][] typeNames = findTypeNames(typeName);
				if(typeNames == null || typeNames.length == 0) return null;
				QualifiedTypeReference convertedType = new QualifiedTypeReference(typeNames[0], new long[typeNames[0].length]);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = (int)(typeRef.sourcePositions[0] & 0x00000000FFFFFFFFL);
				this.substituedTypes.put(convertedType, typeNames);
				this.originalTypes.put(convertedType, typeName);
				this.combinationsCount *= typeNames.length;
				return convertedType;
			}
		}
		return null;
	}

	private TypeReference convert(SingleTypeReference typeRef) {
		if (typeRef.resolvedType != null) {
			if (typeRef.resolvedType.isValidBinding()) {
				SingleTypeReference convertedType = new SingleTypeReference(typeRef.token, 0);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = typeRef.sourceEnd;
				return convertedType;
			} else if((typeRef.resolvedType.problemId() & ProblemReasons.NotFound) != 0) {
				char[][] typeName = typeRef.getTypeName();
				char[][][] typeNames = findTypeNames(typeName);
				if(typeNames == null || typeNames.length == 0) return null;
				QualifiedTypeReference convertedType = new QualifiedTypeReference(typeNames[0], new long[typeNames[0].length]);
				convertedType.sourceStart = typeRef.sourceStart;
				convertedType.sourceEnd = typeRef.sourceEnd;
				this.substituedTypes.put(convertedType, typeNames);
				this.originalTypes.put(convertedType, typeName);
				this.combinationsCount *= typeNames.length;
				return convertedType;
			}
		}
		return null;
	}

	private TypeReference convert(TypeReference typeRef) {
		if (typeRef instanceof ParameterizedSingleTypeReference) {
			return convert((ParameterizedSingleTypeReference)typeRef);
		} else if(typeRef instanceof ParameterizedQualifiedTypeReference) {
			return convert((ParameterizedQualifiedTypeReference)typeRef);
		} else if (typeRef instanceof ArrayTypeReference) {
			return convert((ArrayTypeReference)typeRef);
		} else if(typeRef instanceof ArrayQualifiedTypeReference) {
			return convert((ArrayQualifiedTypeReference)typeRef);
		} else if(typeRef instanceof Wildcard) {
			return convert((Wildcard)typeRef);
		} else if (typeRef instanceof SingleTypeReference) {
			return convert((SingleTypeReference)typeRef);
		} else if (typeRef instanceof QualifiedTypeReference) {
			return convert((QualifiedTypeReference)typeRef);
		}
		return null;
	}

	private TypeReference convert(Wildcard typeRef) {
		TypeReference bound = typeRef.bound;
		TypeReference convertedBound = null;
		if (bound != null) {
			convertedBound = convert(bound);
			if (convertedBound == null) return null;
		}
		Wildcard convertedType = new Wildcard(typeRef.kind);
		convertedType.bound = convertedBound;
		convertedType.sourceStart = typeRef.sourceStart;
		convertedType.sourceEnd = typeRef.sourceEnd;
		return convertedType;
	}

	private char[][][] findTypeNames(char[][] missingTypeName) {
		char[] missingSimpleName = missingTypeName[missingTypeName.length - 1];
		final boolean isQualified = missingTypeName.length > 1;
		final char[] missingFullyQualifiedName =
			isQualified ? CharOperation.concatWith(missingTypeName, '.') : null;
		final ArrayList results = new ArrayList();
		ISearchRequestor storage = new ISearchRequestor() {
			public void acceptConstructor(
					int modifiers,
					char[] simpleTypeName,
					int parameterCount,
					char[] signature,
					char[][] parameterTypes,
					char[][] parameterNames,
					int typeModifiers,
					char[] packageName,
					int extraFlags,
					String path,
					AccessRestriction access) {
				// constructors aren't searched
			}
			public void acceptPackage(char[] packageName) {
				// package aren't searched
			}
			public void acceptType(
					char[] packageName,
					char[] typeName,
					char[][] enclosingTypeNames,
					int modifiers,
					AccessRestriction accessRestriction) {
				char[] fullyQualifiedName = CharOperation.concat(packageName, CharOperation.concat(CharOperation.concatWith(enclosingTypeNames, '.'), typeName, '.'), '.');
				if (isQualified && !CharOperation.endsWith(fullyQualifiedName, missingFullyQualifiedName)) return;
				char[][] compoundName = CharOperation.splitOn('.', fullyQualifiedName);
				results.add(compoundName);
			}

		};
		this.nameEnvironment.findExactTypes(missingSimpleName, true, IJavaSearchConstants.TYPE, storage);
		if(results.size() == 0) return null;
		return (char[][][])results.toArray(new char[results.size()][0][0]);
	}

	private char[][] getOriginal(TypeReference typeRef) {
		return (char[][])this.originalTypes.get(typeRef);
	}

	private QualifiedTypeReference[] getSubstituedTypes() {
		Set types = this.substituedTypes.keySet();
		return (QualifiedTypeReference[]) types.toArray(new QualifiedTypeReference[types.size()]);
	}

	private char[][][] getSubstitution(TypeReference typeRef) {
		return (char[][][])this.substituedTypes.get(typeRef);
	}

	public void guess(TypeReference typeRef, Scope scope, GuessedTypeRequestor requestor) {
		this.substituedTypes = new HashMap();
		this.originalTypes = new HashMap();
		this.combinationsCount = 1;

		TypeReference convertedType = convert(typeRef);

		if(convertedType == null) return;

		QualifiedTypeReference[] substituedTypeNodes = getSubstituedTypes();
		int length = substituedTypeNodes.length;

		int[] substitutionsIndexes = new int[substituedTypeNodes.length];
		char[][][][] subtitutions = new char[substituedTypeNodes.length][][][];
		char[][][] originalTypeNames = new char[substituedTypeNodes.length][][];
		for (int i = 0; i < substituedTypeNodes.length; i++) {
			subtitutions[i] = getSubstitution(substituedTypeNodes[i]);
			originalTypeNames[i] = getOriginal(substituedTypeNodes[i]);
		}

		ResolutionCleaner resolutionCleaner = new ResolutionCleaner();
		for (int i = 0; i < this.combinationsCount; i++) {

			nextSubstitution(substituedTypeNodes, subtitutions, substitutionsIndexes);


			this.problemFactory.startCheckingProblems();
			TypeBinding guessedType = null;
			switch (scope.kind) {
				case Scope.METHOD_SCOPE :
				case Scope.BLOCK_SCOPE :
					resolutionCleaner.cleanUp(convertedType, (BlockScope)scope);
					guessedType = convertedType.resolveType((BlockScope)scope);
					break;
				case Scope.CLASS_SCOPE :
					resolutionCleaner.cleanUp(convertedType, (ClassScope)scope);
					guessedType = convertedType.resolveType((ClassScope)scope);
					break;
			}
			this.problemFactory.stopCheckingProblems();
			if (!this.problemFactory.hasForbiddenProblems) {
				if (guessedType != null) {
					Binding[] missingElements = new Binding[length];
					int[] missingElementsStarts = new int[length];
					int[] missingElementsEnds = new int[length];

					if(computeMissingElements(
							substituedTypeNodes,
							originalTypeNames,
							missingElements,
							missingElementsStarts,
							missingElementsEnds)) {
						requestor.accept(
								guessedType.capture(scope, typeRef.sourceEnd),
								missingElements,
								missingElementsStarts,
								missingElementsEnds,
								this.problemFactory.hasAllowedProblems);
					}
				}
			}
		}
	}
	private void nextSubstitution(
			QualifiedTypeReference[] substituedTypeNodes,
			char[][][][] subtitutions,
			int[] substitutionsIndexes) {
		int length = substituedTypeNodes.length;

		done : for (int i = 0; i < length; i++) {
			if(substitutionsIndexes[i] < subtitutions[i].length - 1) {
				substitutionsIndexes[i]++;
				break done;
			} else {
				substitutionsIndexes[i] = 0;
			}
		}

		for (int i = 0; i < length; i++) {
			QualifiedTypeReference qualifiedTypeReference = substituedTypeNodes[i];
			qualifiedTypeReference.tokens = subtitutions[i][substitutionsIndexes[i]];
			qualifiedTypeReference.sourcePositions = new long[qualifiedTypeReference.tokens.length];
			if(qualifiedTypeReference instanceof ParameterizedQualifiedTypeReference) {
				ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference =
					(ParameterizedQualifiedTypeReference)qualifiedTypeReference;
				TypeReference[][] typeArguments = parameterizedQualifiedTypeReference.typeArguments;
				TypeReference[][] newTypeArguments = new TypeReference[qualifiedTypeReference.tokens.length][];
				for (int j = newTypeArguments.length - 1, k = typeArguments.length -1; j > -1 && k > -1;) {
					newTypeArguments[j] = typeArguments[k];
					j--;
					k--;
				}
			}
		}
	}
}
