/*******************************************************************************
 * 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.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.text.edits.TextEdit;

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.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.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
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.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.SourceRange;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.NodeFinder;
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;

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 fRanges;
			private Collection fProblemNodes;
			private String fKey;
	
			public NameNodeVisitor(TextEdit[] edits, TextChange change, String key) {
				Assert.isNotNull(edits);
				Assert.isNotNull(key);
				
				fRanges= new HashSet(Arrays.asList(RefactoringAnalyzeUtil.getNewRanges(edits, change)));
				fProblemNodes= new ArrayList(0);
				fKey= key;
			}
	
			public SimpleName[] getProblemNodes() {
				return (SimpleName[]) fProblemNodes.toArray(new SimpleName[fProblemNodes.size()]);
			}
	
			//----- visit methods 
	
			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, 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 cuToNewResults= new HashMap(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= (SearchMatch[]) 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 iter= cuToNewResults.entrySet().iterator(); iter.hasNext();) {
			Map.Entry entry= (Entry) iter.next();
			ICompilationUnit cu= (ICompilationUnit) entry.getKey();
			SearchMatch[] newSearchMatches= (SearchMatch[]) 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 updatedOldOffsets= getUpdatedChangeOffsets(change, oldMatches);
		for (int i= 0; i < newMatches.length; i++) {
			SearchMatch newMatch= newMatches[i];
			Integer offsetInNew= new Integer(newMatch.getOffset());
			SearchMatch oldMatch= (SearchMatch) updatedOldOffsets.remove(offsetInNew);
			if (oldMatch == null) {
				addReferenceShadowedError(cu, newMatch, newElementName, result);
			}
		}
		for (Iterator iter= updatedOldOffsets.values().iterator(); iter.hasNext();) {
			// remaining old matches are not found any more -> they have been shadowed
			SearchMatch oldMatch= (SearchMatch) iter.next();
			addShadowsError(cu, oldMatch, result);
		}
	}
	
	/** @return Map &lt;Integer updatedOffset, SearchMatch oldMatch&gt; */
	private static Map getUpdatedChangeOffsets(TextChange change, SearchMatch[] oldMatches) {
		Map/*<Integer updatedOffset, SearchMatch oldMatch>*/ updatedOffsets= new HashMap();
		Map oldToUpdatedOffsets= getEditChangeOffsetUpdates(change);
		for (int i= 0; i < oldMatches.length; i++) {
			SearchMatch oldMatch= oldMatches[i];
			Integer updatedOffset= (Integer) oldToUpdatedOffsets.get(new Integer(oldMatch.getOffset()));
			if (updatedOffset == null)
				updatedOffset= new Integer(-1); //match not updated
			updatedOffsets.put(updatedOffset, oldMatch);
		}
		return updatedOffsets;
	}

	/** @return Map &lt;Integer oldOffset, Integer updatedOffset&gt; */
	private static Map getEditChangeOffsetUpdates(TextChange change) {
		TextEditChangeGroup[] editChanges= change.getTextEditChangeGroups();
		Map/*<oldOffset, newOffset>*/ offsetUpdates= new HashMap(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[] {cu.getElementName(), 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, cu.getElementName()); 
		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 statementsRecovery whether statements 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 statementsRecovery) throws CoreException {

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

		String newCuSource= cuChange.getPreviewContent(new NullProgressMonitor());
		CompilationUnit newCUNode= new RefactoringASTParser(AST.JLS3).parse(newCuSource, compilationUnit, true, statementsRecovery, 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, new SourceRange(problem))));
		}
		return result;
	}
}
