/*******************************************************************************
 * Copyright (c) 2009 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 implementation and ideas 
 ******************************************************************************/
package org.eclipse.equinox.p2.cudf;

import java.io.*;
import java.util.*;
import org.eclipse.equinox.p2.cudf.metadata.*;
import org.eclipse.equinox.p2.cudf.query.*;
import org.eclipse.equinox.p2.cudf.solver.ProfileChangeRequest;

public class Parser {

	private static final boolean FORCE_QUERY = true; //TO SET TO FALSE FOR COMPETITION
	private static final boolean DEBUG = false; //TO SET TO FALSE FOR COMPETITION
	private static final boolean TIMING = true; //TO SET TO FALSE FOR COMPETITION
	private InstallableUnit currentIU = null;
	private ProfileChangeRequest currentRequest = null;
	private List allIUs = new ArrayList();
	private QueryableArray query = null;
	private List preInstalled = new ArrayList(10000);
	private List keepRequests = new ArrayList();
	private List currentKeepRequests = new ArrayList();

	class Tuple {
		String name;
		String version;
		String operator;
		Set extraData;

		Tuple(String line) {
			String[] tuple = new String[3];
			int i = 0;
			for (StringTokenizer iter = new StringTokenizer(line, " \t"); iter.hasMoreTokens(); i++)
				tuple[i] = iter.nextToken();
			name = tuple[0];
			operator = tuple[1];
			version = tuple[2];
		}
	}

	public ProfileChangeRequest parse(File file) {
		return parse(file, false, null);
	}

	public ProfileChangeRequest parse(File file, boolean includeRecommends, String sumProperty) {
		try {
			return parse(new FileInputStream(file), includeRecommends, sumProperty);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		}
	}

	public ProfileChangeRequest parse(InputStream stream) {
		return parse(stream, false, null);
	}

	public ProfileChangeRequest parse(InputStream stream, String sumProperty) {
		return parse(stream, false, sumProperty);
	}

	public ProfileChangeRequest parse(InputStream stream, boolean includeRecommends, String sumProperty) {
		long start;
		if (TIMING)
			start = System.currentTimeMillis();
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
			String next = reader.readLine();
			while (true) {

				// look-ahead to check for line continuation
				String line = next;
				for (next = reader.readLine(); next != null && next.length() > 1 && next.charAt(0) == ' '; next = reader.readLine()) {
					line = line + next.substring(1);
				}

				// terminating condition of the loop... reached the end of the file
				if (line == null) {
					validateAndAddIU();
					break;
				}

				// end of stanza
				if (line.trim().length() == 0) {
					validateAndAddIU();
					continue;
				}

				// preamble stanza
				if (line.startsWith("#") || line.startsWith("preamble: ") || line.startsWith("property: ") || line.startsWith("univ-checksum: ")) {
					// ignore
				}

				// request stanza
				else if (line.startsWith("request: ")) {
					handleRequest(line);
				} else if (line.startsWith("install: ")) {
					handleInstall(line);
				} else if (line.startsWith("upgrade: ")) {
					handleUpgrade(line);
				} else if (line.startsWith("remove: ")) {
					handleRemove(line);
				}

				// package stanza
				else if (line.startsWith("package: ")) {
					handlePackage(line);
				} else if (line.startsWith("version: ")) {
					handleVersion(line);
				} else if (line.startsWith("installed: ")) {
					handleInstalled(line);
				} else if (line.startsWith("depends: ")) {
					handleDepends(line);
				} else if (line.startsWith("conflicts: ")) {
					handleConflicts(line);
				} else if (line.startsWith("provides: ")) {
					handleProvides(line);
				} else if (line.startsWith("expected: ")) {
					handleExpected(line);
				} else if (line.startsWith("recommends: ") && includeRecommends) {
					handleRecommends(line);
				} else if (line.startsWith("keep: ")) {
					handleKeep(line);
				} else if (sumProperty != null && line.startsWith(sumProperty)) {
					handleSumProperty(line, sumProperty);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null)
				try {
					reader.close();
				} catch (IOException e) {
					// ignore
				}
		}
		if (TIMING)
			Log.println("Time to parse:" + (System.currentTimeMillis() - start));
		if (DEBUG)
			for (Iterator iter = allIUs.iterator(); iter.hasNext();)
				debug((InstallableUnit) iter.next());
		if (FORCE_QUERY) {
			if (query == null)
				initializeQueryableArray();
			if (currentRequest == null)
				currentRequest = new ProfileChangeRequest(query);
		}
		debug(currentRequest);
		return currentRequest;
	}

	private void handleSumProperty(String line, String sumProperty) {
		currentIU.setSumProperty(line.substring(sumProperty.length() + 1).trim());
		System.out.printf("**** handling property %s with value %s for IU %s\n", sumProperty, currentIU.getSumProperty(), currentIU.getId());
	}

	private void handleKeep(String line) {
		line = line.substring("keep: ".length());
		if (line.contains("version")) {
			currentKeepRequests.add(new RequiredCapability(currentIU.getId(), new VersionRange(currentIU.getVersion()), false));
			return;
		}
		if (line.contains("package")) {
			currentKeepRequests.add(new RequiredCapability(currentIU.getId(), VersionRange.emptyRange, false));
			return;
		}
		if (line.contains("none"))
			return;
		if (line.contains("feature")) {
			IProvidedCapability[] caps = currentIU.getProvidedCapabilities();
			for (int i = 0; i < caps.length; i++) {
				if (!caps[i].getName().equals(currentIU.getId()))
					currentKeepRequests.add(new RequiredCapability(caps[i].getName(), caps[i].getVersion(), false));
			}
		}

	}

	private void handleExpected(String line) {
		currentRequest.setExpected(Integer.decode(line.substring("expected: ".length()).trim()).intValue());
	}

	/*
	 * Ensure that the current IU that we have been building is validate and if so, then
	 * add it to our collected list of all converted IUs from the file.
	 */
	private void validateAndAddIU() {
		if (currentIU == null)
			return;
		// For a package stanza, the id and version are the only mandatory elements
		if (currentIU.getId() == null)
			throw new IllegalStateException("Malformed \'package\' stanza. No package element found.");
		if (currentIU.getVersion() == null)
			throw new IllegalStateException("Malformed \'package\' stanza. Package " + currentIU.getId() + " does not have a version.");
		if (currentIU.getProvidedCapabilities().length == 0) {
			currentIU.setCapabilities(new IProvidedCapability[] {new ProvidedCapability(currentIU.getId(), new VersionRange(currentIU.getVersion(), true, currentIU.getVersion(), true))});
		}
		if (currentIU.isInstalled()) {
			keepRequests.addAll(currentKeepRequests);
		}
		allIUs.add(currentIU);
		// reset to be ready for the next stanza
		currentIU = null;
		currentKeepRequests.clear();
	}

	private void handleInstalled(String line) {
		String value = line.substring("installed: ".length());
		if (value.length() != 0) {
			if (DEBUG)
				if (!Boolean.valueOf(value).booleanValue()) {
					System.err.println("Unexcepted value for installed.");
					return;
				}
			currentIU.setInstalled(true);
			preInstalled.add(new RequiredCapability(currentIU.getId(), new VersionRange(currentIU.getVersion()), true));
		}
	}

	private void handleInstall(String line) {
		line = line.substring("install: ".length());
		List installRequest = createRequires(line, true, false, true);
		for (Iterator iterator = installRequest.iterator(); iterator.hasNext();) {
			currentRequest.addInstallableUnit((IRequiredCapability) iterator.next());
		}
		return;
	}

	private void handleRequest(String line) {
		initializeQueryableArray();
		currentRequest = new ProfileChangeRequest(query);
		currentRequest.setPreInstalledIUs(preInstalled);
		currentRequest.setContrainstFromKeep(keepRequests);
	}

	private void handleRemove(String line) {
		line = line.substring("remove: ".length());
		List removeRequest = createRequires(line, true, false, true);
		for (Iterator iterator = removeRequest.iterator(); iterator.hasNext();) {
			currentRequest.removeInstallableUnit((IRequiredCapability) iterator.next());
		}
		return;
	}

	private void initializeQueryableArray() {
		query = new QueryableArray((InstallableUnit[]) allIUs.toArray(new InstallableUnit[allIUs.size()]));
	}

	private void handleUpgrade(String line) {
		line = line.substring("upgrade: ".length());
		List updateRequest = createRequires(line, true, false, true);
		for (Iterator iterator = updateRequest.iterator(); iterator.hasNext();) {
			IRequiredCapability requirement = (IRequiredCapability) iterator.next();
			currentRequest.upgradeInstallableUnit(requirement);

			//Add a requirement forcing uniqueness of the upgraded package in the resulting solution
			currentRequest.upgradeInstallableUnit(new RequiredCapability(requirement.getName(), VersionRange.emptyRange, 1));

			//Add a requirement forcing the solution to be greater or equal to the highest installed version
			requirement = getHighestInstalledVersion(requirement);
			if (requirement != null)
				currentRequest.upgradeInstallableUnit(requirement);
		}
		return;
	}

	private IRequiredCapability getHighestInstalledVersion(IRequiredCapability req) {
		Version highestVersion = null;
		Collector c = query.query(new CapabilityQuery(req), new Collector(), null);
		for (Iterator iterator = c.iterator(); iterator.hasNext();) {
			InstallableUnit candidate = (InstallableUnit) iterator.next();
			if (!candidate.isInstalled())
				continue;
			if (candidate.getId().equals(req.getName())) {
				if (highestVersion == null || candidate.getVersion().getMajor() > highestVersion.getMajor())
					highestVersion = candidate.getVersion();
			} else {
				//Requesting the upgrade of a virtual package
				IProvidedCapability[] prov = candidate.getProvidedCapabilities();
				for (int i = 0; i < prov.length; i++) {
					if (prov[i].getVersion().equals(VersionRange.emptyRange))
						continue;
					if (prov[i].getName().equals(req.getName()) && (highestVersion == null || prov[i].getVersion().getMinimum().getMajor() > highestVersion.getMajor()))
						highestVersion = prov[i].getVersion().getMinimum();
				}
			}
		}
		if (highestVersion == null)
			return null;
		return new RequiredCapability(req.getName(), new VersionRange(highestVersion, true, Version.maxVersion, true));
	}

	/*
	 * Convert the version string to a version object and set it on the IU
	 */
	private void handleVersion(String line) {
		currentIU.setVersion(new Version(cudfPosintToInt(line.substring("version: ".length()))));
	}

	private String cudfPosintToInt(String posint) {
		if (posint.startsWith("+")) {
			return posint.substring(1).trim();
		}
		return posint.trim();
	}

	private void handleDepends(String line) {
		mergeRequirements(createRequires(line.substring("depends: ".length()), true, false, true));
	}

	private void handleRecommends(String line) {
		mergeRequirements(createRequires(line.substring("recommends: ".length()), true, true, true));
	}

	/*
	 * Conflicts are like depends except NOT'd.
	 */
	private void handleConflicts(String line) {
		List reqs = createRequires(line.substring("conflicts: ".length()), false, false, false);
		List conflicts = new ArrayList();
		for (Iterator iter = reqs.iterator(); iter.hasNext();) {
			IRequiredCapability req = (IRequiredCapability) iter.next();
			if (currentIU.getId().equals(req.getName()) && req.getRange().equals(VersionRange.emptyRange)) {
				currentIU.setSingleton(true);
			} else {
				conflicts.add(new NotRequirement(req));
			}
		}
		mergeRequirements(conflicts);
	}

	/*
	 * Set the given list of requirements on teh current IU. Merge if necessary.
	 */
	private void mergeRequirements(List requirements) {
		if (currentIU.getRequiredCapabilities() != null) {
			IRequiredCapability[] current = currentIU.getRequiredCapabilities();
			for (int i = 0; i < current.length; i++)
				requirements.add(current[i]);
		}
		currentIU.setRequiredCapabilities((IRequiredCapability[]) requirements.toArray(new IRequiredCapability[requirements.size()]));
	}

	/*
	 * Returns a map where the key is the package name and the value is a Tuple.
	 * If there is more than one entry for a particular package, the extra entries are included
	 * in the extraData field of the Tuple. 
	 */
	private List createPackageList(String line) {
		StringTokenizer tokenizer = new StringTokenizer(line, ",");
		List result = new ArrayList(tokenizer.countTokens());
		while (tokenizer.hasMoreElements()) {
			result.add(new Tuple(tokenizer.nextToken()));
		}
		return result;
	}

	private List createRequires(String line, boolean expandNotEquals, boolean optional, boolean dependency) {
		ArrayList ands = new ArrayList();
		StringTokenizer s = new StringTokenizer(line, ",");
		String subtoken;
		while (s.hasMoreElements()) {
			StringTokenizer subTokenizer = new StringTokenizer(s.nextToken(), "|");
			if (subTokenizer.countTokens() == 1) { //This token does not contain a |.
				subtoken = subTokenizer.nextToken().trim();
				// FIXME should be handled differently in depends and conflicts.
				if ("true!".equals(subtoken)) {
					if (dependency)
						continue;
					throw new RuntimeException("Cannot have true! in a conflict!!!!!");
				}
				if ("false!".equals(subtoken)) {
					if (!dependency)
						continue;
					throw new RuntimeException("Cannot have false! in a dependency!!!!!");
				}
				Object o = createRequire(subtoken, expandNotEquals, optional);
				if (o instanceof IRequiredCapability)
					ands.add(o);
				else
					ands.addAll((Collection) o);
				continue;
			}

			IRequiredCapability[] ors = new RequiredCapability[subTokenizer.countTokens()];
			int i = 0;
			while (subTokenizer.hasMoreElements()) {
				ors[i++] = (IRequiredCapability) createRequire(subTokenizer.nextToken(), expandNotEquals, optional);
			}
			ands.add(new ORRequirement(ors, optional));
		}
		return ands;
	}

	private Object createRequire(String nextToken, boolean expandNotEquals, boolean optional) {
		//>, >=, =, <, <=, !=
		StringTokenizer expressionTokens = new StringTokenizer(nextToken.trim(), ">=!<", true);
		int tokenCount = expressionTokens.countTokens();

		if (tokenCount == 1) // a
			return new RequiredCapability(expressionTokens.nextToken().trim(), VersionRange.emptyRange, optional);

		if (tokenCount == 3) // a > 2, a < 2, a = 2
			return new RequiredCapability(expressionTokens.nextToken().trim(), createRange3(expressionTokens.nextToken(), expressionTokens.nextToken()), optional);

		if (tokenCount == 4) { //a >= 2, a <=2, a != 2
			String id = expressionTokens.nextToken().trim();
			String signFirstChar = expressionTokens.nextToken();
			expressionTokens.nextToken();//skip second char of the sign
			String version = expressionTokens.nextToken().trim();
			if (!("!".equals(signFirstChar))) // a >= 2 a <= 2
				return new RequiredCapability(id, createRange4(signFirstChar, version), optional);

			//a != 2
			if (expandNotEquals) {
				return new ORRequirement(new IRequiredCapability[] {new RequiredCapability(id, createRange3("<", version), optional), new RequiredCapability(id, createRange3(">", version), optional)}, optional);
			}
			ArrayList res = new ArrayList(2);
			res.add(new RequiredCapability(id, createRange3("<", version), optional));
			res.add(new RequiredCapability(id, createRange3(">", version), optional));
			return res;
		}
		return null;
	}

	private VersionRange createRange3(String sign, String versionAsString) {
		int version = Integer.decode(cudfPosintToInt(versionAsString)).intValue();
		sign = sign.trim();
		if (">".equals(sign))
			return new VersionRange(new Version(version), false, Version.maxVersion, false);
		if ("<".equals(sign))
			return new VersionRange(Version.emptyVersion, false, new Version(version), false);
		if ("=".equals(sign))
			return new VersionRange(new Version(version));
		throw new IllegalArgumentException(sign);
	}

	private VersionRange createRange4(String sign, String versionAsString) {
		int version = Integer.decode(cudfPosintToInt(versionAsString)).intValue();
		if (">".equals(sign)) //THIS IS FOR >=
			return new VersionRange(new Version(version), true, Version.maxVersion, false);
		if ("<".equals(sign)) //THIS IS FOR <=
			return new VersionRange(Version.emptyVersion, false, new Version(version), true);
		return null;
	}

	private IProvidedCapability createProvidedCapability(Tuple tuple) {
		Set extraData = tuple.extraData;
		// one constraint so simply return the capability
		if (extraData == null)
			return new ProvidedCapability(tuple.name, createVersionRange(tuple.operator, tuple.version));
		// 2 constraints (e.g. a>=1, a<4) so create a real range like a[1,4)
		if (extraData.size() == 1)
			return new ProvidedCapability(tuple.name, createVersionRange(tuple, (Tuple) extraData.iterator().next()));
		// TODO merge more than 2 requirements (a>2, a<4, a>3)
		return new ProvidedCapability(tuple.name, createVersionRange(tuple.operator, tuple.version));
	}

	/*
	 * Create and return a version range object which merges the 2 given versions and operators.
	 * e.g  a>=1 and a<4 becomes a[1,4)
	 */
	private VersionRange createVersionRange(Tuple t1, Tuple t2) {
		Version one = Version.parseVersion(t1.version);
		Version two = Version.parseVersion(t2.version);
		if (one.compareTo(two) < 0) {
			return new VersionRange(one, include(t1.operator), two, include(t2.operator));
		} else if (one.compareTo(two) == 0) {
			return new VersionRange(one, include(t1.operator), one, include(t1.operator));
		} else if (one.compareTo(two) > 0) {
			return new VersionRange(two, include(t2.operator), one, include(t1.operator));
		}
		// should never reach this. avoid compile error.
		return null;
	}

	/*
	 * Helper method for when we are creating version ranges and calculating "includeMin/Max".
	 */
	private boolean include(String operator) {
		return "=".equals(operator) || "<=".equals(operator) || ">=".equals(operator);
	}

	/*
	 * Create and return a version range based on the given operator and number. Note that != is
	 * handled elsewhere.
	 */
	private VersionRange createVersionRange(String operator, String number) {
		if (operator == null || number == null)
			return VersionRange.emptyRange;
		if ("=".equals(operator))
			return new VersionRange('[' + number + ',' + number + ']');
		if ("<".equals(operator))
			return new VersionRange("[0," + number + ')');
		if (">".equals(operator))
			return new VersionRange('(' + number + ',' + Integer.MAX_VALUE + ']');
		if ("<=".equals(operator))
			return new VersionRange("[0," + number + ']');
		if (">=".equals(operator))
			return new VersionRange('[' + number + ',' + Integer.MAX_VALUE + ']');
		return VersionRange.emptyRange;
	}

	// package name matches: "^[a-zA-Z0-9+./@()%-]+$"
	private void handlePackage(String readLine) {
		currentIU = new InstallableUnit();
		currentIU.setId(readLine.substring("package: ".length()));
	}

	private void handleProvides(String line) {
		line = line.substring("provides: ".length());
		List pkgs = createPackageList(line);
		IProvidedCapability[] providedCapabilities = new ProvidedCapability[pkgs.size() + 1];
		int i = 0;
		for (Iterator iter = pkgs.iterator(); iter.hasNext();) {
			providedCapabilities[i++] = createProvidedCapability((Tuple) iter.next());
		}
		providedCapabilities[i++] = new ProvidedCapability(currentIU.getId(), new VersionRange(currentIU.getVersion(), true, currentIU.getVersion(), true));
		currentIU.setCapabilities(providedCapabilities);
	}

	//	// copied from ProfileSynchronizer
	private void debug(ProfileChangeRequest request) {
		if (!DEBUG || request == null)
			return;
		//		Log.println("\nProfile Change Request:");
		//		InstallableUnit[] toAdd = request.getAddedInstallableUnit();
		//		if (toAdd == null || toAdd.length == 0) {
		//			Log.println("No installable units to add.");
		//		} else {
		//			for (int i = 0; i < toAdd.length; i++)
		//				Log.println("Adding IU: " + toAdd[i].getId() + ' ' + toAdd[i].getVersion());
		//		}
		//		Map propsToAdd = request.getInstallableUnitProfilePropertiesToAdd();
		//		if (propsToAdd == null || propsToAdd.isEmpty()) {
		//			Log.println("No IU properties to add.");
		//		} else {
		//			for (Iterator iter = propsToAdd.keySet().iterator(); iter.hasNext();) {
		//				Object key = iter.next();
		//				Log.println("Adding IU property: " + key + "->" + propsToAdd.get(key));
		//			}
		//		}
		//
		//		InstallableUnit[] toRemove = request.getRemovedInstallableUnits();
		//		if (toRemove == null || toRemove.length == 0) {
		//			Log.println("No installable units to remove.");
		//		} else {
		//			for (int i = 0; i < toRemove.length; i++)
		//				Log.println("Removing IU: " + toRemove[i].getId() + ' ' + toRemove[i].getVersion());
		//		}
		//		Map propsToRemove = request.getInstallableUnitProfilePropertiesToRemove();
		//		if (propsToRemove == null || propsToRemove.isEmpty()) {
		//			Log.println("No IU properties to remove.");
		//		} else {
		//			for (Iterator iter = propsToRemove.keySet().iterator(); iter.hasNext();) {
		//				Object key = iter.next();
		//				Log.println("Removing IU property: " + key + "->" + propsToRemove.get(key));
		//			}
		//		}
	}

	// dump info to console
	private void debug(InstallableUnit unit) {
		if (!DEBUG)
			return;
		Log.println("\nInstallableUnit: " + unit.getId());
		Log.println("Version: " + unit.getVersion());
		if (unit.isInstalled())
			Log.println("Installed: true");
		IRequiredCapability[] reqs = unit.getRequiredCapabilities();
		for (int i = 0; i < reqs.length; i++) {
			Log.println("Requirement: " + reqs[i]);
		}
	}

}
