/*******************************************************************************
 * 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) {
		StringBuffer b = new StringBuffer();
		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.indexOf(warning) != -1) {
						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
			StringBuffer message = new StringBuffer(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;
	}
}