/*******************************************************************************
 * 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 org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.codeassist.complete.CompletionParser;
import org.eclipse.jdt.internal.codeassist.complete.CompletionScanner;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;
import org.eclipse.jdt.internal.compiler.util.Util;

public class UnresolvedReferenceNameFinder extends ASTVisitor {
	private static final int MAX_LINE_COUNT = 100;
	private static final int FAKE_BLOCKS_COUNT = 20;

	public static interface UnresolvedReferenceNameRequestor {
		public void acceptName(char[] name);
	}

	private UnresolvedReferenceNameRequestor requestor;

	private CompletionEngine completionEngine;
	private CompletionParser parser;
	private CompletionScanner completionScanner;

	private int parentsPtr;
	private ASTNode[] parents;

	private int potentialVariableNamesPtr;
	private char[][] potentialVariableNames;
	private int[] potentialVariableNameStarts;

	private SimpleSetOfCharArray acceptedNames = new SimpleSetOfCharArray();

	public UnresolvedReferenceNameFinder(CompletionEngine completionEngine) {
		this.completionEngine = completionEngine;
		this.parser = completionEngine.parser;
		this.completionScanner = (CompletionScanner) this.parser.scanner;
	}

	private void acceptName(char[] name) {
		// the null check is added to fix bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=166570
		if (name == null) return;

		if (!CharOperation.prefixEquals(this.completionEngine.completionToken, name, false /* ignore case */)
				&& !(this.completionEngine.options.camelCaseMatch && CharOperation.camelCaseMatch(this.completionEngine.completionToken, name))) return;

		if (this.acceptedNames.includes(name)) return;

		this.acceptedNames.add(name);

		// accept result
		this.requestor.acceptName(name);
	}

	public void find(
			char[] startWith,
			Initializer initializer,
			ClassScope scope,
			int from,
			char[][] discouragedNames,
			UnresolvedReferenceNameRequestor nameRequestor) {
		MethodDeclaration fakeMethod =
			this.findAfter(startWith, scope, from, initializer.bodyEnd, MAX_LINE_COUNT, false, discouragedNames, nameRequestor);
		if (fakeMethod != null) fakeMethod.traverse(this, scope);
	}

	public void find(
			char[] startWith,
			AbstractMethodDeclaration methodDeclaration,
			int from,
			char[][] discouragedNames,
			UnresolvedReferenceNameRequestor nameRequestor) {
		MethodDeclaration fakeMethod =
			this.findAfter(startWith, methodDeclaration.scope, from, methodDeclaration.bodyEnd, MAX_LINE_COUNT, false, discouragedNames, nameRequestor);
		if (fakeMethod != null) fakeMethod.traverse(this, methodDeclaration.scope.classScope());
	}

	public void findAfter(
			char[] startWith,
			Scope scope,
			ClassScope classScope,
			int from,
			int to,
			char[][] discouragedNames,
			UnresolvedReferenceNameRequestor nameRequestor) {
		MethodDeclaration fakeMethod =
			this.findAfter(startWith, scope, from, to, MAX_LINE_COUNT / 2, true, discouragedNames, nameRequestor);
		if (fakeMethod != null) fakeMethod.traverse(this, classScope);
	}

	private MethodDeclaration findAfter(
			char[] startWith,
			Scope s,
			int from,
			int to,
			int maxLineCount,
			boolean outsideEnclosingBlock,
			char[][] discouragedNames,
			UnresolvedReferenceNameRequestor nameRequestor) {
		this.requestor = nameRequestor;

		// reinitialize completion scanner to be usable as a normal scanner
		this.completionScanner.cursorLocation = 0;

		if (!outsideEnclosingBlock) {
			// compute location of the end of the current block
			this.completionScanner.resetTo(from + 1, to);
			this.completionScanner.jumpOverBlock();

			to = this.completionScanner.startPosition - 1;
		}

		int maxEnd =
			this.completionScanner.getLineEnd(
					Util.getLineNumber(from, this.completionScanner.lineEnds, 0, this.completionScanner.linePtr) + maxLineCount);

		int end;
		if (maxEnd < 0) {
			end = to;
		} else {
			end = maxEnd < to ? maxEnd : to;
		}

		this.parser.startRecordingIdentifiers(from, end);

		MethodDeclaration fakeMethod = this.parser.parseSomeStatements(
				from,
				end,
				outsideEnclosingBlock ? FAKE_BLOCKS_COUNT : 0,
				s.compilationUnitScope().referenceContext);

		this.parser.stopRecordingIdentifiers();

		if(!initPotentialNamesTables(discouragedNames)) return null;

		this.parentsPtr = -1;
		this.parents = new ASTNode[10];

		return fakeMethod;
	}

	public void findBefore(
			char[] startWith,
			Scope scope,
			ClassScope classScope,
			int from,
			int recordTo,
			int parseTo,
			char[][] discouragedNames,
			UnresolvedReferenceNameRequestor nameRequestor) {
		MethodDeclaration fakeMethod =
			this.findBefore(startWith, scope, from, recordTo, parseTo, MAX_LINE_COUNT / 2, discouragedNames, nameRequestor);
		if (fakeMethod != null) fakeMethod.traverse(this, classScope);
	}

	private MethodDeclaration findBefore(
			char[] startWith,
			Scope s,
			int from,
			int recordTo,
			int parseTo,
			int maxLineCount,
			char[][] discouragedNames,
			UnresolvedReferenceNameRequestor nameRequestor) {
		this.requestor = nameRequestor;

		// reinitialize completion scanner to be usable as a normal scanner
		this.completionScanner.cursorLocation = 0;

		int minStart =
			this.completionScanner.getLineStart(
					Util.getLineNumber(recordTo, this.completionScanner.lineEnds, 0, this.completionScanner.linePtr) - maxLineCount);

		int start;
		int fakeBlocksCount;
		if (minStart <= from) {
			start = from;
			fakeBlocksCount = 0;
		} else {
			start = minStart;
			fakeBlocksCount = FAKE_BLOCKS_COUNT;
		}

		this.parser.startRecordingIdentifiers(start, recordTo);

		MethodDeclaration fakeMethod = this.parser.parseSomeStatements(
				start,
				parseTo,
				fakeBlocksCount,
				s.compilationUnitScope().referenceContext);

		this.parser.stopRecordingIdentifiers();

		if(!initPotentialNamesTables(discouragedNames)) return null;

		this.parentsPtr = -1;
		this.parents = new ASTNode[10];

		return fakeMethod;
	}

	private boolean initPotentialNamesTables(char[][] discouragedNames) {
		char[][] pvns = this.parser.potentialVariableNames;
		int[] pvnss = this.parser.potentialVariableNameStarts;
		int pvnsPtr = this.parser.potentialVariableNamesPtr;

		if (pvnsPtr < 0) return false; // there is no potential names

		// remove null and discouragedNames
		int discouragedNamesCount = discouragedNames == null ? 0 : discouragedNames.length;
		int j = -1;
		next : for (int i = 0; i <= pvnsPtr; i++) {
			char[] temp = pvns[i];

			if (temp == null) continue next;

			for (int k = 0; k < discouragedNamesCount; k++) {
				if (CharOperation.equals(temp, discouragedNames[k], false)) {
					continue next;
				}
			}

			pvns[i] = null;
			pvns[++j] = temp;
			pvnss[j] = pvnss[i];
		}
		pvnsPtr = j;

		if (pvnsPtr < 0) return false; // there is no potential names

		this.potentialVariableNames = pvns;
		this.potentialVariableNameStarts = pvnss;
		this.potentialVariableNamesPtr = pvnsPtr;

		return true;
	}

	private void popParent() {
		this.parentsPtr--;
	}
	private void pushParent(ASTNode parent) {
		int length = this.parents.length;
		if (this.parentsPtr >= length - 1) {
			System.arraycopy(this.parents, 0, this.parents = new ASTNode[length * 2], 0, length);
		}
		this.parents[++this.parentsPtr] = parent;
	}

	private ASTNode getEnclosingDeclaration() {
		int i = this.parentsPtr;
		while (i > -1) {
			ASTNode parent = this.parents[i];
			if (parent instanceof AbstractMethodDeclaration) {
				return parent;
			} else if (parent instanceof Initializer) {
				return parent;
			} else if (parent instanceof FieldDeclaration) {
				return parent;
			} else if (parent instanceof TypeDeclaration) {
				return parent;
			}
			i--;
		}
		return null;
	}

	public boolean visit(Block block, BlockScope blockScope) {
		ASTNode enclosingDeclaration = getEnclosingDeclaration();
		removeLocals(block.statements, enclosingDeclaration.sourceStart, block.sourceEnd);
		pushParent(block);
		return true;
	}

	public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope classScope) {
		if (((constructorDeclaration.bits & ASTNode.IsDefaultConstructor) == 0) && !constructorDeclaration.isClinit()) {
			removeLocals(
					constructorDeclaration.arguments,
					constructorDeclaration.declarationSourceStart,
					constructorDeclaration.declarationSourceEnd);
			removeLocals(
					constructorDeclaration.statements,
					constructorDeclaration.declarationSourceStart,
					constructorDeclaration.declarationSourceEnd);
		}
		pushParent(constructorDeclaration);
		return true;
	}

	public boolean visit(FieldDeclaration fieldDeclaration, MethodScope methodScope) {
		pushParent(fieldDeclaration);
		return true;
	}

	public boolean visit(Initializer initializer, MethodScope methodScope) {
		pushParent(initializer);
		return true;
	}

	public boolean visit(MethodDeclaration methodDeclaration, ClassScope classScope) {
		removeLocals(
				methodDeclaration.arguments,
				methodDeclaration.declarationSourceStart,
				methodDeclaration.declarationSourceEnd);
		removeLocals(
				methodDeclaration.statements,
				methodDeclaration.declarationSourceStart,
				methodDeclaration.declarationSourceEnd);
		pushParent(methodDeclaration);
		return true;
	}

	public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope blockScope) {
		removeFields(localTypeDeclaration);
		pushParent(localTypeDeclaration);
		return true;
	}

	public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) {
		removeFields(memberTypeDeclaration);
		pushParent(memberTypeDeclaration);
		return true;
	}

	public void endVisit(Block block, BlockScope blockScope) {
		popParent();
	}

	public void endVisit(Argument argument, BlockScope blockScope) {
		endVisitRemoved(argument.declarationSourceStart, argument.sourceEnd);
	}

	public void endVisit(Argument argument, ClassScope classScope) {
		endVisitRemoved(argument.declarationSourceStart, argument.sourceEnd);
	}

	public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope classScope) {
		if (((constructorDeclaration.bits & ASTNode.IsDefaultConstructor) == 0) && !constructorDeclaration.isClinit()) {
			endVisitPreserved(constructorDeclaration.bodyStart, constructorDeclaration.bodyEnd);
		}
		popParent();
	}

	public void endVisit(FieldDeclaration fieldDeclaration, MethodScope methodScope) {
		endVisitRemoved(fieldDeclaration.declarationSourceStart, fieldDeclaration.sourceEnd);
		endVisitPreserved(fieldDeclaration.sourceEnd, fieldDeclaration.declarationEnd);
		popParent();
	}

	public void endVisit(Initializer initializer, MethodScope methodScope) {
		endVisitPreserved(initializer.bodyStart, initializer.bodyEnd);
		popParent();
	}

	public void endVisit(LocalDeclaration localDeclaration, BlockScope blockScope) {
		endVisitRemoved(localDeclaration.declarationSourceStart, localDeclaration.sourceEnd);
	}

	public void endVisit(MethodDeclaration methodDeclaration, ClassScope classScope) {
		endVisitPreserved(
				methodDeclaration.bodyStart,
				methodDeclaration.bodyEnd);
		popParent();
	}

	public void endVisit(TypeDeclaration typeDeclaration, BlockScope blockScope) {
		endVisitRemoved(typeDeclaration.sourceStart, typeDeclaration.declarationSourceEnd);
		popParent();
	}

	public void endVisit(TypeDeclaration typeDeclaration, ClassScope classScope) {
		endVisitRemoved(typeDeclaration.sourceStart, typeDeclaration.declarationSourceEnd);
		popParent();
	}

	private int indexOfFisrtNameAfter(int position) {
		int left = 0;
		int right = this.potentialVariableNamesPtr;

		next : while (true) {
			if (right < left) return -1;

			int mid = left + (right - left) / 2;
			int midPosition = this.potentialVariableNameStarts[mid];
			if (midPosition < 0) {
				int nextMid = indexOfNextName(mid);
				if (nextMid < 0 || right < nextMid) { // no next index or next index is after 'right'
					right = mid - 1;
					continue next;
				}
				mid = nextMid;
				midPosition = this.potentialVariableNameStarts[nextMid];

				if (mid == right) { // mid and right are at the same index, we must move 'left'
					int leftPosition = this.potentialVariableNameStarts[left];
					if (leftPosition < 0 || leftPosition < position) { // 'left' is empty or 'left' is before the position
						int nextLeft = indexOfNextName(left);
						if (nextLeft < 0) return - 1;

						left = nextLeft;
						continue next;
					}

					return left;
				}
			}

			if (left != right) {
				if (midPosition < position) {
					left = mid + 1;
				} else {
					right = mid;
				}
			} else {
				if (midPosition < position) {
					return -1;
				}
				return mid;
			}
		}
	}

	private int indexOfNextName(int index) {
		int nextIndex = index + 1;
		while (nextIndex <= this.potentialVariableNamesPtr &&
				this.potentialVariableNames[nextIndex] == null) {
			int jumpIndex = -this.potentialVariableNameStarts[nextIndex];
			if (jumpIndex > 0) {
				nextIndex = jumpIndex;
			} else {
				nextIndex++;
			}
		}

		if (this.potentialVariableNamesPtr < nextIndex) {
			if  (index < this.potentialVariableNamesPtr) {
				this.potentialVariableNamesPtr = index;
			}
			return -1;
		}
		if (index + 1 < nextIndex) {
			this.potentialVariableNameStarts[index + 1] = -nextIndex;
		}
		return nextIndex;
	}

	private void removeNameAt(int index) {
		this.potentialVariableNames[index] = null;
		int nextIndex = indexOfNextName(index);
		if (nextIndex != -1) {
			this.potentialVariableNameStarts[index] = -nextIndex;
		} else {
			this.potentialVariableNamesPtr = index - 1;
		}
	}

	private void endVisitPreserved(int start, int end) {
		int i = indexOfFisrtNameAfter(start);
		done : while (i != -1) {
			int nameStart = this.potentialVariableNameStarts[i];
			if (start < nameStart && nameStart < end) {
				acceptName(this.potentialVariableNames[i]);
				removeNameAt(i);
			}

			if (end < nameStart) break done;
			i = indexOfNextName(i);
		}
	}

	private void endVisitRemoved(int start, int end) {
		int i = indexOfFisrtNameAfter(start);
		done : while (i != -1) {
			int nameStart = this.potentialVariableNameStarts[i];
			if (start < nameStart && nameStart < end) {
				removeNameAt(i);
			}

			if (end < nameStart) break done;
			i = indexOfNextName(i);
		}
	}

	private void removeLocals(Statement[] statements, int start, int end) {
		if (statements != null) {
			for (int i = 0; i < statements.length; i++) {
				if (statements[i] instanceof LocalDeclaration) {
					LocalDeclaration localDeclaration = (LocalDeclaration) statements[i];
					int j = indexOfFisrtNameAfter(start);
					done : while (j != -1) {
						int nameStart = this.potentialVariableNameStarts[j];
						if (start <= nameStart && nameStart <= end) {
							if (CharOperation.equals(this.potentialVariableNames[j], localDeclaration.name, false)) {
								removeNameAt(j);
							}
						}

						if (end < nameStart) break done;
						j = indexOfNextName(j);
					}
				}
			}

		}
	}

	private void removeFields(TypeDeclaration typeDeclaration) {
		int start = typeDeclaration.declarationSourceStart;
		int end = typeDeclaration.declarationSourceEnd;

		FieldDeclaration[] fieldDeclarations = typeDeclaration.fields;
		if (fieldDeclarations != null) {
			for (int i = 0; i < fieldDeclarations.length; i++) {
				int j = indexOfFisrtNameAfter(start);
				done : while (j != -1) {
					int nameStart = this.potentialVariableNameStarts[j];
					if (start <= nameStart && nameStart <= end) {
						if (CharOperation.equals(this.potentialVariableNames[j], fieldDeclarations[i].name, false)) {
							removeNameAt(j);
						}
					}

					if (end < nameStart) break done;
					j = indexOfNextName(j);
				}
			}
		}
	}
}
