/*******************************************************************************
 *  Copyright (c) 2017 SSI Schaefer IT Solutions GmbH 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:
 *      SSI Schaefer IT Solutions GmbH
 *******************************************************************************/
package org.eclipse.tea.library.build.model;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
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 org.eclipse.core.resources.IResource;
import org.eclipse.tea.library.build.jar.JarManager;
import org.eclipse.tea.library.build.jar.ZipExec;
import org.eclipse.tea.library.build.jar.ZipExecFactory;
import org.eclipse.tea.library.build.jar.ZipExecPart;
import org.eclipse.tea.library.build.util.FileUtils;

/**
 * Provides information about building a RCP plugin.
 */
public class PluginBuild extends BundleBuild<PluginData> implements Comparable<PluginBuild> {

	protected Set<PluginBuild> sourceDependencies;
	protected Set<MavenExternalJarBuild> mavenDependencies;
	protected Set<String> workspaceDependencies;
	protected final Set<PluginBuild> fragments = new TreeSet<>();

	public static final Pattern MAVEN_COORDINATE_PATTERN = Pattern
			.compile("([^: ]+):([^: ]+)(:([^: ]*)(:([^: ]+))?)?:([^: ]+)");

	public PluginBuild(PluginData data) {
		super(data);
	}

	/**
	 * Returns the name of this plugin.
	 */
	public final String getPluginName() {
		return data.getBundleName();
	}

	/**
	 * Returns the bundle directory; {@code null} for a JAR distribution.
	 */
	public final File getPluginDirectory() {
		return data.bundleDir;
	}

	/**
	 * Returns all existing and valid dependencies.
	 */
	public final Collection<PluginBuild> getSourceDependencies() {
		return sourceDependencies;
	}

	public final Collection<MavenExternalJarBuild> getMavenExternalJarDependencies() {
		return mavenDependencies;
	}

	/**
	 * Returns the names of all dependencies which could be found in the
	 * workspace.
	 */
	public final Collection<String> getWorkspaceDependencies() {
		return workspaceDependencies;
	}

	public final Collection<PluginBuild> getFragments() {
		return fragments;
	}

	/**
	 * Compares two plugins by its name.
	 */
	@Override
	public int compareTo(PluginBuild o) {
		return getPluginName().compareTo(o.getPluginName());
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == this) {
			return true;
		}
		if (!(obj instanceof PluginBuild)) {
			return false;
		}
		PluginBuild other = (PluginBuild) obj;
		return getPluginName().equals(other.getPluginName());
	}

	@Override
	public int hashCode() {
		return getPluginName().hashCode();
	}

	@Override
	public String toString() {
		return getPluginName();
	}

	protected void updateDependencies(WorkspaceBuild ws) {
		sourceDependencies = new TreeSet<>();
		workspaceDependencies = new TreeSet<>();
		mavenDependencies = new TreeSet<>();

		for (ParameterValue pv : data.getDependencies()) {
			addSourceDependency(ws, pv.getValue());
		}

		for (ParameterValue pv : data.getMavenDependencies()) {
			addMavenDependency(ws, pv.getValue());
		}

		// check fragments
		ParameterValue fragmentHost = data.getFragmentHost();
		if (fragmentHost != null) {
			PluginBuild host = addSourceDependency(ws, fragmentHost.getValue());
			if (host != null) {
				host.fragments.add(this);
			} else {
				ws.addHostLessFragment(this);
			}
		}
	}

	private void addMavenDependency(WorkspaceBuild ws, String value) {
		// dependency format: "groupId:name:version"
		Matcher matcher = MAVEN_COORDINATE_PATTERN.matcher(value);
		if (matcher.matches()) {
			mavenDependencies.add(new MavenExternalJarBuild(matcher.group(0)));
		}
	}

	private PluginBuild addSourceDependency(WorkspaceBuild ws, String name) {
		PluginBuild pb = ws.sourcePlugins.get(name);
		if (pb != null) {
			sourceDependencies.add(pb);
			workspaceDependencies.add(name);
		} else if (ws.isClosedOrIncomplete(name)) {
			workspaceDependencies.add(name);
		}
		return pb;
	}

	@Override
	public String getJarFileName(String buildVersion) {
		return getPluginName() + '_' + buildVersion + ".jar";
	}

	/**
	 * Find the binary for this plugin. Only valid if {@link #getData()}.
	 * {@link PluginData#isBinary() isBinary()}.
	 *
	 * @return the path to the underlying backing jar file for this binary
	 *         plugin. Never null.
	 * @throws Exception
	 *             in case the file cannot be found.
	 */
	public File getBinaryJarFile() throws Exception {
		if (!data.isBinary()) {
			throw new IllegalStateException(this + " is not binary!");
		}

		for (IResource r : data.getProject().members()) {
			String name = r.getName();
			if (name.startsWith(data.getBundleName()) && name.endsWith(".jar")) {
				return r.getLocation().toFile();
			}
		}
		throw new IllegalStateException(this + " has no binary file even though it is binary?!");
	}

	/**
	 * Creates the JAR file for this plugin.
	 *
	 * @return the path to the generated jar file.
	 */
	@Override
	public File execJarCommands(ZipExecFactory zip, File distDirectory, String buildVersion, JarManager jarManager)
			throws Exception {
		return execJarCommands(zip, distDirectory, buildVersion, true);
	}

	/**
	 * Creates the JAR file for this plugin. If withBinInc is
	 * <code>false</code>, no binary includes will be added to the jar.
	 *
	 * @return the path to the generated jar file.
	 */
	public File execJarCommands(ZipExecFactory zip, File distDirectory, String buildVersion, boolean withBinInc)
			throws Exception {
		final String oldBundleVersion = data.getBundleVersion();
		final File manifest = data.getManifestFile();
		if (oldBundleVersion == null || manifest == null) {
			// simply create the JAR
			return doExecJarCommands(zip, distDirectory, buildVersion, withBinInc);
		}

		// backup the manifest file
		File rootDir = manifest.getParentFile().getParentFile();
		final File backup = new File(rootDir, "__manifest__.bak");
		FileUtils.copyFile(manifest, backup);
		final long timeStamp = manifest.lastModified();

		String[] classPath = data.getClassPath();

		try {
			// create the new manifest
			data.setBundleVersion(buildVersion);

			// TODO: what to do about this? don't want to have it always?
			String[] enhancedCP = new String[classPath.length + (classPath.length == 0 ? 2 : 1)];
			enhancedCP[0] = "external:$com.wamas.fastpatch.root$/" + data.getBundleName();
			if (classPath.length == 0) {
				enhancedCP[1] = ".";
			}
			System.arraycopy(classPath, 0, enhancedCP, 1, classPath.length);
			data.setClassPath(enhancedCP);

			data.writeManifest();
			if (!manifest.setLastModified(timeStamp)) {
				zip.log.debug("cannot set last modified time: " + manifest);
			}

			// create the JAR
			return doExecJarCommands(zip, distDirectory, buildVersion, withBinInc);
		} finally {
			// restore the old manifest
			FileUtils.copyFile(backup, manifest);
			FileUtils.delete(backup);
			data.setBundleVersion(oldBundleVersion);
			data.setClassPath(classPath);
			data.refreshProject();
		}
	}

	public boolean isPreserveBinaryStructure() {
		return Boolean.parseBoolean(data.getSimpleManifestValue("Preserve-Binary-Structure"));
	}

	private File doExecJarCommands(ZipExecFactory zip, File distDirectory, String buildVersion, boolean withBinInc)
			throws Exception {
		final File jarFile = new File(distDirectory, getJarFileName(buildVersion));

		// remove the jar file
		FileUtils.delete(jarFile);

		// update the manifest for binary deployment
		data.updateManifestForBinaryDeployment();

		// create the ZIP executor
		final ZipExec exec = zip.createZipExec();
		exec.setZipFile(jarFile);
		exec.setJarMode(true);

		// run ZIP on 'bin' directories
		Map<String, List<String>> binaryFolders = data.getBinaryFolders();
		String[] binInc = data.getBinaryIncludes();

		for (String inc : binInc) {
			List<String> paths = binaryFolders.get(inc);
			if (paths != null && !paths.isEmpty()) {
				for (String path : paths) {
					File binDir = new File(data.getBundleDir(), path);
					if (binDir.isDirectory() && binDir.list().length > 0) {
						ZipExecPart part = new ZipExecPart();
						if (isPreserveBinaryStructure()) {
							part.sourceDirectory = data.getBundleDir();
							part.relativePaths.add(path);
						} else {
							part.sourceDirectory = binDir;
							part.relativePaths.add(".");
						}
						part.excludeGit = true;

						exec.addPart(part);
					}
				}
			}
		}

		// run ZIP for binary includes
		if (withBinInc) {
			ZipExecPart incPart = new ZipExecPart();
			for (String bin : binInc) {
				// output folders are added above
				if (!binaryFolders.containsKey(bin)) {
					incPart.relativePaths.add(bin);
				}
			}
			if (!incPart.relativePaths.isEmpty()) {
				incPart.sourceDirectory = data.getBundleDir();
				incPart.excludeGit = true;
				exec.addPart(incPart);
			}
		}

		// create the jar file
		try {
			exec.createZip();
		} catch (Exception ex) {
			throw new RuntimeException("Unable to zip plug-in '" + data.getBundleName() + "'", ex);
		}

		return jarFile;
	}

	/**
	 * Calculates the state of the 'unpack' flag (used by features).
	 */
	public boolean needUnpack() {
		// check our special flag
		if (data.manifest.getNeedUnpack()) {
			return true;
		}

		// check the class path
		String[] classPath = data.getClassPath();
		if (classPath == null) {
			return false;
		}
		for (String element : classPath) {
			if (!element.equals(".")) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Creates a self-contained ZIP file for this plugins. The result can be
	 * treated as a 'product' for stand-alone Java applications.
	 *
	 * @param zipFactory
	 *            ZIP factory
	 * @param buildVersion
	 *            build version of the product
	 * @param output
	 *            ZIP file to build
	 */
	public void buildSelfContainedZip(ZipExecFactory zipFactory, String buildVersion, File output) throws Exception {
		File outputDirectory = output.getParentFile();
		File temp = new File(outputDirectory, "zip_" + String.valueOf(System.currentTimeMillis()));
		File libs = new File(temp, getPluginName());

		FileUtils.mkdirs(libs);

		try {
			copyLibsForSelfContainment(zipFactory, libs, buildVersion);

			FileUtils.delete(output);

			ZipExec exec = zipFactory.createZipExec();
			exec.setZipFile(output);

			ZipExecPart part = new ZipExecPart();
			part.sourceDirectory = temp;
			part.relativePaths.add(libs.getName());
			exec.addPart(part);
			exec.createZip();
		} finally {
			FileUtils.deleteDirectory(temp);
		}

	}

	private void copyLibsForSelfContainment(ZipExecFactory zipFactory, File destDir, String buildVersion)
			throws Exception {
		if (data.isBinary()) {
			disruptBinaryJar(zipFactory, destDir);
		} else {
			execJarCommands(zipFactory, destDir, buildVersion, false);
		}
		File pd = getPluginDirectory();

		if (pd != null && pd.exists() && pd.isDirectory()) {
			for (String inc : getData().getBinaryIncludes()) {
				if (".".equals(inc)) {
					continue;
				}

				File binFile = new File(pd, inc);
				if (binFile.exists() && binFile.isFile() && binFile.getName().toLowerCase().endsWith(".jar")) {
					FileUtils.copyFileToDirectory(binFile, destDir);
				}
			}
		}

		for (PluginBuild dep : getSourceDependencies()) {
			dep.copyLibsForSelfContainment(zipFactory, destDir, buildVersion);
		}
	}

	private void disruptBinaryJar(ZipExecFactory zipFactory, File destDir) throws Exception {
		// unpack the binary, remove META-INF, move all jars to destDir, re-pack
		// all remaining
		// files into new jar
		File binFile = getBinaryJarFile();
		File tmp = new File(destDir, binFile.getName() + "_" + System.currentTimeMillis());
		tmp.mkdirs();

		final ZipExec exec = zipFactory.createZipExec();
		exec.unzip(binFile, tmp);
		File meta = new File(tmp, "META-INF");
		if (meta.exists() && meta.isDirectory()) {
			FileUtils.deleteDirectory(meta);
		}

		moveJarsRecursive(tmp, destDir);

		File target = new File(destDir, getPluginName() + "_stripped.jar");

		// now create jar of the "remains"
		FileUtils.delete(target);

		// create the ZIP executor
		exec.setZipFile(target);
		exec.setJarMode(true);

		// run ZIP on the remains of the original jar
		ZipExecPart part = new ZipExecPart();
		part.sourceDirectory = tmp;
		part.relativePaths.add(".");
		part.excludeGit = true;
		exec.addPart(part);
		exec.createZip();

		FileUtils.deleteDirectory(tmp);
	}

	private void moveJarsRecursive(File tmp, File destDir) throws IOException {
		File[] files = tmp.listFiles();
		if (files == null || files.length == 0) {
			return;
		}

		for (File f : files) {
			if (f.isFile() && f.getName().endsWith(".jar")) {
				FileUtils.moveFile(f, new File(destDir, f.getName()));
			}
			if (f.isDirectory()) {
				moveJarsRecursive(f, destDir);
			}
		}
	}
}
