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

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.runtime.Platform;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class SetupManager {
	public class SetupException extends Exception {
		/**
		 * All serializable objects should have a stable serialVersionUID
		 */
		private static final long serialVersionUID = 1L;

		public SetupException(String message, Throwable cause) {
			super(message, cause);
		}

		public SetupException(String message) {
			super(message);
		}
	}

	private static SetupManager instance;
	private static final String SETUP_DEBUG = "setup.debug";
	private static final String SETUP_FILES = "setup.files";
	private static final String SETUP_OPTIONS = "setup.options";
	private static final String SETUP_OVERRIDE_ECLIPSEARGS = "setup.override.eclipseArgs";
	private static final String SETUP_OVERRIDE_SYSTEMPROPERTIES = "setup.override.systemProperties";
	private static final String SETUP_OVERRIDE_VMARGS = "setup.override.vmArgs";
	private String defaultOptionSetIds = "";
	private Map<String, Setup> setupById;
	private Collection<Setup> setups;

	private static boolean contains(Object[] set, Object element) {
		for (Object setElement : set) {
			if (element.equals(setElement)) {
				return true;
			}
		}
		return false;
	}

	public synchronized static SetupManager getInstance() throws SetupException {
		if (instance != null) {
			return instance;
		}
		instance = new SetupManager();
		return instance;
	}

	public static boolean inDebugMode() {
		return Boolean.getBoolean(SETUP_DEBUG);
	}

	public static void main(String[] args) throws Exception {
		SetupManager manager = SetupManager.getInstance();
		System.out.println(manager.getDefaultSetup());
	}

	static String[] parseItems(String string) {
		if (string == null) {
			return new String[0];
		}
		StringTokenizer tokenizer = new StringTokenizer(string, ","); //$NON-NLS-1$
		if (!tokenizer.hasMoreTokens()) {
			return new String[0];
		}
		String first = tokenizer.nextToken().trim();
		if (!tokenizer.hasMoreTokens()) {
			return new String[] {first};
		}
		ArrayList<String> items = new ArrayList<>();
		items.add(first);
		do {
			items.add(tokenizer.nextToken().trim());
		} while (tokenizer.hasMoreTokens());
		return items.toArray(new String[items.size()]);
	}

	protected SetupManager() throws SetupException {
		setups = new ArrayList<>();
		setupById = new HashMap<>();
		try {
			loadSetups();
		} catch (SetupException e) {
			throw e;
		} catch (Exception e) {
			throw new SetupException("Problems initializing SetupManager", e);
		}
	}

	public Setup buildSetup(String[] optionSets) {
		Setup defaultSetup = Setup.getDefaultSetup(this);
		for (Setup customSetup : setups) {
			if ((customSetup.getId() == null || contains(optionSets, customSetup.getId())) && customSetup.isSatisfied(optionSets)) {
				defaultSetup.merge(customSetup);
			}
		}
		defaultSetup.setEclipseArguments(parseOptions(System.getProperty(SETUP_OVERRIDE_ECLIPSEARGS)));
		defaultSetup.setVMArguments(parseOptions(System.getProperty(SETUP_OVERRIDE_VMARGS)));
		defaultSetup.setSystemProperties(parseOptions(System.getProperty(SETUP_OVERRIDE_SYSTEMPROPERTIES)));
		return defaultSetup;
	}

	private String getAttribute(NamedNodeMap attributes, String name) {
		Node selected = attributes.getNamedItem(name);
		return selected == null ? null : selected.getNodeValue();
	}

	private String[] getDefaultOptionSets() {
		return parseItems(System.getProperty(SETUP_OPTIONS, defaultOptionSetIds));
	}

	/**
	 * Returns a brand new setup object configured according to the current
	 * default setup settings.
	 *
	 * @return a new setup object
	 */
	public Setup getDefaultSetup() {
		return buildSetup(getDefaultOptionSets());
	}

	public Setup getSetup(String id) {
		return setupById.get(id);
	}

	private void loadEclipseArgument(Setup newSetup, Element toParse) {
		newSetup.setEclipseArgument(toParse.getAttribute("option"), toParse.getAttribute("value"));
	}

	private void loadProperty(Setup newSetup, Element toParse) {
		newSetup.setSystemProperty(toParse.getAttribute("key"), toParse.getAttribute("value"));
	}

	private void loadSetup(Element markup) {
		NamedNodeMap attributes = markup.getAttributes();
		if (attributes == null) {
			return;
		}
		Setup newSetup = new Setup(this);
		newSetup.setId(getAttribute(attributes, "id"));
		newSetup.setName(getAttribute(attributes, "name"));
		String timeout = getAttribute(attributes, "timeout");
		newSetup.setBaseSetups(parseItems(getAttribute(attributes, "base")));
		newSetup.setRequiredSets(parseItems(getAttribute(attributes, "with")));

		if (timeout != null) {
			newSetup.setTimeout(Integer.parseInt(timeout));
		}
		NodeList children = markup.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node next = children.item(i);
			if (!(next instanceof Element)) {
				continue;
			}
			Element toParse = (Element) next;
			switch (toParse.getTagName()) {
			case "eclipseArg":
				loadEclipseArgument(newSetup, toParse);
				break;
			case "vmArg":
				loadVMArgument(newSetup, toParse);
				break;
			case "systemProperty":
				loadProperty(newSetup, toParse);
				break;
			default:
				break;
			}
		}
		setups.add(newSetup);
		if (newSetup.getId() != null) {
			setupById.put(newSetup.getId(), newSetup);
		}
	}

	private void loadSetups() throws ParserConfigurationException, FactoryConfigurationError, SAXException, IOException, SetupException {
		String setupFilesProperty = System.getProperty(SETUP_FILES);
		boolean defaultLocation = false;
		if (setupFilesProperty == null) {
			setupFilesProperty = "default-setup.xml";
			defaultLocation = true;
		}
		String[] setupFileNames = parseItems(setupFilesProperty);
		File[] setupFiles = new File[setupFileNames.length];
		int found = 0;
		for (int i = 0; i < setupFiles.length; i++) {
			setupFiles[found] = new File(setupFileNames[i]);
			if (!setupFiles[found].isFile()) {
				if (!defaultLocation) {
					// warn if user-provided location does not exist
					System.out.println("No setup files found at '" + setupFiles[i].getAbsolutePath() + "'. ");
				}
				continue;
			}
			found++;
		}
		if (found == 0) {
			if (Platform.isRunning()) {
				// No setup descriptions found, only the default setup will be available
				return;
			}
			// no setup files found, and we are not running in Eclipse...
			throw new SetupException("No setup descriptions found. Ensure you are specifying the path for an existing setup file (e.g. -Dsetup.files=<setup-file-location1>[...,<setup-file-locationN>])");
		}
		DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		for (int fileIndex = 0; fileIndex < found; fileIndex++) {
			Document doc = docBuilder.parse(setupFiles[fileIndex]);
			Element root = doc.getDocumentElement();
			String setupDefaultOptionSets = root.getAttribute("default");
			if (setupDefaultOptionSets != null) {
				defaultOptionSetIds = defaultOptionSetIds == null ? setupDefaultOptionSets : (defaultOptionSetIds + ',' + setupDefaultOptionSets);
			}
			NodeList optionSets = root.getChildNodes();
			for (int i = 0; i < optionSets.getLength(); i++) {
				Node next = optionSets.item(i);
				if (!(next instanceof Element)) {
					continue;
				}
				Element toParse = (Element) next;
				if (!toParse.getTagName().equals("optionSet")) {
					continue;
				}
				loadSetup(toParse);
			}
		}
	}

	private void loadVMArgument(Setup newSetup, Element toParse) {
		newSetup.setVMArgument(toParse.getAttribute("option"), toParse.getAttribute("value"));
	}

	/*
	 * Use a double equal sign to escape and equal to treat it from becoming
	 * a key/value pair
	 */
	private static Map<String, String> parseOptions(String options) {
		if (options == null) {
			return Collections.EMPTY_MAP;
		}
		Map<String, String> result = new HashMap<>();
		StringTokenizer tokenizer = new StringTokenizer(options.trim(), ";");
		while (tokenizer.hasMoreTokens()) {
			String option = tokenizer.nextToken();
			int separatorIndex = option.indexOf('=');
			if (separatorIndex == -1 || separatorIndex == option.length() - 1) { // property with no value defined
				result.put(option, "");
				continue;
			}
			// the 90% case is that we won't have an escaped equals so check to see if we can short-circuit
			if (!option.contains("==")) {
				String key = option.substring(0, separatorIndex);
				String value = option.substring(separatorIndex + 1);
				result.put(key, value);
				continue;
			}
			// otherwise we have an escaped equals somewhere in this option
			int valueStart = -1;
			// strip out the key (first non-escaped equal)
			StringBuilder key = new StringBuilder();
			for (int i = 0; i < option.length(); i++) {
				char c = option.charAt(i);
				// if we don't have an equal sign, then just add it to the key
				if (c != '=') {
					key.append(c);
					continue;
				}
				i++;
				if (i >= option.length()) {
					break;
				}
				char next = option.charAt(i);
				if (next == '=') {
					key.append('=');
					continue;
				}
				// we had a single equal
				valueStart = i;
				break;
			}
			String value = "";
			// now get the value. replace == by =
			if (valueStart > -1) {
				value = option.substring(valueStart).replaceAll("==", "=");
			}
			result.put(key.toString(), value);
		}
		return result;
	}
}
