/*
 * Copyright (c) 2006, 2007 Borland Software Corporation
 * 
 * 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:
 *    Anna Karjakina (Borland) - initial API and implementation
 */
package org.eclipse.gmf.internal.common.codegen;

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.List;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.gmf.internal.common.Activator;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.Name;
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.ui.PreferenceConstants;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;

public class OrganizeImportsPostprocessor {

	private final boolean myRestoreExistingImports;

	public OrganizeImportsPostprocessor() {
		this(true);
	}

	/**
	 * @param restoreExistingImports
	 *            specifies if the existing imports should be kept or removed,
	 *            see {@link ImportRewrite#create(CompilationUnit, boolean)} for
	 *            details.
	 */
	public OrganizeImportsPostprocessor(boolean restoreExistingImports) {
		myRestoreExistingImports = restoreExistingImports;
	}

	/**
	 * Organizes qualified names in document.
	 * <p>
	 * Traverses the ast tree and extracts any full qualified names to be import
	 * statements, with respect to the name conflicts possible.
	 * </p>
	 * <p>
	 * Afterwards these imports are organized with the help of
	 * {@link ImportRewrite} manager.
	 * </p>
	 * <p>
	 * Changes are applied directly to the given ICompilationUnit's buffer,
	 * using code formatting settings as specified in the JDT UI preferences.
	 * Saving of the unit is left for the user consideration.
	 * </p>
	 * 
	 * @param icu
	 *            the compilation unit containing <b>valid</b> code
	 * @param declaredImportsAsStrings
	 *            imports added in previous file revision (default is null)
	 * @param monitor
	 *            the progress monitor used to report progress and request
	 *            cancelation, or <code>null</code> if none
	 * 
	 * @throws CoreException
	 *             the exception is thrown if the rewrite fails.
	 * 
	 * @see ImportRewrite
	 */
	public void organizeImports(ICompilationUnit icu, IProgressMonitor progress) throws CoreException {
		organizeImports(icu, null, progress);
	}

	public void organizeImports(ICompilationUnit icu, String[] declaredImportsAsStrings, IProgressMonitor progress) throws CoreException {
		IDocument document = new Document(icu.getBuffer().getContents());

		ASTParser parser = ASTParser.newParser(AST.JLS4);
		parser.setSource(icu);
		parser.setCompilerOptions(createCompilerOptions("1.5"));
		CompilationUnit cu = (CompilationUnit) parser.createAST(progress);

		TextEdit importsEdit = organizeImports(cu, declaredImportsAsStrings, progress);

		try {
			importsEdit.apply(document);
		} catch (BadLocationException e) {
			throw new CoreException(new Status(IStatus.ERROR, Activator.getID(), 0, "Unable to apply imports text changes", e));
		} catch (MalformedTreeException ex) {
			throw new CoreException(new Status(IStatus.ERROR, Activator.getID(), 0, "Unable to apply imports text changes", ex));
		}
		icu.getBuffer().setContents(document.get());
	}

	/**
	 * Organizes qualified names in document.
	 * <p>
	 * Traverses the ast tree and extracts any full qualified names to be import
	 * statements, with respect to the name conflicts possible.
	 * </p>
	 * <p>
	 * Afterwards these imports are organized with the help of
	 * {@link ImportRewrite} manager.
	 * </p>
	 * 
	 * @param astRoot
	 *            the parsed traversable ast tree, should contain no errors
	 * @param declaredImports
	 *            imports added in previous file revision (default is null)
	 * @param monitor
	 *            the progress monitor used to report progress and request
	 *            cancelation, or <code>null</code> if none
	 * 
	 * @return text edit object describing the changes to the document
	 *         corresponding to the changes recorded by rewriter
	 * 
	 * @throws CoreException
	 *             the exception is thrown if the rewrite fails.
	 * 
	 * @see ImportRewrite
	 */
	public TextEdit organizeImports(CompilationUnit astRoot, IProgressMonitor progress) throws CoreException {
		return organizeImports(astRoot, null, progress);
	}

	public TextEdit organizeImports(CompilationUnit astRoot, String[] declaredImports, IProgressMonitor progress) throws CoreException {
		MultiTextEdit result = new MultiTextEdit();

		HashSet<String> oldSingleImports = new HashSet<String>();
		HashSet<String> oldDemandImports = new HashSet<String>();

		@SuppressWarnings("unchecked")
		final List<ImportDeclaration> importDeclarations = astRoot.imports();
		String[] customImports = substract(declaredImports, importDeclarations);
		if (isDebug()) {
			collectExistingImports(astRoot, oldSingleImports, oldDemandImports, customImports);
		}

		if (!checkForNoSyntaxErrors(astRoot)) {
			String location = astRoot.getJavaElement() == null ? "<undefined>" : astRoot.getJavaElement().getElementName();
			throw new CoreException(new Status(IStatus.ERROR, Activator.getID(), 0, Messages.bind(Messages.organizeImportsFail, location), null));
		}

		ArrayList<Name> qualifiedTypeReferences = new ArrayList<Name>();
		ArrayList<SimpleName> simpleTypeReferences = new ArrayList<SimpleName>();
		ArrayList<String> importsAdded = new ArrayList<String>();

		PackageReferencesCollector.collect(astRoot, qualifiedTypeReferences, simpleTypeReferences, importsAdded);

		ImportRewrite importRewrite = createImportRewrite(astRoot);
		copyImports(importRewrite, customImports);
		ImportRewrite.ImportRewriteContext context = new ReferencedTypesAwareImportRewriteContext(simpleTypeReferences, importRewrite);

		Iterator<Name> refIterator = qualifiedTypeReferences.iterator();
		while (refIterator.hasNext()) {
			Name typeRef = refIterator.next();
			if (typeRef.isQualifiedName()) {
				QualifiedName qualifiedName = (QualifiedName) typeRef;
				SimpleName simpleName = qualifiedName.getName();
				boolean added = addImport(simpleName.getIdentifier(), qualifiedName.getFullyQualifiedName(), importRewrite, context, importsAdded);
				if (added) {
					Name qualifier = qualifiedName.getQualifier();
					int qualifierStart = qualifier.getStartPosition();
					int simpleNameStart = simpleName.getStartPosition();
					try {
						result.addChild(new ReplaceEdit(qualifierStart, simpleNameStart - qualifierStart, ""));
					} catch (MalformedTreeException e) {
						throw new CoreException(new Status(IStatus.ERROR, Activator.getID(), 0, "Unable to produce correct text changes for replacing full name: " + qualifiedName, e));
					}
				}
			} else {
				SimpleName simpleName = (SimpleName) typeRef;
				addImport(simpleName.getIdentifier(), simpleName.getFullyQualifiedName(), importRewrite, context, importsAdded);
			}
		}

		TextEdit edit = importRewrite.rewriteImports(progress);
		try {
			result.addChild(edit);
		} catch (MalformedTreeException e) {
			throw new CoreException(new Status(IStatus.ERROR, Activator.getID(), 0, "Text changes conflict while organizing imports", e));
		}

		if (isDebug()) {
			determineImportDifferences(importRewrite, oldSingleImports, oldDemandImports);
		}

		return result;
	}

	/*
	 * Since we do organizeImports prior to merge, we must ensure imports added
	 * manually are known to OrganizeImportsProcessor
	 */
	private static void copyImports(ImportRewrite importRewrite, String[] importsToCopy) {
		if (importsToCopy == null || importsToCopy.length == 0) {
			return;
		}
		for (int i = 0; i < importsToCopy.length; i++) {
			importRewrite.addImport(importsToCopy[i]);
		}
	}

	private String[] substract(String[] declaredImports, List<ImportDeclaration> list) {
		if (declaredImports == null || declaredImports.length == 0) {
			return declaredImports;
		}
		ArrayList<String> result = new ArrayList<String>(Arrays.asList(declaredImports));
		for (int i = 0; i < list.size(); i++) {
			result.remove(list.get(i).getName().getFullyQualifiedName());
		}
		return result.toArray(new String[result.size()]);
	}

	private boolean addImport(String typeName, String fullName, ImportRewrite importRewrite, ImportRewrite.ImportRewriteContext context, Collection<String> importsAdded) {
		boolean resultIsOk = importRewrite.addImport(fullName, context).equals(typeName);
		if (resultIsOk && !importsAdded.contains(fullName)) {
			importsAdded.add(fullName);
		}
		return resultIsOk;
	}

	private void collectExistingImports(CompilationUnit astRoot, Set<String> oldSingleImports, Set<String> oldDemandImports, String[] declaredImports) {
		if (declaredImports != null && declaredImports.length > 0) {
			for (int i = 0; i < declaredImports.length; i++) {
				String curr = declaredImports[i];
				if (curr.endsWith("*")) {
					oldDemandImports.add(curr);
				} else {
					oldSingleImports.add(curr);
				}
			}
		}
		@SuppressWarnings("unchecked")
		final List<ImportDeclaration> imports = astRoot.imports();
		for (int i = 0; i < imports.size(); i++) {
			ImportDeclaration curr = imports.get(i);
			String id = curr.getName().getFullyQualifiedName();
			if (curr.isOnDemand()) {
				oldDemandImports.add(id);
			} else {
				oldSingleImports.add(id);
			}
		}
	}

	private boolean checkForNoSyntaxErrors(CompilationUnit astRoot) {
		IProblem[] problems = astRoot.getProblems();
		for (int i = 0; i < problems.length; i++) {
			IProblem curr = problems[i];
			if (curr.isError() && (curr.getID() & IProblem.Syntax) != 0) {
				return false;
			}
		}
		return true;
	}

	private class ReferencedTypesAwareImportRewriteContext extends ImportRewrite.ImportRewriteContext {

		private Collection<SimpleName> mySimpleTypesReferenced;

		private ImportRewrite myImportRewrite;

		public ReferencedTypesAwareImportRewriteContext(Collection<SimpleName> simpleTypesReferenced, ImportRewrite importRewrite) {
			mySimpleTypesReferenced = simpleTypesReferenced;
			myImportRewrite = importRewrite;
		}

		public int findInContext(String qualifier, String name, int kind) {
			int result = myImportRewrite.getDefaultImportRewriteContext().findInContext(qualifier, name, kind);
			if (result == RES_NAME_UNKNOWN) {
				for (Iterator<SimpleName> it = mySimpleTypesReferenced.iterator(); it.hasNext();) {
					SimpleName next = it.next();
					if (name.equals(next.getIdentifier())) {
						return RES_NAME_CONFLICT;
					}
				}
			}
			return result;
		}
	};

	/**
	 * Returns a {@link ImportRewrite} using
	 * {@link ImportRewrite#create(CompilationUnit, boolean)} and configures the
	 * rewriter with the settings as specified in the JDT UI preferences.
	 * 
	 * @param astRoot
	 *            the AST root to create the rewriter on
	 * @return the new rewriter configured with the settings as specified in the
	 *         JDT UI preferences.
	 * 
	 * @see ImportRewrite#create(CompilationUnit, boolean)
	 */
	public ImportRewrite createImportRewrite(CompilationUnit astRoot) {
		return configureImportRewrite(ImportRewrite.create(astRoot, myRestoreExistingImports));
	}

	private static ImportRewrite configureImportRewrite(ImportRewrite rewrite) {
		IJavaProject project = rewrite.getCompilationUnit().getJavaProject();
		String order = PreferenceConstants.getPreference(PreferenceConstants.ORGIMPORTS_IMPORTORDER, project);
		rewrite.setImportOrder(order.split(";", 0)); //$NON-NLS-1$

		String thres = PreferenceConstants.getPreference(PreferenceConstants.ORGIMPORTS_ONDEMANDTHRESHOLD, project);
		try {
			int num = Integer.parseInt(thres);
			if (num == 0) {
				num = 1;
			}
			rewrite.setOnDemandImportThreshold(num);
		} catch (NumberFormatException e) {
			// ignore
		}
		String thresStatic = PreferenceConstants.getPreference(PreferenceConstants.ORGIMPORTS_STATIC_ONDEMANDTHRESHOLD, project);
		try {
			int num = Integer.parseInt(thresStatic);
			if (num == 0) {
				num = 1;
			}
			rewrite.setStaticOnDemandImportThreshold(num);
		} catch (NumberFormatException e) {
			// ignore
		}
		return rewrite;
	}

	private void determineImportDifferences(ImportRewrite importsStructure, Set<String> oldSingleImports, Set<String> oldDemandImports) {
		ArrayList<String> importsAdded = new ArrayList<String>();
		importsAdded.addAll(Arrays.asList(importsStructure.getCreatedImports()));
		importsAdded.addAll(Arrays.asList(importsStructure.getCreatedStaticImports()));
		Object[] content = oldSingleImports.toArray();
		for (int i = 0; i < content.length; i++) {
			String importName = (String) content[i];
			if (importsAdded.remove(importName)) {
				oldSingleImports.remove(importName);
			}
		}
		content = oldDemandImports.toArray();
		for (int i = 0; i < content.length; i++) {
			String importName = (String) content[i];
			if (importsAdded.remove(importName + ".*")) { //$NON-NLS-1$
				oldDemandImports.remove(importName);
			}
		}
		int fNumberOfImportsAdded = importsAdded.size();
		int fNumberOfImportsRemoved = oldSingleImports.size() + oldDemandImports.size();
		Activator.log(new Status(IStatus.INFO, Activator.getID(), 0, "[imports added]: " + fNumberOfImportsAdded, null));
		Activator.log(new Status(IStatus.INFO, Activator.getID(), 0, "[imports removed]: " + fNumberOfImportsRemoved, null));
	}

	private static boolean isDebug() {
		return Boolean.parseBoolean(Platform.getDebugOption(Activator.getID() + "/debug/organizeImports"));//$NON-NLS-1$
	}

	@SuppressWarnings("unchecked")
	private final static HashMap<String, String> createCompilerOptions(String targetLevel) {
		HashMap<String, String> result = new HashMap<String, String>(JavaCore.getOptions());
		result.put(JavaCore.COMPILER_COMPLIANCE, targetLevel);
		result.put(JavaCore.COMPILER_SOURCE, targetLevel);
		result.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, targetLevel);
		return result;
	}

}
