/*******************************************************************************
 * Copyright (c) 2000, 2011 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.rename;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;

import org.eclipse.core.resources.IResource;

import org.eclipse.text.edits.TextEdit;

import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;

import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.TextEditChangeGroup;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.SourceRange;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.search.FieldDeclarationMatch;
import org.eclipse.jdt.core.search.MethodDeclarationMatch;
import org.eclipse.jdt.core.search.SearchMatch;

import org.eclipse.jdt.internal.corext.SourceRangeFactory;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.internal.corext.util.SearchUtils;

import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;

class RenameAnalyzeUtil {

	private static class ProblemNodeFinder {

		private ProblemNodeFinder() {
			//static
		}

		public static SimpleName[] getProblemNodes(ASTNode methodNode, VariableDeclaration variableNode, TextEdit[] edits, TextChange change) {
			String key= variableNode.resolveBinding().getKey();
			NameNodeVisitor visitor= new NameNodeVisitor(edits, change, key);
			methodNode.accept(visitor);
			return visitor.getProblemNodes();
		}

		private static class NameNodeVisitor extends ASTVisitor {

			private Collection<IRegion> fRanges;
			private Collection<SimpleName> fProblemNodes;
			private String fKey;

			public NameNodeVisitor(TextEdit[] edits, TextChange change, String key) {
				Assert.isNotNull(edits);
				Assert.isNotNull(key);

				fRanges= new HashSet<IRegion>(Arrays.asList(RefactoringAnalyzeUtil.getNewRanges(edits, change)));
				fProblemNodes= new ArrayList<SimpleName>(0);
				fKey= key;
			}

			public SimpleName[] getProblemNodes() {
				return fProblemNodes.toArray(new SimpleName[fProblemNodes.size()]);
			}

			//----- visit methods

			@Override
			public boolean visit(SimpleName node) {
				VariableDeclaration decl= getVariableDeclaration(node);
				if (decl == null)
					return super.visit(node);

				IVariableBinding binding= decl.resolveBinding();
				if (binding == null)
					return super.visit(node);

				boolean keysEqual= fKey.equals(binding.getKey());
				boolean rangeInSet= fRanges.contains(new Region(node.getStartPosition(), node.getLength()));

				if (keysEqual && !rangeInSet)
					fProblemNodes.add(node);

				if (!keysEqual && rangeInSet)
					fProblemNodes.add(node);

				/*
				 * if (!keyEquals && !rangeInSet)
				 * 		ok, different local variable.
				 *
				 * if (keyEquals && rangeInSet)
				 * 		ok, renamed local variable & has been renamed.
				 */

				return super.visit(node);
			}
		}
	}

	static class LocalAnalyzePackage {
		public final TextEdit fDeclarationEdit;
		public final TextEdit[] fOccurenceEdits;

		public LocalAnalyzePackage(final TextEdit declarationEdit, final TextEdit[] occurenceEdits) {
			fDeclarationEdit = declarationEdit;
			fOccurenceEdits = occurenceEdits;
		}
	}

	private RenameAnalyzeUtil() {
		//no instance
	}

	static RefactoringStatus analyzeRenameChanges(TextChangeManager manager,  SearchResultGroup[] oldOccurrences, SearchResultGroup[] newOccurrences) {
		RefactoringStatus result= new RefactoringStatus();
		for (int i= 0; i < oldOccurrences.length; i++) {
			SearchResultGroup oldGroup= oldOccurrences[i];
			SearchMatch[] oldSearchResults= oldGroup.getSearchResults();
			ICompilationUnit cunit= oldGroup.getCompilationUnit();
			if (cunit == null)
				continue;
			for (int j= 0; j < oldSearchResults.length; j++) {
				SearchMatch oldSearchResult= oldSearchResults[j];
				if (! RenameAnalyzeUtil.existsInNewOccurrences(oldSearchResult, newOccurrences, manager)){
					addShadowsError(cunit, oldSearchResult, result);
				}
			}
		}
		return result;
	}

	static ICompilationUnit findWorkingCopyForCu(ICompilationUnit[] newWorkingCopies, ICompilationUnit cu){
		ICompilationUnit original= cu == null ? null : cu.getPrimary();
		for (int i= 0; i < newWorkingCopies.length; i++) {
			if (newWorkingCopies[i].getPrimary().equals(original))
				return newWorkingCopies[i];
		}
		return null;
	}

	static ICompilationUnit[] createNewWorkingCopies(ICompilationUnit[] compilationUnitsToModify, TextChangeManager manager, WorkingCopyOwner owner, SubProgressMonitor pm) throws CoreException {
		pm.beginTask("", compilationUnitsToModify.length); //$NON-NLS-1$
		ICompilationUnit[] newWorkingCopies= new ICompilationUnit[compilationUnitsToModify.length];
		for (int i= 0; i < compilationUnitsToModify.length; i++) {
			ICompilationUnit cu= compilationUnitsToModify[i];
			newWorkingCopies[i]= createNewWorkingCopy(cu, manager, owner, new SubProgressMonitor(pm, 1));
		}
		pm.done();
		return newWorkingCopies;
	}

	static ICompilationUnit createNewWorkingCopy(ICompilationUnit cu, TextChangeManager manager,
			WorkingCopyOwner owner, SubProgressMonitor pm) throws CoreException {
		ICompilationUnit newWc= cu.getWorkingCopy(owner, null);
		String previewContent= manager.get(cu).getPreviewContent(new NullProgressMonitor());
		newWc.getBuffer().setContents(previewContent);
		newWc.reconcile(ICompilationUnit.NO_AST, false, owner, pm);
		return newWc;
	}

	private static boolean existsInNewOccurrences(SearchMatch searchResult, SearchResultGroup[] newOccurrences, TextChangeManager manager) {
		SearchResultGroup newGroup= findOccurrenceGroup(searchResult.getResource(), newOccurrences);
		if (newGroup == null)
			return false;

		IRegion oldEditRange= getCorrespondingEditChangeRange(searchResult, manager);
		if (oldEditRange == null)
			return false;

		SearchMatch[] newSearchResults= newGroup.getSearchResults();
		int oldRangeOffset = oldEditRange.getOffset();
		for (int i= 0; i < newSearchResults.length; i++) {
			if (newSearchResults[i].getOffset() == oldRangeOffset)
				return true;
		}
		return false;
	}

	private static IRegion getCorrespondingEditChangeRange(SearchMatch searchResult, TextChangeManager manager) {
		TextChange change= getTextChange(searchResult, manager);
		if (change == null)
			return null;

		IRegion oldMatchRange= createTextRange(searchResult);
		TextEditChangeGroup[] editChanges= change.getTextEditChangeGroups();
		for (int i= 0; i < editChanges.length; i++) {
			if (oldMatchRange.equals(editChanges[i].getRegion()))
				return TextEdit.getCoverage(change.getPreviewEdits(editChanges[i].getTextEdits()));
		}
		return null;
	}

	private static TextChange getTextChange(SearchMatch searchResult, TextChangeManager manager) {
		ICompilationUnit cu= SearchUtils.getCompilationUnit(searchResult);
		if (cu == null)
			return null;
		return manager.get(cu);
	}

	private static IRegion createTextRange(SearchMatch searchResult) {
		return new Region(searchResult.getOffset(), searchResult.getLength());
	}

	private static SearchResultGroup findOccurrenceGroup(IResource resource, SearchResultGroup[] newOccurrences) {
		for (int i= 0; i < newOccurrences.length; i++) {
			if (newOccurrences[i].getResource().equals(resource))
				return newOccurrences[i];
		}
		return null;
	}

//--- find missing changes in BOTH directions

	//TODO: Currently filters out declarations (MethodDeclarationMatch, FieldDeclarationMatch).
	//Long term solution: only pass reference search results in.
	static RefactoringStatus analyzeRenameChanges2(TextChangeManager manager,
			SearchResultGroup[] oldReferences, SearchResultGroup[] newReferences, String newElementName) {
		RefactoringStatus result= new RefactoringStatus();

		HashMap<ICompilationUnit, SearchMatch[]> cuToNewResults= new HashMap<ICompilationUnit, SearchMatch[]>(newReferences.length);
		for (int i1= 0; i1 < newReferences.length; i1++) {
			ICompilationUnit cu= newReferences[i1].getCompilationUnit();
			if (cu != null)
				cuToNewResults.put(cu.getPrimary(), newReferences[i1].getSearchResults());
		}

		for (int i= 0; i < oldReferences.length; i++) {
			SearchResultGroup oldGroup= oldReferences[i];
			SearchMatch[] oldMatches= oldGroup.getSearchResults();
			ICompilationUnit cu= oldGroup.getCompilationUnit();
			if (cu == null)
				continue;

			SearchMatch[] newSearchMatches= cuToNewResults.remove(cu);
			if (newSearchMatches == null) {
				for (int j = 0; j < oldMatches.length; j++) {
					SearchMatch oldMatch = oldMatches[j];
					addShadowsError(cu, oldMatch, result);
				}
			} else {
				analyzeChanges(cu, manager.get(cu), oldMatches, newSearchMatches, newElementName, result);
			}
		}

		for (Iterator<Entry<ICompilationUnit, SearchMatch[]>> iter= cuToNewResults.entrySet().iterator(); iter.hasNext();) {
			Entry<ICompilationUnit, SearchMatch[]> entry= iter.next();
			ICompilationUnit cu= entry.getKey();
			SearchMatch[] newSearchMatches= entry.getValue();
			for (int i= 0; i < newSearchMatches.length; i++) {
				SearchMatch newMatch= newSearchMatches[i];
				addReferenceShadowedError(cu, newMatch, newElementName, result);
			}
		}
		return result;
	}

	private static void analyzeChanges(ICompilationUnit cu, TextChange change,
			SearchMatch[] oldMatches, SearchMatch[] newMatches, String newElementName, RefactoringStatus result) {
		Map<Integer, SearchMatch> updatedOldOffsets= getUpdatedChangeOffsets(change, oldMatches);
		for (int i= 0; i < newMatches.length; i++) {
			SearchMatch newMatch= newMatches[i];
			Integer offsetInNew= new Integer(newMatch.getOffset());
			SearchMatch oldMatch= updatedOldOffsets.remove(offsetInNew);
			if (oldMatch == null) {
				addReferenceShadowedError(cu, newMatch, newElementName, result);
			}
		}
		for (Iterator<SearchMatch> iter= updatedOldOffsets.values().iterator(); iter.hasNext();) {
			// remaining old matches are not found any more -> they have been shadowed
			SearchMatch oldMatch= iter.next();
			addShadowsError(cu, oldMatch, result);
		}
	}

	/**
	 *
	 * @param change
	 * @param oldMatches
	 * @return Map &lt;Integer updatedOffset, SearchMatch oldMatch&gt;
	 */
	private static Map<Integer, SearchMatch> getUpdatedChangeOffsets(TextChange change, SearchMatch[] oldMatches) {
		Map<Integer, SearchMatch> updatedOffsets= new HashMap<Integer, SearchMatch>();
		Map<Integer, Integer> oldToUpdatedOffsets= getEditChangeOffsetUpdates(change);
		for (int i= 0; i < oldMatches.length; i++) {
			SearchMatch oldMatch= oldMatches[i];
			Integer updatedOffset= oldToUpdatedOffsets.get(new Integer(oldMatch.getOffset()));
			if (updatedOffset == null)
				updatedOffset= new Integer(-1); //match not updated
			updatedOffsets.put(updatedOffset, oldMatch);
		}
		return updatedOffsets;
	}

	/**
	 *
	 * @param change
	 * @return Map &lt;Integer oldOffset, Integer updatedOffset&gt;
	 */
	private static Map<Integer, Integer> getEditChangeOffsetUpdates(TextChange change) {
		TextEditChangeGroup[] editChanges= change.getTextEditChangeGroups();
		Map<Integer, Integer> offsetUpdates= new HashMap<Integer, Integer>(editChanges.length);
		for (int i= 0; i < editChanges.length; i++) {
			TextEditChangeGroup editChange= editChanges[i];
			IRegion oldRegion= editChange.getRegion();
			if (oldRegion == null)
				continue;
			IRegion updatedRegion= TextEdit.getCoverage(change.getPreviewEdits(editChange.getTextEdits()));
			if (updatedRegion == null)
				continue;

			offsetUpdates.put(new Integer(oldRegion.getOffset()), new Integer(updatedRegion.getOffset()));
		}
		return offsetUpdates;
	}

	private static void addReferenceShadowedError(ICompilationUnit cu, SearchMatch newMatch, String newElementName, RefactoringStatus result) {
		//Found a new match with no corresponding old match.
		//-> The new match is a reference which was pointing to another element,
		//but that other element has been shadowed

		//TODO: should not have to filter declarations:
		if (newMatch instanceof MethodDeclarationMatch || newMatch instanceof FieldDeclarationMatch)
			return;
		ISourceRange range= getOldSourceRange(newMatch);
		RefactoringStatusContext context= JavaStatusContext.create(cu, range);
		String message= Messages.format(
				RefactoringCoreMessages.RenameAnalyzeUtil_reference_shadowed,
				new String[] {BasicElementLabels.getFileName(cu), BasicElementLabels.getJavaElementName(newElementName)});
		result.addError(message, context);
	}

	private static ISourceRange getOldSourceRange(SearchMatch newMatch) {
		// cannot transfom offset in preview to offset in original -> just show enclosing method
		IJavaElement newMatchElement= (IJavaElement) newMatch.getElement();
		IJavaElement primaryElement= newMatchElement.getPrimaryElement();
		ISourceRange range= null;
		if (primaryElement.exists() && primaryElement instanceof ISourceReference) {
			try {
				range= ((ISourceReference) primaryElement).getSourceRange();
			} catch (JavaModelException e) {
				// can live without source range
			}
		}
		return range;
	}

	private static void addShadowsError(ICompilationUnit cu, SearchMatch oldMatch, RefactoringStatus result) {
		// Old match not found in new matches -> reference has been shadowed

		//TODO: should not have to filter declarations:
		if (oldMatch instanceof MethodDeclarationMatch || oldMatch instanceof FieldDeclarationMatch)
			return;
		ISourceRange range= new SourceRange(oldMatch.getOffset(), oldMatch.getLength());
		RefactoringStatusContext context= JavaStatusContext.create(cu, range);
		String message= Messages.format(RefactoringCoreMessages.RenameAnalyzeUtil_shadows, BasicElementLabels.getFileName(cu));
		result.addError(message, context);
	}

	/**
	 * This method analyzes a set of local variable renames inside one cu. It checks whether
	 * any new compile errors have been introduced by the rename(s) and whether the correct
	 * node(s) has/have been renamed.
	 *
	 * @param analyzePackages the LocalAnalyzePackages containing the information about the local renames
	 * @param cuChange the TextChange containing all local variable changes to be applied.
	 * @param oldCUNode the fully (incl. bindings) resolved AST node of the original compilation unit
	 * @param recovery whether statements and bindings recovery should be performed when parsing the changed CU
	 * @return a RefactoringStatus containing errors if compile errors or wrongly renamed nodes are found
	 * @throws CoreException thrown if there was an error greating the preview content of the change
	 */
	public static RefactoringStatus analyzeLocalRenames(LocalAnalyzePackage[] analyzePackages, TextChange cuChange, CompilationUnit oldCUNode, boolean recovery) throws CoreException {

		RefactoringStatus result= new RefactoringStatus();
		ICompilationUnit compilationUnit= (ICompilationUnit) oldCUNode.getJavaElement();

		String newCuSource= cuChange.getPreviewContent(new NullProgressMonitor());
		CompilationUnit newCUNode= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(newCuSource, compilationUnit, true, recovery, null);

		result.merge(analyzeCompileErrors(newCuSource, newCUNode, oldCUNode));
		if (result.hasError())
			return result;

		for (int i= 0; i < analyzePackages.length; i++) {
			ASTNode enclosing= getEnclosingBlockOrMethod(analyzePackages[i].fDeclarationEdit, cuChange, newCUNode);

			// get new declaration
			IRegion newRegion= RefactoringAnalyzeUtil.getNewTextRange(analyzePackages[i].fDeclarationEdit, cuChange);
			ASTNode newDeclaration= NodeFinder.perform(newCUNode, newRegion.getOffset(), newRegion.getLength());
			Assert.isTrue(newDeclaration instanceof Name);

			VariableDeclaration declaration= getVariableDeclaration((Name) newDeclaration);
			Assert.isNotNull(declaration);

			SimpleName[] problemNodes= ProblemNodeFinder.getProblemNodes(enclosing, declaration, analyzePackages[i].fOccurenceEdits, cuChange);
			result.merge(RefactoringAnalyzeUtil.reportProblemNodes(newCuSource, problemNodes));
		}
		return result;
	}

	private static VariableDeclaration getVariableDeclaration(Name node) {
		IBinding binding= node.resolveBinding();
		if (binding == null && node.getParent() instanceof VariableDeclaration)
			return (VariableDeclaration) node.getParent();

		if (binding != null && binding.getKind() == IBinding.VARIABLE) {
			CompilationUnit cu= (CompilationUnit) ASTNodes.getParent(node, CompilationUnit.class);
			return ASTNodes.findVariableDeclaration( ((IVariableBinding) binding), cu);
		}
		return null;
	}

	private static ASTNode getEnclosingBlockOrMethod(TextEdit declarationEdit, TextChange change, CompilationUnit newCUNode) {
		ASTNode enclosing= RefactoringAnalyzeUtil.getBlock(declarationEdit, change, newCUNode);
		if (enclosing == null)
			enclosing= RefactoringAnalyzeUtil.getMethodDeclaration(declarationEdit, change, newCUNode);
		return enclosing;
	}

	private static RefactoringStatus analyzeCompileErrors(String newCuSource, CompilationUnit newCUNode, CompilationUnit oldCUNode) {
		RefactoringStatus result= new RefactoringStatus();
		IProblem[] newProblems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, oldCUNode);
		for (int i= 0; i < newProblems.length; i++) {
			IProblem problem= newProblems[i];
			if (problem.isError())
				result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource,
						SourceRangeFactory.create(problem))));
		}
		return result;
	}
}
