/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.externaltools.internal.registry;


import java.util.ArrayList;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.RefreshTab;
import org.eclipse.ui.externaltools.internal.model.ExternalToolsPlugin;
import org.eclipse.ui.externaltools.internal.model.IExternalToolConstants;
import org.eclipse.ui.externaltools.internal.ui.ExternalToolsUIMessages;

/**
 * Responsible reading an old external tool format and creating
 * and migrating it to create a new external tool.
 */
public final class ExternalToolMigration {
	/**
	 * Structure to represent a variable definition within a
	 * source string.
	 */
	public static final class VariableDefinition {
		/**
		 * Index in the source text where the variable started
		 * or <code>-1</code> if no valid variable start tag 
		 * identifier found.
		 */
		public int start = -1;
		
		/**
		 * Index in the source text of the character following
		 * the end of the variable or <code>-1</code> if no 
		 * valid variable end tag found.
		 */
		public int end = -1;
		
		/**
		 * The variable's name found in the source text, or
		 * <code>null</code> if no valid variable found.
		 */
		public String name = null;
		
		/**
		 * The variable's argument found in the source text, or
		 * <code>null</code> if no valid variable found or if
		 * the variable did not specify an argument
		 */
		public String argument = null;
		
		/**
		 * Create an initialized variable definition.
		 */
		private VariableDefinition() {
			super();
		}
	}
	
	/**
	 * Variable tag indentifiers
	 */
	private static final String VAR_TAG_START = "${"; //$NON-NLS-1$
	private static final String VAR_TAG_END = "}"; //$NON-NLS-1$
	private static final String VAR_TAG_SEP = ":"; //$NON-NLS-1$	
	
	/**
	 * External tool type for Ant build files (value <code>antBuildType</code>).
	 */
	public static final String TOOL_TYPE_ANT_BUILD = "antBuildType"; //$NON-NLS-1$;
	/**
	 * Ant builder launch configuration type identifier. Ant project builders
	 * are of this type.
	 */
	public static final String ID_ANT_BUILDER_LAUNCH_CONFIGURATION_TYPE = "org.eclipse.ant.AntBuilderLaunchConfigurationType"; //$NON-NLS-1$
		
	public static final String RUN_TARGETS_ATTRIBUTE = TOOL_TYPE_ANT_BUILD + ".runTargets"; //$NON-NLS-1$;

	/**
	* String attribute indicating the Ant targets to execute. Default value is
	 * <code>null</code> which indicates that the default target is to be
	 * executed. Format is a comma separated listing of targets.
	 * NOTE: This value is copied here from org.eclipse.ant.ui.internal.IAntLaunchConfigurationConstants.
	 * 		Ant no longer resides in External Tools and this plug-in. This value is kept here only
	 * 		for migration.
	 */
	public static final String ATTR_ANT_TARGETS = IExternalToolConstants.PLUGIN_ID + ".ATTR_ANT_TARGETS"; //$NON-NLS-1$
	
	/*
	 * 2.0 External Tool Tags
	 */
	public static final String TAG_TOOL_TYPE = "!{tool_type}"; //$NON-NLS-1$
	public static final String TAG_TOOL_NAME = "!{tool_name}"; //$NON-NLS-1$
	public static final String TAG_TOOL_LOCATION = "!{tool_loc}"; //$NON-NLS-1$
	public static final String TAG_TOOL_ARGUMENTS = "!{tool_args}"; //$NON-NLS-1$
	public static final String TAG_TOOL_DIRECTORY = "!{tool_dir}"; //$NON-NLS-1$
	public static final String TAG_TOOL_REFRESH = "!{tool_refresh}"; //$NON-NLS-1$
	public static final String TAG_TOOL_SHOW_LOG = "!{tool_show_log}"; //$NON-NLS-1$
	public static final String TAG_TOOL_BUILD_TYPES = "!{tool_build_types}"; //$NON-NLS-1$
	public static final String TAG_TOOL_BLOCK = "!{tool_block}"; //$NON-NLS-1$

	// Known kind of tools
	private static final String TOOL_TYPE_ANT = "org.eclipse.ui.externaltools.type.ant"; //$NON-NLS-1$
	private static final String TOOL_TYPE_PROGRAM = "org.eclipse.ui.externaltools.type.program"; //$NON-NLS-1$

	/*
	 * 2.1 External Tool Keys
	 */
	public static final String TAG_TYPE = "type"; //$NON-NLS-1$
	public static final String TAG_NAME = "name"; //$NON-NLS-1$
	public static final String TAG_LOCATION = "location"; //$NON-NLS-1$
	public static final String TAG_WORK_DIR = "workDirectory"; //$NON-NLS-1$
	public static final String TAG_CAPTURE_OUTPUT = "captureOutput"; //$NON-NLS-1$
	public static final String TAG_SHOW_CONSOLE = "showConsole"; //$NON-NLS-1$
	public static final String TAG_RUN_BKGRND = "runInBackground"; //$NON-NLS-1$
	public static final String TAG_PROMPT_ARGS = "promptForArguments"; //$NON-NLS-1$
	public static final String TAG_ARGS = "arguments"; //$NON-NLS-1$
	public static final String TAG_REFRESH_SCOPE = "refreshScope"; //$NON-NLS-1$
	public static final String TAG_REFRESH_RECURSIVE = "refreshRecursive"; //$NON-NLS-1$
	public static final String TAG_RUN_BUILD_KINDS = "runForBuildKinds"; //$NON-NLS-1$
	public static final String TAG_EXTRA_ATTR = "extraAttribute"; //$NON-NLS-1$
	public static final String TAG_VERSION = "version"; //$NON-NLS-1$

	private static final String EXTRA_ATTR_SEPARATOR = "="; //$NON-NLS-1$

	private static final String VERSION_21 = "2.1"; //$NON-NLS-1$;

	private static final String TRUE = "true"; //$NON-NLS-1$
	private static final String FALSE = "false"; //$NON-NLS-1$

	/**
	 * Allows no instances.
	 */
	private ExternalToolMigration() {
		super();
	}

	/**
	 * Returns a  launch configuration working copy from the argument map or
	 * <code>null</code> if the given map cannot be interpreted as a 2.0 or 2.1
	 * branch external tool. The returned working copy will be unsaved and its
	 * location will be set to the metadata area.
	 */
	public static ILaunchConfigurationWorkingCopy configFromArgumentMap(Map args) {
		String version = (String) args.get(TAG_VERSION);
		if (VERSION_21.equals(version)) {
			return configFrom21ArgumentMap(args);
		}
		return configFrom20ArgumentMap(args);
	}

	public static ILaunchConfigurationWorkingCopy configFrom21ArgumentMap(Map commandArgs) {
		String name = (String) commandArgs.get(TAG_NAME);
		String type = (String) commandArgs.get(TAG_TYPE);
		
		ILaunchConfigurationWorkingCopy config = newConfig(type, name);
		if (config == null) {
			return null;
		}
		
		config.setAttribute(IExternalToolConstants.ATTR_LOCATION, (String) commandArgs.get(TAG_LOCATION));
		config.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, (String) commandArgs.get(TAG_WORK_DIR));
		config.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, TRUE.equals(commandArgs.get(TAG_CAPTURE_OUTPUT)));
		config.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, TRUE.equals(commandArgs.get(TAG_SHOW_CONSOLE)));
		config.setAttribute(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, TRUE.equals(commandArgs.get(TAG_RUN_BKGRND)));
		config.setAttribute(IExternalToolConstants.ATTR_PROMPT_FOR_ARGUMENTS, TRUE.equals(commandArgs.get(TAG_PROMPT_ARGS)));
		config.setAttribute(RefreshTab.ATTR_REFRESH_SCOPE, (String) commandArgs.get(TAG_REFRESH_SCOPE));
		config.setAttribute(RefreshTab.ATTR_REFRESH_RECURSIVE, TRUE.equals(commandArgs.get(TAG_REFRESH_RECURSIVE)));

		config.setAttribute(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, (String) commandArgs.get(TAG_RUN_BUILD_KINDS));
		
		String args = (String) commandArgs.get(TAG_ARGS);
		if (args != null) {
			config.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, args);
		}

		String extraAttributes = (String) commandArgs.get(TAG_EXTRA_ATTR);
		if (extraAttributes != null) {
			StringTokenizer tokenizer = new StringTokenizer(extraAttributes, EXTRA_ATTR_SEPARATOR);
			while (tokenizer.hasMoreTokens()) {
				String key = tokenizer.nextToken();
				if (!tokenizer.hasMoreTokens())
					break;
				String value = tokenizer.nextToken();
				if (key.equals(RUN_TARGETS_ATTRIBUTE)) {
					// 2.1 implementation only defined 1 "extra attribute"
					config.setAttribute(ATTR_ANT_TARGETS, value);
				}
			}
		}
		return config;
	}

	/**
	 * Creates an external tool from the map.
	 */
	public static ILaunchConfigurationWorkingCopy configFrom20ArgumentMap(Map args) {
		// Update the type...
		String type = (String) args.get(TAG_TOOL_TYPE);
		if (TOOL_TYPE_ANT.equals(type)) {
			type = TOOL_TYPE_ANT_BUILD;
		} else if (TOOL_TYPE_PROGRAM.equals(type)){
			type = IExternalToolConstants.TOOL_TYPE_PROGRAM;
		} else {
			return null;
		}

		String name = (String) args.get(TAG_TOOL_NAME);
		
		ILaunchConfigurationWorkingCopy config = newConfig(type, name);
		if (config == null) {
			return null;
		}

		// Update the location...
		String location = (String) args.get(TAG_TOOL_LOCATION);
		config.setAttribute(IExternalToolConstants.ATTR_LOCATION, location);

		// Update the refresh scope...
		String refresh = (String) args.get(TAG_TOOL_REFRESH);
		if (refresh != null) {
			VariableDefinition varDef = extractVariableDefinition(refresh, 0);
			if ("none".equals(varDef.name)) { //$NON-NLS-1$
				refresh = null;
			}
			config.setAttribute(RefreshTab.ATTR_REFRESH_SCOPE, refresh);
		}

		// Update the arguments
		String arguments = (String) args.get(TAG_TOOL_ARGUMENTS);
		if (type.equals(TOOL_TYPE_ANT_BUILD)) {
			String targetNames = null;
			if (arguments != null) {
				int start = 0;
				ArrayList targets = new ArrayList();
				StringBuffer buffer = new StringBuffer();
				VariableDefinition varDef = extractVariableDefinition(arguments, start);
				while (varDef.end != -1) {
					if ("ant_target".equals(varDef.name) && varDef.argument != null) { //$NON-NLS-1$
						targets.add(varDef.argument);
						buffer.append(arguments.substring(start, varDef.start));
					} else {
						buffer.append(arguments.substring(start, varDef.end));
					}
					start = varDef.end;
					varDef = extractVariableDefinition(arguments, start);
				}
				buffer.append(arguments.substring(start, arguments.length()));
				arguments = buffer.toString();
	
				buffer.setLength(0);
				for (int i = 0; i < targets.size(); i++) {
					String target = (String) targets.get(i);
					if (target != null && target.length() > 0) {
						buffer.append(target);
						buffer.append(","); //$NON-NLS-1$
					}
				}
				targetNames = buffer.toString();
			}
			if (targetNames != null && targetNames.length() > 0) {
				config.setAttribute(ATTR_ANT_TARGETS, targetNames);
			}
		}
		config.setAttribute(IExternalToolConstants.ATTR_TOOL_ARGUMENTS, arguments);

		// Collect the rest of the information
		config.setAttribute(IExternalToolConstants.ATTR_SHOW_CONSOLE, TRUE.equals(args.get(TAG_TOOL_SHOW_LOG)));
		config.setAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT, TRUE.equals(args.get(TAG_TOOL_SHOW_LOG)));
		config.setAttribute(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, FALSE.equals(args.get(TAG_TOOL_BLOCK)));
		String buildKinds= (String) args.get(TAG_TOOL_BUILD_TYPES);
		if (buildKinds != null) {
			buildKinds= buildKinds.replace(';', ','); // Replace the old separator with the new
		}
		config.setAttribute(IExternalToolConstants.ATTR_RUN_BUILD_KINDS, buildKinds);
		config.setAttribute(IExternalToolConstants.ATTR_WORKING_DIRECTORY, (String) args.get(TAG_TOOL_DIRECTORY));
		return config;
	}

	/**
	 * Returns a new working copy with the given external tool name and external
	 * tool type or <code>null</code> if no config could be created.
	 */
	private static ILaunchConfigurationWorkingCopy newConfig(String type, String name) {
		if (type == null || name == null) {
			return null;
		}
		ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
		ILaunchConfigurationType configType;
		if (TOOL_TYPE_ANT_BUILD.equals(type)) {
			configType = manager.getLaunchConfigurationType(ID_ANT_BUILDER_LAUNCH_CONFIGURATION_TYPE);
		} else if (IExternalToolConstants.TOOL_TYPE_PROGRAM.equals(type)) {
			configType = manager.getLaunchConfigurationType(IExternalToolConstants.ID_PROGRAM_BUILDER_LAUNCH_CONFIGURATION_TYPE);
		} else {
			return null;
		}
		try {
			if (configType != null) {
				return configType.newInstance(null, name);
			}
		} catch (CoreException e) {
			ExternalToolsPlugin.getDefault().log(e);
		}
		return null;
	}
	
	/**
	 * Returns the tool name extracted from the given command argument map.
	 * Extraction is attempted using 2.0 and 2.1 external tool formats.
	 */
	public static String getNameFromCommandArgs(Map commandArgs) {
		String name= (String) commandArgs.get(TAG_NAME);
		if (name == null) {
			name= (String) commandArgs.get(TAG_TOOL_NAME);
		}
		return name;
	}
	
	/**
	 * Migrate the old RUN_IN_BACKGROUND launch config attribute to the new
	 * LAUNCH_IN_BACKGROUND attribute provided by the debug ui plugin.
	 * 
	 * @param config the config to migrate
	 * @return the migrated config
	 */
	public static ILaunchConfiguration migrateRunInBackground(ILaunchConfiguration config) {
		String noValueFlag= "NoValue"; //$NON-NLS-1$
		String attr= null;
		try {
			attr = config.getAttribute(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, noValueFlag);
		} catch (CoreException e) {
			// Exception will occur if the attribute is already set because the attribute is actually a boolean.
			// No migration necessary.
			return config;
		}
		if (noValueFlag.equals(attr)) {
			//the old constant
			String ATTR_RUN_IN_BACKGROUND= IExternalToolConstants.PLUGIN_ID + ".ATTR_RUN_IN_BACKGROUND"; //$NON-NLS-1$
			boolean runInBackground= false;
			try {
				runInBackground = config.getAttribute(ATTR_RUN_IN_BACKGROUND, runInBackground);
			} catch (CoreException e) {
				ExternalToolsPlugin.getDefault().log(ExternalToolsUIMessages.getString("ExternalToolMigration.37"), e); //$NON-NLS-1$
			}
			try {
				ILaunchConfigurationWorkingCopy workingCopy= config.getWorkingCopy();
				workingCopy.setAttribute(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, runInBackground);
				config= workingCopy.doSave();
			} catch (CoreException e) {
				ExternalToolsPlugin.getDefault().log(ExternalToolsUIMessages.getString("ExternalToolMigration.38"), e); //$NON-NLS-1$
			}
		}
		return config;
	}
	
	/**
	 * Extracts a variable name and argument from the given string.
	 * 
	 * @param text the source text to parse for a variable tag
	 * @param start the index in the string to start the search
	 * @return the variable definition
	 */
	public static VariableDefinition extractVariableDefinition(String text, int start) {
		VariableDefinition varDef = new VariableDefinition();
		
		varDef.start = text.indexOf(VAR_TAG_START, start);
		if (varDef.start < 0){
			return varDef;
		}
		start = varDef.start + VAR_TAG_START.length();
		
		int end = text.indexOf(VAR_TAG_END, start);
		if (end < 0) {
			return varDef;
		}
		varDef.end = end + VAR_TAG_END.length();
		if (end == start) {
			return varDef;
		}
	
		int mid = text.indexOf(VAR_TAG_SEP, start);
		if (mid < 0 || mid > end) {
			varDef.name = text.substring(start, end);
		} else {
			if (mid > start) {
				varDef.name = text.substring(start, mid);
			}
			mid = mid + VAR_TAG_SEP.length();
			if (mid < end) {
				varDef.argument = text.substring(mid, end);
			}
		}
		
		return varDef;
	}	
}
