/*******************************************************************************
 * Copyright (c) 2005, 2013 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 313386
 *     IBM Corporation - incorporating into Eclipse
 *******************************************************************************/

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

import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.core.util.IConstantPool;
import org.eclipse.jdt.core.util.IConstantPoolConstant;
import org.eclipse.jdt.core.util.IConstantPoolEntry;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;

/**
 * Provides a method to analyze sources if it is possible to export projects to an Ant buildfile which compiles correctly.
 */
public class SourceAnalyzer {

	/**
	 * Utility class.
	 */
	private SourceAnalyzer() {

	}

	/**
	 * Check if source directories of project has cycles or if there are dependencies between them that are not conform with classpath order.
	 * 
	 * <p>
	 * NOTE: Unused references in classes are not considered if they cause cycles or classpath order problems. This is because this class analyzes the
	 * bytecode and indeed the compiler throws unused references away.
	 */
	public static void checkCycles(IJavaProject currentProject, EclipseClasspath classpath, Shell shell) {
		StringBuffer message = new StringBuffer();
		Map<String, String> src2dir = new TreeMap<>(); // map string to string
		Map<String, Set<String>> srcdir2classes = new TreeMap<>(); // map string to Set of strings
		determineSources(currentProject, classpath, src2dir, srcdir2classes);
		Map<String, Set<String>> srcdir2sourcedirs = determineRequiredSrcDirs(src2dir, srcdir2classes);
		String projectName = currentProject.getProject().getName();

		List<String> cycle = new ArrayList<>();
		if (isCyclic(srcdir2sourcedirs, cycle)) {
			showCycleWarning(projectName, shell, cycle, message);
			return;
		}

		checkBuildOrder(classpath, projectName, shell, srcdir2sourcedirs);
	}

	/**
	 * Determine all sources belonging to a source directory.
	 */
	private static void determineSources(IJavaProject currentProject, EclipseClasspath classpath, Map<String, String> src2dir, Map<String, Set<String>> srcdir2classes) {
		for (int i = 0; i < classpath.srcDirs.size(); i++) {
			String srcDir = classpath.srcDirs.get(i);
			String classDir = classpath.classDirs.get(i);
			if (EclipseClasspath.isReference(srcDir)) {
				continue;
			}
			File dir;
			if (srcDir.equals(".")) { //$NON-NLS-1$
				dir = currentProject.getResource().getLocation().toFile();
			} else {
				IFile file = currentProject.getProject().getFile(srcDir);
				dir = file.getLocation().toFile();
			}
			if (EclipseClasspath.isLinkedResource(srcDir)) {
				String link = classpath.resolveLinkedResource(srcDir);
				dir = new File(link);
				if (!dir.isAbsolute()) {
					// make absolute
					dir = new File(ExportUtil.getProjectRoot(currentProject), link);
				}
			}
			Set<String> sources = findFiles(dir, ".java"); //$NON-NLS-1$

			// find all required classfiles for each source directory
			for (Iterator<String> iter = sources.iterator(); iter.hasNext();) {
				String srcFile = iter.next();
				src2dir.put(srcFile, srcDir);
				IFile classFile = currentProject.getProject().getFile(classDir + '/' + srcFile + ".class"); //$NON-NLS-1$
				if (!classFile.exists()) {
					// project was not compiled, check not possible
					continue;
				}
				Set<String> classes = srcdir2classes.get(srcDir);
				if (classes == null) {
					classes = new TreeSet<>();
				}
				classes.addAll(getRequiredClasses(classFile));
				srcdir2classes.put(srcDir, classes);
			}
		}
	}

	/**
	 * Determine for each source directory which other source directories it requires.
	 * 
	 * @return Map string to Set of strings. (Maps source dir to Set of required source dirs.)
	 */
	private static Map<String, Set<String>> determineRequiredSrcDirs(Map<String, String> src2dir, Map<String, Set<String>> srcdir2classes) {
		Map<String, Set<String>> srcdir2sourcedirs = new TreeMap<>(); // map string to Set of strings
		for (Iterator<String> iter = srcdir2classes.keySet().iterator(); iter.hasNext();) {
			String srcDir = iter.next();
			Set<String> classes = srcdir2classes.get(srcDir);
			for (Iterator<String> iterator = classes.iterator(); iterator.hasNext();) {
				String classname = iterator.next();
				String classsrc = src2dir.get(classname);
				// don't add reference to itself
				if (classsrc != null && !classsrc.equals(srcDir)) {
					Set<String> sourcedirs = srcdir2sourcedirs.get(srcDir);
					if (sourcedirs == null) {
						sourcedirs = new TreeSet<>();
					}
					sourcedirs.add(classsrc);
					srcdir2sourcedirs.put(srcDir, sourcedirs);
				}
			}
		}
		return srcdir2sourcedirs;
	}

	private static void showCycleWarning(String projectName, Shell shell, List<String> cycle, StringBuffer message) {

		String m = MessageFormat.format(DataTransferMessages.SourceAnalyzer_0, new Object[] { projectName });
		message.append(m);
		message.append(ExportUtil.NEWLINE);

		// print cycle path
		for (String s : cycle) {
			s = EclipseClasspath.getLinkedResourceName(s);
			message.append(s);
			message.append(" -> "); //$NON-NLS-1$
		}
		message.append(EclipseClasspath.getLinkedResourceName(cycle.get(0)));
		MessageDialog.openWarning(shell, DataTransferMessages.SourceAnalyzer_1, message.toString());
	}

	/**
	 * Check if build order is correct.
	 */
	private static void checkBuildOrder(EclipseClasspath classpath, String projectName, Shell shell, Map<String, Set<String>> srcdir2sourcedirs) {
		for (Iterator<String> iter = srcdir2sourcedirs.keySet().iterator(); iter.hasNext();) {
			String srcdir = iter.next();
			Set<String> sourcedirs = srcdir2sourcedirs.get(srcdir);
			int classpathIndex = classpath.srcDirs.indexOf(srcdir);
			for (Iterator<String> iterator = sourcedirs.iterator(); iterator.hasNext();) {
				String requiredSrc = iterator.next();
				int i = classpath.srcDirs.indexOf(requiredSrc);
				if (i > classpathIndex) {
					String s = MessageFormat.format(DataTransferMessages.SourceAnalyzer_3, new Object[] { projectName });
					MessageDialog.openWarning(shell, DataTransferMessages.SourceAnalyzer_2, s + ExportUtil.NEWLINE + requiredSrc + " <-> " + srcdir //$NON-NLS-1$
							+ ExportUtil.NEWLINE);
					break;
				}
			}
		}
	}

	/**
	 * Find all classes that are required by given class file.
	 * 
	 * @param file
	 *            a ".class" file
	 * @return set of strings, each contains a full qualified class name (forward slash as package separator)
	 */
	public static Set<String> getRequiredClasses(IFile file) {
		Set<String> classes = new TreeSet<>();
		IClassFile classFile = JavaCore.createClassFileFrom(file);
		IClassFileReader reader = ToolFactory.createDefaultClassFileReader(classFile, IClassFileReader.CONSTANT_POOL);
		if (reader == null) {
			// class not compiled
			return classes;
		}
		IConstantPool pool = reader.getConstantPool();
		for (int i = 0; i < pool.getConstantPoolCount(); i++) {
			if (pool.getEntryKind(i) == IConstantPoolConstant.CONSTANT_Class) {
				IConstantPoolEntry entry = pool.decodeEntry(i);
				String classname = new String(entry.getClassInfoName());
				// don't return inner classes
				int index = classname.indexOf('$');
				if (index != -1) {
					classname = classname.substring(0, index);
				}
				classes.add(classname);
			}
		}
		return classes;
	}

	/**
	 * Find all files with particular extension under given directory.
	 * 
	 * @param dir
	 *            directory to start search
	 * @param extension
	 *            extension to search
	 * @return filenames relative to directory (without extension and with forward slashes)
	 */
	public static Set<String> findFiles(File dir, String extension) {
		Set<String> visited = new TreeSet<>();
		findFiles(dir, dir, extension, visited);
		return visited;
	}

	private static void findFiles(File base, File dir, String extension, Set<String> visited) {
		if (dir.isDirectory()) {
			File[] children = dir.listFiles();
			for (int i = 0; i < children.length; i++) {
				findFiles(base, children[i], extension, visited);
			}
		} else if (dir.getAbsolutePath().endsWith(extension)) {
			// remove base directory
			String filename = ExportUtil.removePrefixAndSuffix(dir.getAbsolutePath(), base.getAbsolutePath() + File.separator, extension);
			visited.add(filename.replace('\\', '/'));
		}
	}

	/**
	 * Check if given graph that is described through a map is cyclic.
	 * 
	 * @param srcdir2sourcedirs
	 *            Maps string to set of strings. The keys are the graph nodes which are mapped to its neighbors.
	 * @param cycle
	 *            filled with name of nodes which cause cycle
	 */
	private static boolean isCyclic(Map<String, Set<String>> srcdir2sourcedirs, List<String> cycle) {
		return !isAcyclic(srcdir2sourcedirs, cycle);
	}

	private static boolean isAcyclic(Map<String, Set<String>> srcdir2sourcedirs, List<String> cycle) {
		// standard graph theory
		List<String> visited = new ArrayList<>();
		List<String> exited = new ArrayList<>();

		for (Iterator<String> iter = srcdir2sourcedirs.keySet().iterator(); iter.hasNext();) {
			String srcdir = iter.next();
			if (!visited.contains(srcdir)) {
				if (circleSearch(srcdir, srcdir2sourcedirs, visited, exited, cycle)) {
					return false;
				}
			}
		}
		return true;
	}

	private static boolean circleSearch(String srcdir, Map<String, Set<String>> srcdir2sourcedirs, List<String> visited, List<String> exited, List<String> cycle) {
		boolean res = false;
		visited.add(srcdir);
		cycle.add(srcdir);
		Set<String> sourcedirs = srcdir2sourcedirs.get(srcdir);
		if (sourcedirs != null) {
			for (Iterator<String> iter = sourcedirs.iterator(); iter.hasNext();) {
				String src = iter.next();
				if (!visited.contains(src)) {
					res = circleSearch(src, srcdir2sourcedirs, visited, exited, cycle);
				} else if (!exited.contains(src)) {
					res = true;
				}
				if (res) {
					break;
				}
			}
		}
		if (!res) {
			cycle.clear();
		}
		exited.add(srcdir);
		return res;
	}
}
