/*******************************************************************************
 * Copyright (c) 2004, 2015 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.tests.session;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.internal.runtime.InternalPlatform;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.tests.session.ProcessController.TimeOutException;

/*
 * Implementation note: vmArguments and eclipseArguments are HashMap (and not
 * just Map) because we are interested in features that are specific to HashMap
 * (is Cloneable, allows null values).
 */
public class Setup implements Cloneable {

	public static final String APPLICATION = "application";

	private static final String ARCH = "arch";

	public static final String CONFIGURATION = "configuration";

	public static final String DATA = "data";

	public static final String DEBUG = "debug";

	private static final int DEFAULT_TIMEOUT = 0;

	public static final String DEV = "dev";

	public static final String INSTALL = "install";

	private static final String NL = "nl";

	private static final String OS = "os";

	public static final String VM = "vm";

	private static final String WS = "ws";

	private static final String PROP_BOOT_DELEGATION = "org.osgi.framework.bootdelegation";

	public static String getDefaultArchOption() {
		return System.getProperty(InternalPlatform.PROP_ARCH);
	}

	public static String getDefaultConfiguration() {
		return System.getProperty(InternalPlatform.PROP_CONFIG_AREA);
	}

	public static String getDefaultDebugOption() {
		return System.getProperty(InternalPlatform.PROP_DEBUG);
	}

	public static String getDefaultDevOption() {
		return System.getProperty(InternalPlatform.PROP_DEV);
	}

	public static String getDefaultInstallLocation() {
		String currentInstall = System.getProperty(InternalPlatform.PROP_INSTALL_AREA);
		if (currentInstall != null) {
			try {
				return new URI(currentInstall).getPath();
			} catch (URISyntaxException e) {
				// nothing to be done
			}
		}
		return null;
	}

	public static String getDefaultInstanceLocation() {
		return new File(System.getProperty("java.io.tmpdir"), "workspace").toString();
	}

	public static String getDefaultNLOption() {
		return System.getProperty(InternalPlatform.PROP_NL);
	}

	public static String getDefaultOSOption() {
		return System.getProperty(InternalPlatform.PROP_OS);
	}

	/**
	 * Creates a setup containing default settings. The default settings will
	 * vary depending on the running environment.
	 *
	 * @see #getDefaultConfiguration()
	 * @see #getDefaultDebugOption()
	 * @see #getDefaultDevOption()
	 * @see #getDefaultInstallLocation()
	 * @see #getDefaultInstanceLocation()
	 * @see #getDefaultVMLocation()
	 * @return a setup with all default settings
	 */
	static Setup getDefaultSetup(SetupManager manager) {
		Setup defaultSetup = new Setup(manager);
		// see bug 93343
		defaultSetup.setSystemProperty(PROP_BOOT_DELEGATION, System.getProperty(PROP_BOOT_DELEGATION));
		defaultSetup.setSystemProperty(InternalPlatform.PROP_CONSOLE_LOG, System.getProperty(InternalPlatform.PROP_CONSOLE_LOG, "true"));
		if (Setup.getDefaultVMLocation() != null) {
			defaultSetup.setEclipseArgument(VM, Setup.getDefaultVMLocation());
		}
		if (Setup.getDefaultConfiguration() != null) {
			defaultSetup.setEclipseArgument(CONFIGURATION, Setup.getDefaultConfiguration());
		}
		if (Setup.getDefaultDebugOption() != null) {
			defaultSetup.setSystemProperty(InternalPlatform.PROP_DEBUG, Setup.getDefaultDebugOption());
		}
		if (Setup.getDefaultDevOption() != null) {
			defaultSetup.setEclipseArgument(DEV, Setup.getDefaultDevOption());
		}
		if (Setup.getDefaultInstallLocation() != null) {
			defaultSetup.setEclipseArgument(INSTALL, Setup.getDefaultInstallLocation());
		}
		if (Setup.getDefaultInstanceLocation() != null) {
			defaultSetup.setEclipseArgument(DATA, Setup.getDefaultInstanceLocation());
		}
		if (Setup.getDefaultArchOption() != null) {
			defaultSetup.setEclipseArgument(ARCH, Setup.getDefaultArchOption());
		}
		String defaultOS = Setup.getDefaultOSOption();
		if (defaultOS != null) {
			defaultSetup.setEclipseArgument(OS, defaultOS);
			if (Platform.OS_MACOSX.equals(defaultOS)) {
				// see bug 98508
				defaultSetup.setVMArgument("XstartOnFirstThread", "");
			}
		}
		if (Setup.getDefaultWSOption() != null) {
			defaultSetup.setEclipseArgument(WS, Setup.getDefaultWSOption());
		}
		if (Setup.getDefaultNLOption() != null) {
			defaultSetup.setEclipseArgument(NL, Setup.getDefaultNLOption());
		}
		defaultSetup.setTimeout(DEFAULT_TIMEOUT);
		return defaultSetup;
	}

	public static String getDefaultVMLocation() {
		String javaVM = System.getProperty("eclipse.vm");
		if (javaVM != null) {
			return javaVM;
		}
		javaVM = System.getProperty("java.home");
		if (javaVM == null) {
			return null;
		}
		// XXX: this is a hack and will not work with some VMs...
		return new File(new File(javaVM, "bin"), "java").toString();
	}

	public static String getDefaultWSOption() {
		return System.getProperty(InternalPlatform.PROP_WS);
	}

	private String[] baseSetups;

	private HashMap<String, String> eclipseArguments = new HashMap<>();

	private String id;

	private SetupManager manager;

	private String name;

	private String[] requiredSets;

	private HashMap<String, String> systemProperties = new HashMap<>();

	private int timeout;

	private HashMap<String, String> vmArguments = new HashMap<>();

	public Setup(SetupManager manager) {
		this.manager = manager;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.lang.Object#clone()
	 */
	@Override
	public Object clone() {
		Setup clone = null;
		try {
			clone = (Setup) super.clone();
			// ensure we don't end up sharing references to mutable objects
			clone.eclipseArguments = new HashMap<>(eclipseArguments);
			clone.vmArguments = new HashMap<>(vmArguments);
			clone.systemProperties = new HashMap<>(systemProperties);
		} catch (CloneNotSupportedException e) {
			// just does not happen: we do implement Cloneable
		}
		return clone;
	}

	private void fillClassPath(List<String> params) {
		if (vmArguments.containsKey("cp") || vmArguments.containsKey("classpath")) {
			// classpath was specified as VM argument
			return;
		}
		String inheritedClassPath = System.getProperty("java.class.path");
		if (inheritedClassPath == null) {
			String installLocation = getEclipseArgument(INSTALL);
			if (installLocation == null) {
				throw new IllegalStateException("Classpath could not be computed");
			}
			inheritedClassPath = new File(installLocation, "startup.jar").toString();
		}
		params.add("-classpath");
		params.add(inheritedClassPath);
	}

	public void fillCommandLine(List<String> commandLine) {
		String vmLocation = getEclipseArgument(VM);
		if (vmLocation == null) {
			throw new IllegalStateException("VM location not set");
		}
		commandLine.add(vmLocation);
		fillClassPath(commandLine);
		fillVMArgs(commandLine);
		fillSystemProperties(commandLine);
		commandLine.add("org.eclipse.core.launcher.Main");
		fillEclipseArgs(commandLine);
	}

	private void fillEclipseArgs(List<String> params) {
		for (Entry<String, String> entry : eclipseArguments.entrySet()) {
			params.add('-' + entry.getKey());
			if (entry.getValue() != null && entry.getValue().length() > 0) {
				params.add(entry.getValue());
			}
		}
	}

	private void fillSystemProperties(List<String> command) {
		for (Entry<String, String> entry : systemProperties.entrySet()) {
			// null-valued properties are ignored
			if (entry.getValue() == null) {
				continue;
			}
			StringBuffer property = new StringBuffer("-D");
			property.append(entry.getKey());
			if (entry.getValue().length() > 0) {
				property.append('=');
				property.append(entry.getValue());
			}
			command.add(property.toString());
		}
	}

	private void fillVMArgs(List<String> params) {
		for (Entry<String, String> entry : vmArguments.entrySet()) {
			params.add('-' + entry.getKey());
			if (entry.getValue() != null && entry.getValue().length() > 0) {
				params.add(entry.getValue());
			}
		}
	}

	String[] getBaseSetups() {
		return baseSetups;
	}

	public String[] getCommandLine() {
		List<String> commandLine = new ArrayList<>();
		fillCommandLine(commandLine);
		return commandLine.toArray(new String[commandLine.size()]);
	}

	public String getEclipseArgsLine() {
		List<String> eclipseArgs = new ArrayList<>();
		fillEclipseArgs(eclipseArgs);
		StringBuffer result = new StringBuffer();
		for (String string : eclipseArgs) {
			result.append(string);
			result.append(' ');
		}
		return result.length() > 0 ? result.substring(0, result.length() - 1) : null;
	}

	public String getEclipseArgument(String key) {
		return eclipseArguments.get(key);
	}

	public Map<String, String> getEclipseArguments() {
		return new HashMap<>(eclipseArguments);
	}

	public String getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	String[] getRequiredSets() {
		return requiredSets;
	}

	public Map<String, String> getSystemProperties() {
		return new HashMap<>(systemProperties);
	}

	public String getSystemPropertiesLine() {
		List<String> sysProperties = new ArrayList<>();
		fillSystemProperties(sysProperties);
		StringBuffer result = new StringBuffer();
		for (String string : sysProperties) {
			result.append(string);
			result.append(' ');
		}
		return result.length() > 0 ? result.substring(0, result.length() - 1) : null;
	}

	public int getTimeout() {
		return timeout;
	}

	public String getVMArgsLine() {
		List<String> vmArgs = new ArrayList<>();
		fillVMArgs(vmArgs);
		StringBuffer result = new StringBuffer();
		for (String string : vmArgs) {
			result.append(string);
			result.append(' ');
		}
		return result.length() > 0 ? result.substring(0, result.length() - 1) : null;
	}

	public String getVMArgument(String key) {
		return vmArguments.get(key);
	}

	public Map<String, String> getVMArguments() {
		return new HashMap<>(vmArguments);
	}

	public boolean isA(String baseOptionSet) {
		if (baseOptionSet.equals(id)) {
			return true;
		}
		if (baseSetups == null) {
			return false;
		}
		for (String baseSetup : baseSetups) {
			Setup base = manager.getSetup(baseSetup);
			if (base != null && base.isA(baseOptionSet)) {
				return true;
			}
		}
		return false;
	}

	public boolean isSatisfied(String[] availableSets) {
		for (String requiredSet : requiredSets) {
			boolean satisfied = false;
			for (int j = 0; !satisfied && j < availableSets.length; j++) {
				Setup available = manager.getSetup(availableSets[j]);
				if (available != null && available.isA(requiredSet)) {
					satisfied = true;
				}
			}
			if (!satisfied) {
				return false;
			}
		}
		return true;
	}

	public void merge(Setup variation) {
		eclipseArguments.putAll(variation.eclipseArguments);
		vmArguments.putAll(variation.vmArguments);
		systemProperties.putAll(variation.systemProperties);
	}

	public int run() throws InterruptedException, IOException, TimeOutException {
		if (SetupManager.inDebugMode()) {
			System.out.print("Command line: ");
			System.out.println(toCommandLineString());
		}
		ProcessController process = new ProcessController(getTimeout(), getCommandLine());
		process.forwardErrorOutput(System.err);
		process.forwardOutput(System.out);
		//if necessary to interact with the spawned process, this would have
		// to be done
		//process.forwardInput(System.in);
		return process.execute();
	}

	void setBaseSetups(String[] baseSetups) {
		this.baseSetups = baseSetups;
	}

	public void setEclipseArgument(String key, String value) {
		if (value == null) {
			eclipseArguments.remove(key);
		} else {
			eclipseArguments.put(key, value);
		}
	}

	public void setEclipseArguments(Map<String, String> newArguments) {
		if (newArguments == null) {
			eclipseArguments.clear();
		} else {
			eclipseArguments.putAll(newArguments);
		}
	}

	public void setId(String id) {
		this.id = id;
	}

	public void setName(String name) {
		this.name = name;
	}

	void setRequiredSets(String[] requiredSets) {
		this.requiredSets = requiredSets;
	}

	public void setSystemProperties(Map<String, String> newProperties) {
		if (newProperties == null) {
			systemProperties.clear();
		} else {
			systemProperties.putAll(newProperties);
		}
	}

	public void setSystemProperty(String key, String value) {
		if (value == null) {
			systemProperties.remove(key);
		} else {
			systemProperties.put(key, value);
		}
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	public void setVMArgument(String key, String value) {
		if (value == null) {
			vmArguments.remove(key);
		} else {
			vmArguments.put(key, value);
		}
	}

	public void setVMArguments(Map<String, String> newArguments) {
		if (newArguments == null) {
			vmArguments.clear();
		} else {
			vmArguments.putAll(newArguments);
		}
	}

	public String toCommandLineString() {
		String[] commandLine = getCommandLine();
		StringBuffer result = new StringBuffer();
		result.append("[\n");
		for (String element : commandLine) {
			result.append('\t');
			result.append(element);
			result.append('\n');
		}
		result.append(']');
		return result.toString();
	}

	@Override
	public String toString() {
		StringBuffer result = new StringBuffer();
		if (id != null || name != null) {
			if (id != null) {
				result.append(id);
				result.append(' ');
			}
			if (name != null) {
				if (name != null) {
					result.append("(");
					result.append(name);
					result.append(") ");
				}
			}
			result.append("= ");
		}
		result.append("[");
		result.append("\n\teclipseArguments: ");
		result.append(eclipseArguments);
		result.append("\n\tvmArguments: ");
		result.append(vmArguments);
		result.append("\n\tsystemProperties: ");
		result.append(systemProperties);
		result.append("\n]");
		return result.toString();
	}
}
