/*******************************************************************************
 * Copyright (c) 2011, 2017 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 - [quick fix] Add quick fixes for null annotations - https://bugs.eclipse.org/337977
 *     IBM Corporation - bug fixes
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.fix;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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.MethodDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.VariableDeclaration;

import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.fix.NullAnnotationsRewriteOperations.Builder;
import org.eclipse.jdt.internal.corext.fix.NullAnnotationsRewriteOperations.ChangeKind;
import org.eclipse.jdt.internal.corext.fix.NullAnnotationsRewriteOperations.RemoveRedundantAnnotationRewriteOperation;
import org.eclipse.jdt.internal.corext.fix.NullAnnotationsRewriteOperations.SignatureAnnotationRewriteOperation;
import org.eclipse.jdt.internal.corext.fix.TypeAnnotationRewriteOperations.MoveTypeAnnotationRewriteOperation;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;

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

import org.eclipse.jdt.internal.ui.text.correction.ProblemLocation;
import org.eclipse.jdt.internal.ui.text.correction.TypeAnnotationSubProcessor;

public class NullAnnotationsFix extends CompilationUnitRewriteOperationsFix {

	private CompilationUnit cu;

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

	public CompilationUnit getCu() {
		return cu;
	}

	/* recognizes any simple name referring to a parameter binding */
	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;
	}

	/* recognizes the expression of a return statement and the return type of a method declaration. */
	public static boolean isComplainingAboutReturn(ASTNode selectedNode) {
		if (selectedNode.getParent().getNodeType() == ASTNode.RETURN_STATEMENT)
			return true;
		while (!(selectedNode instanceof Type)) {
			if (selectedNode == null) return false;
			selectedNode= selectedNode.getParent();
		}
		return selectedNode.getLocationInParent() == MethodDeclaration.RETURN_TYPE2_PROPERTY;
	}

	public static NullAnnotationsFix createNullAnnotationInSignatureFix(CompilationUnit compilationUnit, IProblemLocation problem,
			ChangeKind changeKind, boolean isArgumentProblem) {
		IJavaElement javaElement= compilationUnit.getJavaElement();
		String nullableAnnotationName= getNullableAnnotationName(javaElement, false);
		String nonNullAnnotationName= getNonNullAnnotationName(javaElement, false);
		Builder builder= new Builder(problem, compilationUnit, nullableAnnotationName, nonNullAnnotationName,
										/*allowRemove*/true, isArgumentProblem, changeKind);
		boolean addNonNull= false;

		switch (problem.getProblemId()) {
			case IProblem.IllegalDefinitionToNonNullParameter:
			case IProblem.IllegalRedefinitionToNonNullParameter:
				// case ParameterLackingNullableAnnotation: // never proposed with modifyOverridden
				if (changeKind == ChangeKind.OVERRIDDEN) {
					addNonNull= true;
					builder.swapAnnotations();
				}
				break;
			case IProblem.ParameterLackingNonNullAnnotation:
			case IProblem.IllegalReturnNullityRedefinition:
				if (changeKind != ChangeKind.OVERRIDDEN) {
					addNonNull= true;
					builder.swapAnnotations();
				}
				break;
			case IProblem.RequiredNonNullButProvidedNull:
			case IProblem.RequiredNonNullButProvidedPotentialNull:
			case IProblem.RequiredNonNullButProvidedUnknown:
			case IProblem.RequiredNonNullButProvidedSpecdNullable:
				if (isArgumentProblem == (changeKind != ChangeKind.TARGET)) {
					addNonNull= true;
					builder.swapAnnotations();
				}
				break;
			case IProblem.ConflictingNullAnnotations:
				if (isArgumentProblem && changeKind == ChangeKind.INVERSE) {
					return null; // cannot redefine @Nullable param to @NonNull
				}
				//$FALL-THROUGH$
			case IProblem.ConflictingInheritedNullAnnotations:
				if (changeKind == ChangeKind.INVERSE || changeKind == ChangeKind.OVERRIDDEN) {
					addNonNull= true;
					builder.swapAnnotations();
				}
				break;
			default:
				// all others propose to add @Nullable
		}

		// when performing one change at a time we can actually modify another CU than the current one:
		NullAnnotationsRewriteOperations.SignatureAnnotationRewriteOperation operation= builder.createAddAnnotationOperation(null, false/*thisUnitOnly*/, changeKind);
		if (operation == null)
			return null;

		if (addNonNull) {
			operation.fRemoveIfNonNullByDefault= true;
			operation.fNonNullByDefaultName= getNonNullByDefaultAnnotationName(javaElement, false);
		}
		return new NullAnnotationsFix(operation.getMessage(), operation.getCompilationUnit(), // note that this uses the findings from createAddAnnotationOperation(..)
				new NullAnnotationsRewriteOperations.SignatureAnnotationRewriteOperation[] { operation });
	}

	public static NullAnnotationsFix createRemoveRedundantNullAnnotationsFix(CompilationUnit compilationUnit, IProblemLocation problem) {
		RemoveRedundantAnnotationRewriteOperation operation= new RemoveRedundantAnnotationRewriteOperation(compilationUnit, problem);
		return new NullAnnotationsFix(FixMessages.NullAnnotationsRewriteOperations_remove_redundant_nullness_annotation, compilationUnit, new RemoveRedundantAnnotationRewriteOperation[] { 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<>();
		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]);
			}
		}
		String message;
		if (TypeAnnotationSubProcessor.hasFixFor(problemID)) {
			boolean isMove= createMoveTypeAnnotationOperations(compilationUnit, locations, operations);
			message= isMove ? FixMessages.TypeAnnotationFix_move : FixMessages.TypeAnnotationFix_remove;
		} else {
			createAddNullAnnotationOperations(compilationUnit, locations, operations);
			createRemoveRedundantNullAnnotationsOperations(compilationUnit, locations, operations);
			message= FixMessages.NullAnnotationsFix_add_annotation_change_name;
		}
		if (operations.size() == 0)
			return null;
		CompilationUnitRewriteOperation[] operationsArray= operations.toArray(new CompilationUnitRewriteOperation[operations.size()]);
		return new NullAnnotationsFix(message, compilationUnit, operationsArray);
	}

	private static boolean createMoveTypeAnnotationOperations(CompilationUnit compilationUnit, IProblemLocation[] locations, List<CompilationUnitRewriteOperation> operations) {
		boolean isMove= false;
		for (IProblemLocation location: locations) {
			if (location == null)
				continue;
			MoveTypeAnnotationRewriteOperation operation= new MoveTypeAnnotationRewriteOperation(compilationUnit, location);
			operations.add(operation);
			isMove|= operation.isMove();
		}
		return isMove;
	}

	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<>();
		for (int i= 0; i < locations.length; i++) {
			IProblemLocation problem= locations[i];
			if (problem == null)
				continue; // problem was filtered out by createCleanUp()
			boolean isArgumentProblem= isComplainingAboutArgument(problem.getCoveredNode(compilationUnit));
			Builder builder= new Builder(problem, compilationUnit, nullableAnnotationName, nonNullAnnotationName,
											/*allowRemove*/false, isArgumentProblem, ChangeKind.LOCAL);
			boolean addNonNull= false;
			// cf. createNullAnnotationInSignatureFix() but changeKind is constantly LOCAL
			switch (problem.getProblemId()) {
				case IProblem.IllegalDefinitionToNonNullParameter:
				case IProblem.IllegalRedefinitionToNonNullParameter:
					break;
				case IProblem.ParameterLackingNonNullAnnotation:
				case IProblem.IllegalReturnNullityRedefinition:
					addNonNull= true;
					builder.swapAnnotations();
					break;
				case IProblem.RequiredNonNullButProvidedNull:
				case IProblem.RequiredNonNullButProvidedPotentialNull:
				case IProblem.RequiredNonNullButProvidedUnknown:
				case IProblem.RequiredNonNullButProvidedSpecdNullable:
					if (isArgumentProblem) {
						addNonNull= true;
						builder.swapAnnotations();
					}
					break;
				default:
					// 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.
			SignatureAnnotationRewriteOperation fix= builder.createAddAnnotationOperation(handledPositions, true/*thisUnitOnly*/, ChangeKind.LOCAL);
			if (fix != null) {
				if (addNonNull) {
					fix.fRemoveIfNonNullByDefault= true;
					fix.fNonNullByDefaultName= getNonNullByDefaultAnnotationName(compilationUnit.getJavaElement(), false);
				}
				result.add(fix);
			}
		}
	}

	private static void createRemoveRedundantNullAnnotationsOperations(CompilationUnit compilationUnit, IProblemLocation[] locations, List<CompilationUnitRewriteOperation> result) {
		for (int i= 0; i < locations.length; i++) {
			IProblemLocation problem= locations[i];
			if (problem == null)
				continue; // problem was filtered out by createCleanUp()

			int problemId= problem.getProblemId();
			if (problemId == IProblem.RedundantNullAnnotation || problemId == IProblem.RedundantNullDefaultAnnotationPackage || problemId == IProblem.RedundantNullDefaultAnnotationType
					|| problemId == IProblem.RedundantNullDefaultAnnotationMethod) {
				RemoveRedundantAnnotationRewriteOperation operation= new RemoveRedundantAnnotationRewriteOperation(compilationUnit, problem);
				result.add(operation);
			}
		}
	}

//	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;
//	}

	/**
	 * Tells whether an explicit null annotation exists on the given compilation unit.
	 *
	 * @param compilationUnit the compilation unit
	 * @param offset the offset
	 * @return <code>true</code> if the compilation unit has an explicit null annotation
	 */
	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) {
		return getAnnotationName(javaElement, makeSimple, JavaCore.COMPILER_NULLABLE_ANNOTATION_NAME);
	}

	public static String getNonNullAnnotationName(IJavaElement javaElement, boolean makeSimple) {
		return getAnnotationName(javaElement, makeSimple, JavaCore.COMPILER_NONNULL_ANNOTATION_NAME);
	}

	public static String getNonNullByDefaultAnnotationName(IJavaElement javaElement, boolean makeSimple) {
		return getAnnotationName(javaElement, makeSimple, JavaCore.COMPILER_NONNULL_BY_DEFAULT_ANNOTATION_NAME);
	}

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