/*******************************************************************************
 * Copyright (c) 2011, 2012 GK Software AG 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:
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - [quick fix] Add quick fixes for null annotations - https://bugs.eclipse.org/337977
 *     IBM Corporation - bug fixes
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.fix;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.swt.graphics.Image;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.ASTNode;
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.SimpleName;
import org.eclipse.jdt.core.dom.VariableDeclaration;

import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFix;
import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFix.CompilationUnitRewriteOperation;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;

import org.eclipse.jdt.ui.cleanup.ICleanUpFix;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.jdt.ui.text.java.correction.ICommandAccess;

import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.text.correction.ProblemLocation;
import org.eclipse.jdt.internal.ui.text.correction.proposals.FixCorrectionProposal;

/**
 * Quick Fixes for null-annotation related problems.
 */
public class NullQuickFixes {

	/** Small adaptation just to make available the 'compilationUnit' passed at instantiation time. */
	private static class MyCURewriteOperationsFix extends CompilationUnitRewriteOperationsFix {
		CompilationUnit cu;

		public MyCURewriteOperationsFix(String name, CompilationUnit compilationUnit, CompilationUnitRewriteOperation[] operations) {
			super(name, compilationUnit, operations);
			this.cu= compilationUnit;
		}
	}

	public static void addReturnAndArgumentTypeProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals) {
		CompilationUnit astRoot= context.getASTRoot();
		ASTNode selectedNode= problem.getCoveringNode(astRoot);

		if (isComplainingAboutArgument(selectedNode) || isComplainingAboutReturn(selectedNode))
			addNullAnnotationInSignatureProposal(context, problem, proposals, false);
	}

	public static void addNullAnnotationInSignatureProposal(IInvocationContext context, IProblemLocation problem, Collection<ICommandAccess> proposals, boolean modifyOverridden) {
		MyCURewriteOperationsFix fix= createNullAnnotationInSignatureFix(context.getASTRoot(), problem, modifyOverridden);

		if (fix != null) {
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
			Map<String, String> options= new Hashtable<String, String>();
			if (fix.cu != context.getASTRoot()) {
				// workaround: adjust the unit to operate on, depending on the findings of RewriteOperations.createAddAnnotationOperation(..)
				final CompilationUnit cu= fix.cu;
				final IInvocationContext originalContext= context;
				context= new IInvocationContext() {
					public int getSelectionOffset() {
						return originalContext.getSelectionOffset();
					}

					public int getSelectionLength() {
						return originalContext.getSelectionLength();
					}

					public ASTNode getCoveringNode() {
						return originalContext.getCoveringNode();
					}

					public ASTNode getCoveredNode() {
						return originalContext.getCoveredNode();
					}

					public ICompilationUnit getCompilationUnit() {
						return (ICompilationUnit) cu.getJavaElement();
					}

					public CompilationUnit getASTRoot() {
						return cu;
					}
				};
			}
			int relevance= modifyOverridden ? 9 : 10; //raise local change above change in overridden method
			FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new NullAnnotationsCleanUp(options, problem.getProblemId()), relevance, image, context);
			proposals.add(proposal);
		}
	}

	public static boolean isComplainingAboutArgument(ASTNode selectedNode) {
		if (!(selectedNode instanceof SimpleName))
			return false;
		SimpleName nameNode= (SimpleName) selectedNode;
		IBinding binding= nameNode.resolveBinding();
		if (binding.getKind() == IBinding.VARIABLE && ((IVariableBinding) binding).isParameter())
			return true;
		VariableDeclaration argDecl= (VariableDeclaration) ASTNodes.getParent(selectedNode, VariableDeclaration.class);
		if (argDecl != null)
			binding= argDecl.resolveBinding();
		if (binding.getKind() == IBinding.VARIABLE && ((IVariableBinding) binding).isParameter())
			return true;
		return false;
	}

	public static boolean isComplainingAboutReturn(ASTNode selectedNode) {
		return selectedNode.getParent().getNodeType() == ASTNode.RETURN_STATEMENT;
	}

	private static MyCURewriteOperationsFix createNullAnnotationInSignatureFix(CompilationUnit compilationUnit, IProblemLocation problem, boolean modifyOverridden) {
		String nullableAnnotationName= getNullableAnnotationName(compilationUnit.getJavaElement(), false);
		String nonNullAnnotationName= getNonNullAnnotationName(compilationUnit.getJavaElement(), false);
		String annotationToAdd= nullableAnnotationName;
		String annotationToRemove= nonNullAnnotationName;

		switch (problem.getProblemId()) {
			case IProblem.IllegalDefinitionToNonNullParameter:
			case IProblem.IllegalRedefinitionToNonNullParameter:
				// case ParameterLackingNullableAnnotation: // never proposed with modifyOverridden
				if (modifyOverridden) {
					annotationToAdd= nonNullAnnotationName;
					annotationToRemove= nullableAnnotationName;
				}
				break;
			case IProblem.ParameterLackingNonNullAnnotation:
			case IProblem.IllegalReturnNullityRedefinition:
				if (!modifyOverridden) {
					annotationToAdd= nonNullAnnotationName;
					annotationToRemove= nullableAnnotationName;
				}
				break;
			case IProblem.RequiredNonNullButProvidedNull:
			case IProblem.RequiredNonNullButProvidedPotentialNull:
			case IProblem.RequiredNonNullButProvidedUnknown:
				annotationToAdd= nonNullAnnotationName;
				break;
		// all others propose to add @Nullable
		}

		// when performing one change at a time we can actually modify another CU than the current one:
		NullRewriteOperations.SignatureAnnotationRewriteOperation operation= NullRewriteOperations.createAddAnnotationOperation(compilationUnit, problem, annotationToAdd, annotationToRemove, null,
				false/*thisUnitOnly*/, true/*allowRemove*/, modifyOverridden);
		if (operation == null)
			return null;

		return new MyCURewriteOperationsFix(operation.getMessage(), operation.getCompilationUnit(), // note that this uses the findings from createAddAnnotationOperation(..)
				new NullRewriteOperations.SignatureAnnotationRewriteOperation[] { operation });
	}

	// Entry for NullAnnotationsCleanup:
	public static ICleanUpFix createCleanUp(CompilationUnit compilationUnit, IProblemLocation[] locations, int problemID) {
		ICompilationUnit cu= (ICompilationUnit) compilationUnit.getJavaElement();
		if (!JavaModelUtil.is50OrHigher(cu.getJavaProject()))
			return null;

		List<CompilationUnitRewriteOperation> operations= new ArrayList<CompilationUnitRewriteOperation>();
		if (locations == null) {
			org.eclipse.jdt.core.compiler.IProblem[] problems= compilationUnit.getProblems();
			locations= new IProblemLocation[problems.length];
			for (int i= 0; i < problems.length; i++) {
				if (problems[i].getID() == problemID)
					locations[i]= new ProblemLocation(problems[i]);
			}
		}

		createAddNullAnnotationOperations(compilationUnit, locations, operations);
		if (operations.size() == 0)
			return null;
		CompilationUnitRewriteOperation[] operationsArray= operations.toArray(new CompilationUnitRewriteOperation[operations.size()]);
		return new MyCURewriteOperationsFix(NullFixMessages.QuickFixes_add_annotation_change_name, compilationUnit, operationsArray);
	}

	private static void createAddNullAnnotationOperations(CompilationUnit compilationUnit, IProblemLocation[] locations, List<CompilationUnitRewriteOperation> result) {
		String nullableAnnotationName= getNullableAnnotationName(compilationUnit.getJavaElement(), false);
		String nonNullAnnotationName= getNonNullAnnotationName(compilationUnit.getJavaElement(), false);
		Set<String> handledPositions= new HashSet<String>();
		for (int i= 0; i < locations.length; i++) {
			IProblemLocation problem= locations[i];
			if (problem == null)
				continue; // problem was filtered out by createCleanUp()
			String annotationToAdd= nullableAnnotationName;
			String annotationToRemove= nonNullAnnotationName;
			switch (problem.getProblemId()) {
				case IProblem.IllegalDefinitionToNonNullParameter:
				case IProblem.IllegalRedefinitionToNonNullParameter:
				case IProblem.ParameterLackingNonNullAnnotation:
				case IProblem.IllegalReturnNullityRedefinition:
					annotationToAdd= nonNullAnnotationName;
					annotationToRemove= nullableAnnotationName;
					break;
				case IProblem.RequiredNonNullButProvidedNull:
				case IProblem.RequiredNonNullButProvidedPotentialNull:
				case IProblem.RequiredNonNullButProvidedUnknown:
					annotationToAdd= nonNullAnnotationName;
					break;
			// all others propose to add @Nullable
			}
			// when performing multiple changes we can only modify the one CU that the CleanUp infrastructure provides to the operation.
			CompilationUnitRewriteOperation fix= NullRewriteOperations.createAddAnnotationOperation(compilationUnit, problem, annotationToAdd, annotationToRemove, handledPositions,
					true/*thisUnitOnly*/, false/*allowRemove*/, false/*modifyOverridden*/);
			if (fix != null)
				result.add(fix);
		}
	}

	private static boolean isMissingNullAnnotationProblem(int id) {
		return id == IProblem.RequiredNonNullButProvidedNull || id == IProblem.RequiredNonNullButProvidedPotentialNull || id == IProblem.IllegalReturnNullityRedefinition
				|| mayIndicateParameterNullcheck(id);
	}

	private static boolean mayIndicateParameterNullcheck(int problemId) {
		return problemId == IProblem.NonNullLocalVariableComparisonYieldsFalse || problemId == IProblem.RedundantNullCheckOnNonNullLocalVariable;
	}

	public static boolean hasExplicitNullAnnotation(ICompilationUnit compilationUnit, int offset) {
// FIXME(SH): check for existing annotations disabled due to lack of precision:
//		      should distinguish what is actually annotated (return? param? which?)
//		try {
//			IJavaElement problemElement = compilationUnit.getElementAt(offset);
//			if (problemElement.getElementType() == IJavaElement.METHOD) {
//				IMethod method = (IMethod) problemElement;
//				String nullable = getNullableAnnotationName(compilationUnit, true);
//				String nonnull = getNonNullAnnotationName(compilationUnit, true);
//				for (IAnnotation annotation : method.getAnnotations()) {
//					if (   annotation.getElementName().equals(nonnull)
//						|| annotation.getElementName().equals(nullable))
//						return true;
//				}
//			}
//		} catch (JavaModelException jme) {
//			/* nop */
//		}
		return false;
	}

	public static String getNullableAnnotationName(IJavaElement javaElement, boolean makeSimple) {
		String qualifiedName= javaElement.getJavaProject().getOption(JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME, true);
		int lastDot;
		if (makeSimple && qualifiedName != null && (lastDot= qualifiedName.lastIndexOf('.')) != -1)
			return qualifiedName.substring(lastDot + 1);
		return qualifiedName;
	}

	public static String getNonNullAnnotationName(IJavaElement javaElement, boolean makeSimple) {
		String qualifiedName= javaElement.getJavaProject().getOption(JavaCore.COMPILER_NONNULL_ANNOTATION_NAME, true);
		int lastDot;
		if (makeSimple && qualifiedName != null && (lastDot= qualifiedName.lastIndexOf('.')) != -1)
			return qualifiedName.substring(lastDot + 1);
		return qualifiedName;
	}
}
