/*******************************************************************************
 * Copyright (c) 2004, 2017 Richard Hoefter and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     Richard Hoefter (richard.hoefter@web.de) - initial API and implementation, bug 95300, bug 95297, bug 128104, bug 201180, bug 288830 
 *     IBM Corporation - NLS'ing and incorporating into Eclipse. 
 *                     - Bug 177833 Class created from combination of all utility classes of contribution 
 *                     - Bug 267459 Java project with an external jar file from C:\ on the build path throws a NPE during the Ant Buildfile generation.
 *                     - bug fixing
 *******************************************************************************/

package org.eclipse.ant.internal.ui.datatransfer;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.junit.JUnitCore;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

/**
 * Collection of utility methods to help when exporting to an Ant build file.
 */
public class ExportUtil {
	private ExportUtil() {
	}

	/**
	 * Get resource from selection.
	 */
	public static IResource getResource(ISelection selection) {
		if (selection instanceof IStructuredSelection) {
			for (Iterator<IAdaptable> iter = ((IStructuredSelection) selection).iterator(); iter.hasNext();) {
				IAdaptable adaptable = iter.next();
				return adaptable.getAdapter(IResource.class);
			}
		}
		return null;
	}

	/**
	 * Get Java project from resource.
	 */
	public static IJavaProject getJavaProjectByName(String name) {
		try {
			IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
			if (project.exists()) {
				return JavaCore.create(project);
			}
		}
		catch (IllegalArgumentException iae) {
			// do nothing
		}
		return null;
	}

	/**
	 * Get project root for given project.
	 */
	public static String getProjectRoot(IJavaProject project) {
		if (project == null) {
			return null;
		}
		IResource resource = project.getResource();
		if (resource == null) {
			return null;
		}
		IPath location = resource.getLocation();
		if (location == null) {
			return null;
		}
		return location.toString();
	}

	/**
	 * Convert Eclipse path to absolute filename.
	 * 
	 * @param file
	 *            Project root optionally followed by resource name. An absolute path is simply converted to a string.
	 * @return full qualified path
	 */
	public static String resolve(IPath file) {
		if (file == null) {
			return null;
		}
		try {
			IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(file);
			URI uri = f.getLocationURI();
			return (uri != null) ? uri.toString() : f.toString();
		}
		catch (IllegalArgumentException e) {
			// resource is missing
			String projectName = removePrefix(file.toString(), "/"); //$NON-NLS-1$
			IJavaProject project = getJavaProjectByName(projectName);
			if (project != null) {
				return getProjectRoot(project);
			}
			// project is null because file is not enclosed in a project i.e.
			// external jar
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=267459
			return file.toOSString();
		}
	}

	/**
	 * Get Java project for given root.
	 */
	public static IJavaProject getJavaProject(String root) {
		IPath path = new Path(root);
		if (path.segmentCount() == 1) {
			return getJavaProjectByName(root);
		}
		IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
		if (resource != null && resource.getType() == IResource.PROJECT) {
			if (resource.exists()) {
				return (IJavaProject) JavaCore.create(resource);
			}
		}
		return null;
	}

	/**
	 * Remove project root from given project file.
	 */
	public static String removeProjectRoot(String file, IProject project) {
		String res = removePrefix(file, '/' + project.getName() + '/');
		if (res.equals('/' + project.getName())) {
			return "."; //$NON-NLS-1$
		}
		return res;
	}

	/**
	 * Remove project root from given project file.
	 * 
	 * @param newProjectRoot
	 *            replace project root, e.g. with a variable ${project.location}
	 */
	public static String replaceProjectRoot(String file, IProject project, String newProjectRoot) {
		String res = removeProjectRoot(file, project);
		if (res.equals(".")) //$NON-NLS-1$
		{
			return newProjectRoot;
		}
		if (newProjectRoot == null) {
			return res;
		}
		if (!res.equals(file)) {
			return newProjectRoot + '/' + res;
		}
		return res;
	}

	/**
	 * Get for given project all directly dependent projects.
	 * 
	 * @return set of IJavaProject objects
	 */
	public static List<IJavaProject> getClasspathProjects(IJavaProject project) throws JavaModelException {
		List<IJavaProject> projects = new ArrayList<>();
		IClasspathEntry entries[] = project.getRawClasspath();
		addClasspathProjects(projects, entries);
		return sortProjectsUsingBuildOrder(projects);
	}

	private static void addClasspathProjects(List<IJavaProject> projects, IClasspathEntry[] entries) {
		for (int i = 0; i < entries.length; i++) {
			IClasspathEntry classpathEntry = entries[i];
			if (classpathEntry.getContentKind() == IPackageFragmentRoot.K_SOURCE && classpathEntry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
				// found required project on build path
				String subProjectRoot = classpathEntry.getPath().toString();
				IJavaProject subProject = getJavaProject(subProjectRoot);
				// is project available in workspace
				if (subProject != null) {
					projects.add(subProject);
				}
			}
		}
	}

	/**
	 * Get for given project all directly and indirectly dependent projects.
	 * 
	 * @return set of IJavaProject objects
	 */
	public static List<IJavaProject> getClasspathProjectsRecursive(IJavaProject project) throws JavaModelException {
		LinkedList<IJavaProject> result = new LinkedList<>();
		getClasspathProjectsRecursive(project, result);
		return sortProjectsUsingBuildOrder(result);
	}

	private static void getClasspathProjectsRecursive(IJavaProject project, LinkedList<IJavaProject> result) throws JavaModelException {
		List<IJavaProject> projects = getClasspathProjects(project);
		for (Iterator<IJavaProject> iter = projects.iterator(); iter.hasNext();) {
			IJavaProject javaProject = iter.next();
			if (!result.contains(javaProject)) {
				result.addFirst(javaProject);
				getClasspathProjectsRecursive(javaProject, result); // recursion
			}
		}
	}

	/**
	 * Sort projects according to General -&gt; Workspace -&gt; Build Order.
	 * 
	 * @param projects
	 *            list of IJavaProject objects
	 * @return list of IJavaProject objects with new order
	 */
	private static List<IJavaProject> sortProjectsUsingBuildOrder(List<IJavaProject> javaProjects) {
		if (javaProjects.isEmpty()) {
			return javaProjects;
		}
		List<IJavaProject> result = new ArrayList<>(javaProjects.size());
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		String[] buildOrder = workspace.getDescription().getBuildOrder();
		if (buildOrder == null) {// default build order
			IProject[] projects = new IProject[javaProjects.size()];
			int i = 0;
			for (Iterator<IJavaProject> iter = javaProjects.iterator(); iter.hasNext(); i++) {
				IJavaProject javaProject = iter.next();
				projects[i] = javaProject.getProject();
			}
			IWorkspace.ProjectOrder po = ResourcesPlugin.getWorkspace().computeProjectOrder(projects);
			projects = po.projects;
			buildOrder = new String[projects.length];
			for (i = 0; i < projects.length; i++) {
				buildOrder[i] = projects[i].getName();
			}
		}

		for (int i = 0; i < buildOrder.length && !javaProjects.isEmpty(); i++) {
			String projectName = buildOrder[i];
			for (Iterator<IJavaProject> iter = javaProjects.iterator(); iter.hasNext();) {
				IJavaProject javaProject = iter.next();
				if (javaProject.getProject().getName().equals(projectName)) {
					result.add(javaProject);
					iter.remove();
				}
			}
		}
		// add any remaining projects not specified in the build order
		result.addAll(javaProjects);
		return result;
	}

	/**
	 * Returns cyclic dependency marker for a given project.
	 * 
	 * <p>
	 * See org.eclipse.jdt.core.tests.model.ClasspathTests.numberOfCycleMarkers.
	 * 
	 * @param javaProject
	 *            project for which cyclic dependency marker should be found
	 * @return cyclic dependency marker for a given project or <code>null</code> if there is no such marker
	 * @throws CoreException
	 */
	public static IMarker getCyclicDependencyMarker(IJavaProject javaProject) throws CoreException {
		IMarker[] markers = javaProject.getProject().findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ONE);
		for (int i = 0; i < markers.length; i++) {
			IMarker marker = markers[i];
			String cycleAttr = (String) marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED);
			if (cycleAttr != null && cycleAttr.equals("true")) //$NON-NLS-1$
			{
				return marker;
			}
		}
		return null;
	}

	/**
	 * Find JUnit tests. Same tests are also returned by Eclipse run configuration wizard.
	 * 
	 * @param containerHandle
	 *            project, package or source folder
	 */
	public static IType[] findTestsInContainer(String containerHandle) {
		IJavaElement container = JavaCore.create(containerHandle);
		if (container == null) {
			return new IType[0];
		}
		try {
			return JUnitCore.findTestTypes(container, new NullProgressMonitor());
		}
		catch (OperationCanceledException e) {
			AntUIPlugin.log(e);
		}
		catch (CoreException e) {
			AntUIPlugin.log(e);
		}
		return new IType[0];
	}

	/**
	 * Compares projects by project name.
	 */
	public static synchronized Comparator<IJavaProject> getJavaProjectComparator() {
		if (javaProjectComparator == null) {
			javaProjectComparator = new JavaProjectComparator();
		}
		return javaProjectComparator;
	}

	private static Comparator<IJavaProject> javaProjectComparator;

	private static class JavaProjectComparator implements Comparator<IJavaProject> {
		@Override
		public int compare(IJavaProject o1, IJavaProject o2) {
			IJavaProject j1 = o1;
			IJavaProject j2 = o2;
			return j1.getProject().getName().compareTo(j2.getProject().getName());
		}
	}

	/**
	 * Compares IFile objects.
	 */
	public static synchronized Comparator<IFile> getIFileComparator() {
		if (fileComparator == null) {
			fileComparator = new IFileComparator();
		}
		return fileComparator;
	}

	private static Comparator<IFile> fileComparator;

	private static class IFileComparator implements Comparator<IFile> {
		@Override
		public int compare(IFile o1, IFile o2) {
			IFile f1 = o1;
			IFile f2 = o2;
			return f1.toString().compareTo(f2.toString());
		}
	}

	/**
	 * Compares IType objects.
	 */
	public static synchronized Comparator<IType> getITypeComparator() {
		if (typeComparator == null) {
			typeComparator = new TypeComparator();
		}
		return typeComparator;
	}

	private static Comparator<IType> typeComparator;

	private static class TypeComparator implements Comparator<IType> {
		@Override
		public int compare(IType o1, IType o2) {
			IType t1 = o1;
			IType t2 = o2;
			return t1.getFullyQualifiedName().compareTo(t2.getFullyQualifiedName());
		}
	}

	/**
	 * Platform specific newline character(s).
	 */
	public static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$

	public static String removePrefix(String s, String prefix) {
		if (s == null) {
			return null;
		}
		if (s.startsWith(prefix)) {
			return s.substring(prefix.length());
		}
		return s;
	}

	/**
	 * Remove suffix from given string.
	 */
	public static String removeSuffix(String s, String suffix) {
		if (s == null) {
			return null;
		}
		if (s.endsWith(suffix)) {
			return s.substring(0, s.length() - suffix.length());
		}
		return s;
	}

	/**
	 * Remove prefix and suffix from given string.
	 */
	public static String removePrefixAndSuffix(String s, String prefix, String suffix) {
		return removePrefix(removeSuffix(s, suffix), prefix);
	}

	/**
	 * Convert document to formatted XML string.
	 */
	public static String toString(Document doc) throws TransformerConfigurationException, TransformerFactoryConfigurationError, TransformerException {
		// NOTE: There are different transformer implementations in the wild,
		// which are configured differently
		// regarding the indent size:
		// Java 1.4: org.apache.xalan.transformer.TransformerIdentityImpl
		// Java 1.5:
		// com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl

		StringWriter writer = new StringWriter();
		Source source = new DOMSource(doc);
		Result result = new StreamResult(writer);
		TransformerFactory factory = TransformerFactory.newInstance();
		// https://ant.apache.org/manual/Tasks/style.html
		// Need this feature to set true for Java 9 to enable extension Functions in the presence of Security manager
		factory.setFeature("http://www.oracle.com/xml/jaxp/properties/enableExtensionFunctions", Boolean.TRUE); //$NON-NLS-1$
		boolean indentFallback = false;
		try {
			// indent using TransformerImpl
			factory.setAttribute("indent-number", "4"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		catch (IllegalArgumentException e) {
			// option not supported, set indent size below
			indentFallback = true;
		}
		Transformer transformer = factory.newTransformer();
		transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
		if (indentFallback) {
			// indent using TransformerIdentityImpl
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		transformer.transform(source, result);
		return writer.toString();
	}

	/**
	 * Read XML file.
	 */
	public static Document parseXmlFile(File file) throws SAXException, IOException, ParserConfigurationException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setValidating(false);
		Document doc = factory.newDocumentBuilder().parse(file);
		return doc;
	}

	/**
	 * Read XML string.
	 */
	public static Document parseXmlString(String s) throws SAXException, IOException, ParserConfigurationException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		factory.setValidating(false);
		Document doc = factory.newDocumentBuilder().parse(new ByteArrayInputStream(s.getBytes()));
		return doc;
	}

	/**
	 * Converts collection to a separated string.
	 * 
	 * @param c
	 *            collection
	 * @param separator
	 *            string to separate items
	 * @return collection items separated with given separator
	 */
	public static String toString(Collection<String> c, String separator) {
		StringBuilder b = new StringBuilder();
		for (Iterator<String> iter = c.iterator(); iter.hasNext();) {
			b.append(iter.next());
			b.append(separator);
		}
		if (c.size() > 0) {
			b.delete(b.length() - separator.length(), b.length());
		}
		return b.toString();
	}

	/**
	 * Remove duplicates preserving original order.
	 * 
	 * @param l
	 *            list to remove duplicates from
	 * @return new list without duplicates
	 */
	public static List<String> removeDuplicates(List<String> l) {
		List<String> res = new ArrayList<>();
		for (Iterator<String> iter = l.iterator(); iter.hasNext();) {
			String element = iter.next();
			if (!res.contains(element)) {
				res.add(element);
			}
		}
		return res;
	}

	/**
	 * Check if given file exists that was not written by this export.
	 */
	public static boolean existsUserFile(String filename) {
		File buildFile = new File(filename);
		if (buildFile.exists()) {
			try (BufferedReader in = new BufferedReader(new FileReader(buildFile))) {
				int i = BuildFileCreator.WARNING.indexOf(NEWLINE);
				String warning = BuildFileCreator.WARNING.substring(0, i);
				String line;
				while ((line = in.readLine()) != null) {
					if (line.contains(warning)) {
						return false;
					}
				}
				return true;
			}
			catch (FileNotFoundException e) {
				return false;
			}
			catch (IOException e) {
				return false;
			}
		}
		return false;
	}

	/**
	 * Request write access to given file. Depending on the version control plug-in opens a confirm checkout dialog.
	 * 
	 * @param shell
	 *            parent instance for dialogs
	 * @param file
	 *            file to request write access for
	 * @return <code>true</code> if user confirmed checkout
	 */
	public static boolean validateEdit(Shell shell, IFile file) {
		return file.getWorkspace().validateEdit(new IFile[] { file }, shell).isOK();
	}

	/**
	 * Request write access to given files. Depending on the version control plug-in opens a confirm checkout dialog.
	 * 
	 * @param shell
	 *            parent instance for dialogs
	 * @return <code>IFile</code> objects for which user confirmed checkout
	 * @throws CoreException
	 *             thrown if project is under version control, but not connected
	 */
	public static Set<IFile> validateEdit(Shell shell, List<IFile> files) throws CoreException {
		Set<IFile> confirmedFiles = new TreeSet<>(getIFileComparator());
		if (files.size() == 0) {
			return confirmedFiles;
		}
		IStatus status = files.get(0).getWorkspace().validateEdit(files.toArray(new IFile[files.size()]), shell);
		if (status.isMultiStatus() && status.getChildren().length > 0) {
			for (int i = 0; i < status.getChildren().length; i++) {
				IStatus statusChild = status.getChildren()[i];
				if (statusChild.isOK()) {
					confirmedFiles.add(files.get(i));
				}
			}
		} else if (status.isOK()) {
			for (Iterator<IFile> iterator = files.iterator(); iterator.hasNext();) {
				IFile file = iterator.next();
				confirmedFiles.add(file);
			}
		}
		if (status.getSeverity() == IStatus.ERROR) {
			// not possible to checkout files: not connected to version
			// control plugin or hijacked files and made read-only, so
			// collect error messages provided by validator and re-throw
			StringBuilder message = new StringBuilder(status.getPlugin() + ": " //$NON-NLS-1$
					+ status.getMessage() + NEWLINE);
			if (status.isMultiStatus()) {
				for (int i = 0; i < status.getChildren().length; i++) {
					IStatus statusChild = status.getChildren()[i];
					message.append(statusChild.getMessage() + NEWLINE);
				}
			}
			throw new CoreException(new Status(IStatus.ERROR, AntUIPlugin.PI_ANTUI, 0, message.toString(), null));
		}

		return confirmedFiles;
	}

	/**
	 * Check if given classpath is a reference to the default classpath of the project. Ideal for testing if runtime classpath was customized.
	 */
	public static boolean isDefaultClasspath(IJavaProject project, EclipseClasspath classpath) {
		// default classpath contains exactly the JRE and the project reference
		List<String> list = removeDuplicates(classpath.rawClassPathEntries);
		if (list.size() != 2) {
			return false;
		}
		String entry1 = list.get(0);
		String entry2 = list.get(1);
		if (!EclipseClasspath.isJreReference(entry1)) {
			return false;
		}
		if (EclipseClasspath.isProjectReference(entry2)) {
			IJavaProject referencedProject = EclipseClasspath.resolveProjectReference(entry2);
			if (referencedProject == null) {
				// project was not loaded in workspace
				return false;
			} else if (referencedProject.getProject().getName().equals(project.getProject().getName())) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Add variable/value for Eclipse variable. If given string is no variable, nothing is added.
	 * 
	 * @param variable2valueMap
	 *            property map to add variable/value
	 * @param s
	 *            String which may contain Eclipse variables, e.g. ${project_name}
	 */
	public static void addVariable(Map<String, String> variable2valueMap, String s, String projectRoot) {
		if (s == null || s.equals(IAntCoreConstants.EMPTY_STRING)) {
			return;
		}
		Pattern pattern = Pattern.compile("\\$\\{.*?\\}"); // ${var} //$NON-NLS-1$
		Matcher matcher = pattern.matcher(s);
		while (matcher.find()) {
			String variable = matcher.group();
			String value;
			try {
				value = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(variable);
			}
			catch (CoreException e) {
				// cannot resolve variable
				value = variable;
			}
			variable = removePrefixAndSuffix(variable, "${", "}"); //$NON-NLS-1$ //$NON-NLS-2$
			// if it is an environment variable, convert to Ant environment
			// syntax
			if (variable.startsWith("env_var:")) //$NON-NLS-1$
			{
				value = "env." + variable.substring("env_var:".length()); //$NON-NLS-1$ //$NON-NLS-2$
			}
			File file = new File(value);
			if (file.exists()) {
				value = getRelativePath(file.getAbsolutePath(), projectRoot);
			}
			variable2valueMap.put(variable, value);
		}
	}

	/**
	 * Returns a path which is equivalent to the given location relative to the specified base path.
	 */
	public static String getRelativePath(String otherLocation, String basePath) {

		IPath location = new Path(otherLocation);
		IPath base = new Path(basePath);
		if ((location.getDevice() != null && !location.getDevice().equalsIgnoreCase(base.getDevice())) || !location.isAbsolute()) {
			return otherLocation;
		}
		int baseCount = base.segmentCount();
		int count = base.matchingFirstSegments(location);
		String temp = IAntCoreConstants.EMPTY_STRING;
		for (int j = 0; j < baseCount - count; j++) {
			temp += "../"; //$NON-NLS-1$
		}
		String relative = new Path(temp).append(location.removeFirstSegments(count)).toString();
		if (relative.length() == 0) {
			relative = "."; //$NON-NLS-1$
		}

		return relative;
	}
}