/*******************************************************************************
 * Copyright (c) 2006, 2007 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 - Initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.jarprocessor;

import java.io.File;
import java.io.IOException;
import java.util.*;

public class PackStep extends CommandStep {

	protected static String packCommand = null;
	private static Boolean canPack = null;

	private String arguments = null;
	private Set exclusions = Collections.EMPTY_SET;

	public static boolean canPack() {
		if (canPack != null)
			return canPack.booleanValue();

		String[] locations = Utils.getPack200Commands("pack200"); //$NON-NLS-1$
		if (locations == null) {
			canPack = Boolean.FALSE;
			packCommand = null;
			return false;
		}

		int result;
		for (int i = 0; i < locations.length; i++) {
			if (locations[i] == null)
				continue;
			result = execute(new String[] {locations[i], "-V"}); //$NON-NLS-1$
			if (result == 0) {
				packCommand = locations[i];
				canPack = Boolean.TRUE;
				return true;
			}
		}

		canPack = Boolean.FALSE;
		return false;
	}

	public PackStep(Properties options) {
		super(options, null, null, false);
		exclusions = Utils.getPackExclusions(options);
	}

	public PackStep(Properties options, boolean verbose) {
		super(options, null, null, verbose);
		exclusions = Utils.getPackExclusions(options);
	}

	public String recursionEffect(String entryName) {
		if (canPack() && entryName.endsWith(".jar") && !exclusions.contains(entryName)) { //$NON-NLS-1$
			return entryName + Utils.PACKED_SUFFIX;
		}
		return null;
	}

	public File preProcess(File input, File workingDirectory, List containers) {
		return null;
	}

	public File postProcess(File input, File workingDirectory, List containers) {
		if (canPack() && packCommand != null) {
			Properties inf = Utils.getEclipseInf(input, verbose);
			if (!shouldPack(input, containers, inf))
				return null;
			File outputFile = new File(workingDirectory, input.getName() + Utils.PACKED_SUFFIX);
			try {
				String[] cmd = getCommand(input, outputFile, inf, containers);
				int result = execute(cmd, verbose);
				if (result != 0 && verbose)
					System.out.println("Error: " + result + " was returned from command: " + Utils.concat(cmd)); //$NON-NLS-1$ //$NON-NLS-2$
			} catch (IOException e) {
				if (verbose)
					e.printStackTrace();
				return null;
			}
			return outputFile;
		}
		return null;
	}

	protected boolean shouldPack(File input, List containers, Properties inf) {
		//1: exclude by containers
		// innermost jar is first on the list, it can override outer jars
		for (Iterator iterator = containers.iterator(); iterator.hasNext();) {
			Properties container = (Properties) iterator.next();
			if (container.containsKey(Utils.MARK_EXCLUDE_CHILDREN_PACK)) {
				if (Boolean.valueOf(container.getProperty(Utils.MARK_EXCLUDE_CHILDREN_PACK)).booleanValue()) {
					if (verbose)
						System.out.println(input.getName() + " is excluded from pack200 by its containers.");
					return false;
				}
				break;
			}
		}

		//2: excluded by self
		if (inf != null && inf.containsKey(Utils.MARK_EXCLUDE_PACK) && Boolean.valueOf(inf.getProperty(Utils.MARK_EXCLUDE_PACK)).booleanValue()) {
			if (verbose)
				System.out.println("Excluding " + input.getName() + " from " + getStepName()); //$NON-NLS-1$ //$NON-NLS-2$
			return false;
		}

		return true;
	}

	protected String[] getCommand(File input, File outputFile, Properties inf, List containers) throws IOException {
		String[] cmd = null;
		String arguments = getArguments(input, inf, containers);
		if (arguments != null && arguments.length() > 0) {
			String[] args = Utils.toStringArray(arguments, ","); //$NON-NLS-1$
			cmd = new String[3 + args.length];
			cmd[0] = packCommand;
			System.arraycopy(args, 0, cmd, 1, args.length);
			cmd[cmd.length - 2] = outputFile.getCanonicalPath();
			cmd[cmd.length - 1] = input.getCanonicalPath();
		} else {
			cmd = new String[] {packCommand, outputFile.getCanonicalPath(), input.getCanonicalPath()};
		}
		return cmd;
	}

	protected String getArguments(File input, Properties inf, List containers) {
		if (arguments != null)
			return arguments;
		//1: Explicitly marked in our .inf file
		if (inf != null && inf.containsKey(Utils.PACK_ARGS)) {
			arguments = inf.getProperty(Utils.PACK_ARGS);
			return arguments;
		}

		//2: Defaults set in one of our containing jars
		for (Iterator iterator = containers.iterator(); iterator.hasNext();) {
			Properties container = (Properties) iterator.next();
			if (container.containsKey(Utils.DEFAULT_PACK_ARGS)) {
				arguments = container.getProperty(Utils.DEFAULT_PACK_ARGS);
				return arguments;
			}
		}

		//3: Set by name in outside pack.properties file
		Properties options = getOptions();
		String argsKey = input.getName() + Utils.PACK_ARGS_SUFFIX;
		if (options.containsKey(argsKey)) {
			arguments = options.getProperty(argsKey);
			return arguments;
		}

		//4: Set by default in outside pack.properties file
		if (options.containsKey(Utils.DEFAULT_PACK_ARGS)) {
			arguments = options.getProperty(Utils.DEFAULT_PACK_ARGS);
			return arguments;
		}

		if (arguments == null)
			arguments = "";
		return arguments;
	}

	public String getStepName() {
		return "Pack"; //$NON-NLS-1$
	}

	public void adjustInf(File input, Properties inf, List containers) {
		if (input == null || inf == null)
			return;

		//don't be verbose to check if we should mark the inf
		boolean v = verbose;
		verbose = false;
		if (!shouldPack(input, containers, inf)) {
			verbose = v;
			return;
		}
		verbose = v;

		//mark as conditioned
		inf.put(Utils.MARK_PROPERTY, "true"); //$NON-NLS-1$

		//record arguments used
		String arguments = inf.getProperty(Utils.PACK_ARGS);
		if (arguments == null) {
			arguments = getArguments(input, inf, containers);
			if (arguments != null && arguments.length() > 0)
				inf.put(Utils.PACK_ARGS, arguments);
		}
	}
}
