/*******************************************************************************
 * Copyright (c) 2000, 2018 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
 *     Nikolay Metchev <nikolaymetchev@gmail.com> - Import static (Ctrl+Shift+M) creates imports for private methods - https://bugs.eclipse.org/409594
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.codemanipulation;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;

import org.eclipse.core.resources.IWorkspaceRunnable;

import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NameQualifiedType;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.core.manipulation.TypeKinds;
import org.eclipse.jdt.core.manipulation.TypeNameMatchCollector;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameMatch;

import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.util.JavaConventionsUtil;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.SharedASTProvider;

import org.eclipse.jdt.internal.ui.JavaUIStatus;


/**
 * Add imports to a compilation unit.
 * The input is an array of full qualified type names. No elimination of unnecessary
 * imports is done (use ImportStructure for this). Duplicates are not added.
 * If the compilation unit is open in an editor, be sure to pass over its working copy.
 */
public class AddImportsOperation implements IWorkspaceRunnable {

	public static interface IChooseImportQuery {
		/**
		 * Selects an import from a list of choices.
		 * @param openChoices Array of found types
		 * @param containerName Name type to be imported
		 * @return Returns <code>null</code> to cancel the operation, or the
		 *         selected imports.
		 */
		TypeNameMatch chooseImport(TypeNameMatch[] openChoices, String containerName);
	}

	private ICompilationUnit fCompilationUnit;
	private final int fSelectionOffset;
	private final int fSelectionLength;
	private final IChooseImportQuery fQuery;
	private IStatus fStatus;
	private boolean fDoSave;
	private final boolean fApply;
	private MultiTextEdit fResultingEdit;

	/**
	 * Generate import statements for the passed java elements
	 * Elements must be of type IType (-> single import) or IPackageFragment
	 * (on-demand-import). Other JavaElements are ignored
	 * @param cu The compilation unit
	 * @param selectionOffset Start of the current text selection
	 * 	@param selectionLength End of the current text selection
	 * @param query Query element to be used for UI interaction or <code>null</code> to not select anything
	 * when multiple possibilities are available
	 * @param save If set, the result will be saved
	 */
	public AddImportsOperation(ICompilationUnit cu, int selectionOffset, int selectionLength, IChooseImportQuery query, boolean save) {
		this(cu, selectionOffset, selectionLength, query, save, true);
	}

	/**
	 * Generate import statements for the passed java elements
	 * Elements must be of type IType (-> single import) or IPackageFragment
	 * (on-demand-import). Other JavaElements are ignored
	 * @param cu The compilation unit
	 * @param selectionOffset Start of the current text selection
	 * 	@param selectionLength End of the current text selection
	 * @param query Query element to be used for UI interaction or <code>null</code> to not select anything
	 * when multiple possibilities are available
	 * @param save If set, the result will be saved
	 * @param apply If set, the resulting edit will be applied
	 */
	public AddImportsOperation(ICompilationUnit cu, int selectionOffset, int selectionLength, IChooseImportQuery query, boolean save, boolean apply) {
		super();
		Assert.isNotNull(cu);

		fCompilationUnit= cu;
		fSelectionOffset= selectionOffset;
		fSelectionLength= selectionLength;
		fQuery= query;
		fStatus= Status.OK_STATUS;
		fDoSave= save;
		fApply= apply;
	}

	/**
	 * @return Returns the status.
	 */
	public IStatus getStatus() {
		return fStatus;
	}

	/**
	 * Runs the operation.
	 * 
	 * @param monitor The progress monitor
	 * @throws CoreException if accessing the CU or rewritting the imports fails
	 * @throws OperationCanceledException Runtime error thrown when operation is canceled.
	 */
	@Override
	public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
		if (monitor == null) {
			monitor= new NullProgressMonitor();
		}
		try {
			monitor.beginTask(CodeGenerationMessages.AddImportsOperation_description, 4);

			CompilationUnit astRoot= SharedASTProvider.getAST(fCompilationUnit, SharedASTProvider.WAIT_YES, new SubProgressMonitor(monitor, 1));
			if (astRoot == null)
				throw new OperationCanceledException();

			ImportRewrite importRewrite= StubUtility.createImportRewrite(astRoot, true);

			MultiTextEdit res= new MultiTextEdit();

			TextEdit edit= evaluateEdits(astRoot, importRewrite, fSelectionOffset, fSelectionLength, new SubProgressMonitor(monitor, 1));
			if (edit == null) {
				return;
			}
			res.addChild(edit);

			TextEdit importsEdit= importRewrite.rewriteImports(new SubProgressMonitor(monitor, 1));
			res.addChild(importsEdit);

			fResultingEdit= res;

			if (fApply) {
				JavaModelUtil.applyEdit(fCompilationUnit, res, fDoSave, new SubProgressMonitor(monitor, 1));
			}
		} finally {
			monitor.done();
		}
	}

	/**
	 * Returns the resulting edit
	 *
	 * @return the resulting edit
	 */
	public MultiTextEdit getResultingEdit() {
		return fResultingEdit;
	}

	private TextEdit evaluateEdits(CompilationUnit root, ImportRewrite importRewrite, int offset, int length, IProgressMonitor monitor) throws JavaModelException {
		SimpleName nameNode= null;
		if (root != null) { // got an AST
			ASTNode node= NodeFinder.perform(root, offset, length);
			if (node instanceof MarkerAnnotation) {
				node= ((Annotation) node).getTypeName();
			}
			if (node instanceof QualifiedName) {
				nameNode= ((QualifiedName) node).getName();
			} else if (node instanceof SimpleName) {
				nameNode= (SimpleName) node;
			}
		}

		String name, simpleName, containerName;
		int qualifierStart;
		int simpleNameStart;

		if (nameNode != null) {
			simpleName= nameNode.getIdentifier();
			simpleNameStart= nameNode.getStartPosition();
			if (nameNode.getLocationInParent() == QualifiedName.NAME_PROPERTY) {
				Name qualifier= ((QualifiedName) nameNode.getParent()).getQualifier();
				containerName= qualifier.getFullyQualifiedName();
				name= JavaModelUtil.concatenateName(containerName, simpleName);
				qualifierStart= qualifier.getStartPosition();
			} else if (nameNode.getLocationInParent() == NameQualifiedType.NAME_PROPERTY) {
				NameQualifiedType nameQualifiedType= (NameQualifiedType) nameNode.getParent();
				Name qualifier= nameQualifiedType.getQualifier();
				containerName= qualifier.getFullyQualifiedName();
				name= JavaModelUtil.concatenateName(containerName, simpleName);
				qualifierStart= qualifier.getStartPosition();
				List<Annotation> annotations= nameQualifiedType.annotations();
				if (!annotations.isEmpty()) { // don't remove annotations
					simpleNameStart= annotations.get(0).getStartPosition();
				}
			} else if (nameNode.getLocationInParent() == MethodInvocation.NAME_PROPERTY) {
				ASTNode qualifier= ((MethodInvocation) nameNode.getParent()).getExpression();
				if (qualifier instanceof Name) {
					containerName= ASTNodes.asString(qualifier);
					name= JavaModelUtil.concatenateName(containerName, simpleName);
					qualifierStart= qualifier.getStartPosition();
				} else {
					return null;
				}
			} else {
				containerName= ""; //$NON-NLS-1$
				name= simpleName;
				qualifierStart= simpleNameStart;
			}

			IBinding binding= nameNode.resolveBinding();
			if (binding != null && !binding.isRecovered()) {
				if (binding instanceof ITypeBinding) {
					ITypeBinding typeBinding= ((ITypeBinding) binding).getTypeDeclaration();
					String qualifiedBindingName= typeBinding.getQualifiedName();
					if (containerName.length() > 0 && !qualifiedBindingName.equals(name)) {
						return null;
					}

					ImportRewriteContext context= new ContextSensitiveImportRewriteContext(root, qualifierStart, importRewrite);
					String res= importRewrite.addImport(typeBinding, context);
					if (containerName.length() > 0 && !res.equals(simpleName)) {
						// adding import failed
						fStatus= JavaUIStatus.createError(IStatus.ERROR, CodeGenerationMessages.AddImportsOperation_error_importclash, null);
						return null;
					}
					if (containerName.length() == 0 && res.equals(simpleName)) {
						// no change necessary
						return null;
					}
					return new ReplaceEdit(qualifierStart, simpleNameStart - qualifierStart, new String());
				} else if (JavaModelUtil.is50OrHigher(fCompilationUnit.getJavaProject()) && (binding instanceof IVariableBinding || binding instanceof IMethodBinding)) {
					boolean isField= binding instanceof IVariableBinding;
					ITypeBinding declaringClass= isField ? ((IVariableBinding) binding).getDeclaringClass() : ((IMethodBinding) binding).getDeclaringClass();
					if (declaringClass == null) {
						return null; // variableBinding.getDeclaringClass() is null for array.length
					}
					if (Modifier.isStatic(binding.getModifiers())) {
						if (containerName.length() > 0) {
							if (containerName.equals(declaringClass.getName()) || containerName.equals(declaringClass.getQualifiedName()) ) {
								ASTNode node= nameNode.getParent();
								boolean isDirectlyAccessible= false;
								while (node != null) {
									if (isTypeDeclarationSubTypeCompatible(node, declaringClass)) {
										isDirectlyAccessible= true;
										break;
									}
									node= node.getParent();
								}
								if (!isDirectlyAccessible) {
									if (Modifier.isPrivate(declaringClass.getModifiers())) {
										fStatus= JavaUIStatus.createError(IStatus.ERROR,
												Messages.format(CodeGenerationMessages.AddImportsOperation_error_not_visible_class, BasicElementLabels.getJavaElementName(declaringClass.getName())),
												null);
										return null;
									}
									String res= importRewrite.addStaticImport(declaringClass.getQualifiedName(), binding.getName(), isField);
									if (!res.equals(simpleName)) {
										// adding import failed
										return null;
									}
								}
								return new ReplaceEdit(qualifierStart, simpleNameStart - qualifierStart, ""); //$NON-NLS-1$
							}
						}
					}
					return null; // no static imports for packages
				} else {
					return null;
				}
			}
			if (binding != null && binding.getKind() != IBinding.TYPE) {
				// recovered binding
				return null;
			}

		} else {
			IBuffer buffer= fCompilationUnit.getBuffer();

			qualifierStart= getNameStart(buffer, offset);
			int nameEnd= getNameEnd(buffer, offset + length);
			int len= nameEnd - qualifierStart;
			name= buffer.getText(qualifierStart, len).trim();
			if (name.length() == 0) {
				return null;
			}

			simpleName= Signature.getSimpleName(name);
			containerName= Signature.getQualifier(name);

			IJavaProject javaProject= fCompilationUnit.getJavaProject();
			if (simpleName.length() == 0 || JavaConventionsUtil.validateJavaTypeName(simpleName, javaProject).matches(IStatus.ERROR)
					|| (containerName.length() > 0 && JavaConventionsUtil.validateJavaTypeName(containerName, javaProject).matches(IStatus.ERROR))) {
				fStatus= JavaUIStatus.createError(IStatus.ERROR, CodeGenerationMessages.AddImportsOperation_error_invalid_selection, null);
				return null;
			}

			simpleNameStart= getSimpleNameStart(buffer, qualifierStart, containerName);

			int res= importRewrite.getDefaultImportRewriteContext().findInContext(containerName, simpleName, ImportRewriteContext.KIND_TYPE);
			if (res == ImportRewriteContext.RES_NAME_CONFLICT) {
				fStatus= JavaUIStatus.createError(IStatus.ERROR, CodeGenerationMessages.AddImportsOperation_error_importclash, null);
				return null;
			} else if (res == ImportRewriteContext.RES_NAME_FOUND) {
				return new ReplaceEdit(qualifierStart, simpleNameStart - qualifierStart, ""); //$NON-NLS-1$
			}
		}
		IJavaSearchScope searchScope= SearchEngine.createJavaSearchScope(new IJavaElement[] { fCompilationUnit.getJavaProject() });

		TypeNameMatch[] types= findAllTypes(simpleName, searchScope, nameNode, new SubProgressMonitor(monitor, 1));
		if (types.length == 0) {
			fStatus= JavaUIStatus.createError(IStatus.ERROR, Messages.format(CodeGenerationMessages.AddImportsOperation_error_notresolved_message, BasicElementLabels.getJavaElementName(simpleName)), null);
			return null;
		}

		if (monitor.isCanceled()) {
			throw new OperationCanceledException();
		}
		TypeNameMatch chosen;
		if (types.length > 1 && fQuery != null) {
			chosen= fQuery.chooseImport(types, containerName);
			if (chosen == null) {
				throw new OperationCanceledException();
			}
		} else {
			chosen= types[0];
		}
		ImportRewriteContext context= root == null ? null : new ContextSensitiveImportRewriteContext(root, simpleNameStart, importRewrite);
		importRewrite.addImport(chosen.getFullyQualifiedName(), context);
		return new ReplaceEdit(qualifierStart, simpleNameStart - qualifierStart, ""); //$NON-NLS-1$
	}


	private boolean isTypeDeclarationSubTypeCompatible(ASTNode typeDeclaration, ITypeBinding supertype) {
		if (typeDeclaration instanceof AbstractTypeDeclaration) {
			ITypeBinding binding= ((AbstractTypeDeclaration) typeDeclaration).resolveBinding();
			return binding != null && binding.isSubTypeCompatible(supertype);
		} else if (typeDeclaration instanceof AnonymousClassDeclaration) {
			ITypeBinding binding= ((AnonymousClassDeclaration) typeDeclaration).resolveBinding();
			return binding != null && binding.isSubTypeCompatible(supertype);
		} else {
			return false;
		}
	}

	private int getNameStart(IBuffer buffer, int pos) {
		while (pos > 0) {
			char ch= buffer.getChar(pos - 1);
			if (!Character.isJavaIdentifierPart(ch) && ch != '.') {
				return pos;
			}
			pos--;
		}
		return pos;
	}

	private int getNameEnd(IBuffer doc, int pos) {
		if (pos > 0) {
			if (Character.isWhitespace(doc.getChar(pos - 1))) {
				return pos;
			}
		}
		int len= doc.getLength();
		while (pos < len) {
			char ch= doc.getChar(pos);
			if (!Character.isJavaIdentifierPart(ch)) {
				return pos;
			}
			pos++;
		}
		return pos;
	}

	private int getSimpleNameStart(IBuffer buffer, int nameStart, String containerName) {
		int containerLen= containerName.length();
		int docLen= buffer.getLength();
		if (containerLen > 0 && nameStart + containerLen + 1 < docLen) {
			for (int k= 0; k < containerLen; k++) {
				if (buffer.getChar(nameStart + k) != containerName.charAt(k)) {
					return nameStart;
				}
			}
			if (buffer.getChar(nameStart + containerLen) == '.') {
				return nameStart + containerLen + 1;
			}
		}
		return nameStart;
	}

	private int getSearchForConstant(int typeKinds) {
		final int CLASSES= TypeKinds.CLASSES;
		final int INTERFACES= TypeKinds.INTERFACES;
		final int ENUMS= TypeKinds.ENUMS;
		final int ANNOTATIONS= TypeKinds.ANNOTATIONS;

		switch (typeKinds & (CLASSES | INTERFACES | ENUMS | ANNOTATIONS)) {
			case CLASSES: return IJavaSearchConstants.CLASS;
			case INTERFACES: return IJavaSearchConstants.INTERFACE;
			case ENUMS: return IJavaSearchConstants.ENUM;
			case ANNOTATIONS: return IJavaSearchConstants.ANNOTATION_TYPE;
			case CLASSES | INTERFACES: return IJavaSearchConstants.CLASS_AND_INTERFACE;
			case CLASSES | ENUMS: return IJavaSearchConstants.CLASS_AND_ENUM;
			default: return IJavaSearchConstants.TYPE;
		}
	}


	/*
	 * Finds a type by the simple name.
	 */
	private TypeNameMatch[] findAllTypes(String simpleTypeName, IJavaSearchScope searchScope, SimpleName nameNode, IProgressMonitor monitor) throws JavaModelException {
		boolean is50OrHigher= JavaModelUtil.is50OrHigher(fCompilationUnit.getJavaProject());

		int typeKinds= TypeKinds.ALL_TYPES;
		if (nameNode != null) {
			typeKinds= ASTResolving.getPossibleTypeKinds(nameNode, is50OrHigher);
		}

		ArrayList<TypeNameMatch> typeInfos= new ArrayList<>();
		TypeNameMatchCollector requestor= new TypeNameMatchCollector(typeInfos);
		int matchMode= SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE;
		new SearchEngine().searchAllTypeNames(null, matchMode, simpleTypeName.toCharArray(), matchMode, getSearchForConstant(typeKinds), searchScope, requestor, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor);

		ArrayList<TypeNameMatch> typeRefsFound= new ArrayList<>(typeInfos.size());
		for (int i= 0, len= typeInfos.size(); i < len; i++) {
			TypeNameMatch curr= typeInfos.get(i);
			if (curr.getPackageName().length() > 0) { // do not suggest imports from the default package
				if (isOfKind(curr, typeKinds, is50OrHigher) && isVisible(curr)) {
					typeRefsFound.add(curr);
				}
			}
		}
		return typeRefsFound.toArray(new TypeNameMatch[typeRefsFound.size()]);
	}

	private boolean isOfKind(TypeNameMatch curr, int typeKinds, boolean is50OrHigher) {
		int flags= curr.getModifiers();
		if (Flags.isAnnotation(flags)) {
			return is50OrHigher && (typeKinds & TypeKinds.ANNOTATIONS) != 0;
		}
		if (Flags.isEnum(flags)) {
			return is50OrHigher && (typeKinds & TypeKinds.ENUMS) != 0;
		}
		if (Flags.isInterface(flags)) {
			return (typeKinds & TypeKinds.INTERFACES) != 0;
		}
		return (typeKinds & TypeKinds.CLASSES) != 0;
	}


	private boolean isVisible(TypeNameMatch curr) {
		int flags= curr.getModifiers();
		if (Flags.isPrivate(flags)) {
			return false;
		}
		if (Flags.isPublic(flags) || Flags.isProtected(flags)) {
			return true;
		}
		return curr.getPackageName().equals(fCompilationUnit.getParent().getElementName());
	}


	/**
	 * @return Returns the scheduling rule for this operation
	 */
	public ISchedulingRule getScheduleRule() {
		return fCompilationUnit.getJavaProject().getResource();
	}

}
