/*******************************************************************************
 * Copyright (c) 2006,2010 IBM Corp. 
 * 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 Corp. - initial implementation
 *******************************************************************************/

package org.eclipse.ptp.pldt.wizards.wizardPages;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.eclipse.cdt.core.templateengine.TemplateCore;
import org.eclipse.cdt.core.templateengine.process.ProcessArgument;
import org.eclipse.cdt.core.templateengine.process.ProcessFailureException;
import org.eclipse.cdt.core.templateengine.process.ProcessRunner;
import org.eclipse.cdt.managedbuilder.core.BuildException;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IManagedBuildInfo;
import org.eclipse.cdt.managedbuilder.core.IManagedProject;
import org.eclipse.cdt.managedbuilder.core.IOption;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ptp.pldt.wizards.MpiWizardsPlugin;
import org.eclipse.ptp.pldt.wizards.messages.Messages;

/**
 * 
 * After the MPIProjectWizardPage runs, and we get MPI include path from the user,
 * we have this opportunity to use that information to modify the include paths, build cmd,  etc.
 * in the project
 * 
 * <p>This handles plain C projects; MPIProjectProcessCPP extends this to handle C++ projects
 * 
 * @author Beth Tibbitts
 *
 */
public class MPIProjectProcess extends ProcessRunner {
	private static final boolean traceOn=false;
	private boolean wizTraceOn=MPIProjectWizardPage.wizardTraceOn;
	//private static final templateID=

	protected Map<String,String> valueStore;
	
	@Override
	public void process(TemplateCore template, ProcessArgument[] args,
			String processId, IProgressMonitor monitor)
			throws ProcessFailureException {
		if(wizTraceOn)System.out.println("MPIProjectProcess().run()..."); //$NON-NLS-1$
		
		valueStore= template.getValueStore();
		String pageID = MPIProjectWizardPage.PAGE_ID;

		Object obj = getNewPropValue(pageID, MPIProjectWizardPage.DO_MPI_INCLUDES, null);
		// use the default value if nothing was set in the pageData by the user
		boolean doMpiIncludes = MPIProjectWizardPage.getDefaultUseMpiIncludes();
		if (obj != null)
			doMpiIncludes = Boolean.valueOf((String) obj);
		if (!doMpiIncludes) {
			if (traceOn)
				System.out.println("Do not save MPI info in this project."); //$NON-NLS-1$
			return;
		}

 		// this process must be executed after a separate process which creates the project
		IProject proj= ResourcesPlugin.getWorkspace().getRoot().getProject(valueStore.get("projectName")); //$NON-NLS-1$
		if(!proj.exists()) {
			System.out.println(Messages.MPIProjectProcess_proj_does_not_exist_quit);
			return;	
		}

		if(traceOn)System.out.println(Messages.MPIProjectProcess_project + proj.getName());

		// Collect the values that the user entered on the wizard page
		String propID = MPIProjectWizardPage.INCLUDE_PATH_PROP_ID;
		String newIncludePath = getNewPropValue(pageID, propID,"c:/mpich2/include"); //$NON-NLS-1$
		if(traceOn)System.out.println("Got prop: "+propID+"="+newIncludePath); //$NON-NLS-1$ //$NON-NLS-2$
		
		propID = MPIProjectWizardPage.LIB_PROP_ID;
		String newLib=getNewPropValue(pageID,propID,"lib"); //$NON-NLS-1$
		
		propID=MPIProjectWizardPage.LIBRARY_SEARCH_PATH_PROP_ID;
		String newLibSearchPath=getNewPropValue(pageID,propID,"c:/mpich2/lib"); //$NON-NLS-1$
		
		propID=MPIProjectWizardPage.MPI_COMPILE_COMMAND_PROP_ID;
		String mpiCompileCommand=getNewPropValue(pageID,propID,"mpicc"); //$NON-NLS-1$
		
		propID=MPIProjectWizardPage.MPI_LINK_COMMAND_PROP_ID;
		String mpiLinkCommand=getNewPropValue(pageID,propID,"mpicc"); //$NON-NLS-1$

		IManagedBuildInfo info = null;
		try {
			info = ManagedBuildManager.getBuildInfo(proj);
			// note: assumed null if this is not a managed build project? will we get here in that case?
			if(traceOn)System.out.println("Build info: " + info); //$NON-NLS-1$
		} catch (Exception e) {
			System.out.println("MPIProjectProcess.run(), "+e.getMessage()); //$NON-NLS-1$
			e.printStackTrace();
			return;
		}
		assert(info!=null);
		
		IManagedProject mProj = info.getManagedProject();
		if(traceOn)showOptions(mProj);
		
		// add the include path, linker, build cmd, etc.  values to all the configurations
		IConfiguration[] configs = mProj.getConfigurations();
		for (int i = 0; i < configs.length; i++) {
			IConfiguration cf = configs[i];
			if(traceOn)System.out.println("Config " + i + ": " + cf.getName()); //$NON-NLS-1$ //$NON-NLS-2$
			addIncludePath(cf, newIncludePath);
			addLinkerOpt(cf,newLib,newLibSearchPath);
			setCompileCommand(cf,mpiCompileCommand);
			setLinkCommand(cf,mpiLinkCommand);		
		}
		if(traceOn)System.out.println("MPIProjectProcess, newIncludePath: "+newIncludePath); //$NON-NLS-1$
		if(traceOn)System.out.println("   newLib: "+newLib+"  newLibSrchPth: "+newLibSearchPath); //$NON-NLS-1$ //$NON-NLS-2$
		if(traceOn)System.out.println("   compileCmd: "+mpiCompileCommand); //$NON-NLS-1$
		if(traceOn)System.out.println("   linkCmd: "+mpiLinkCommand); //$NON-NLS-1$
		// ManagedBuildManger.saveBuildInfo(...) assures that the
		// values are persisted in the build model, otherwise they will
		// be lost when you shut down Eclipse.
		if(traceOn)System.out.println("ManagedBuildManager.saveBuildInfo..."); //$NON-NLS-1$
		
		ManagedBuildManager.saveBuildInfo(proj, true);

	}
	public static String getResourceString(String key) {
		ResourceBundle bundle = MpiWizardsPlugin.getDefault().getResourceBundle();
		try {
			return (bundle != null) ? bundle.getString(key) : key;
		} catch (MissingResourceException e) {
			return key;
		}
	}

	/**
	 * Get a value that was possibly obtained from the user on the associated wizard page.
	 * @param pageID The pageID for our wizard page
	 * @param propID The propID of the value we want
	 * @param defaultVal The default value to use if the user didn't select anything,
	 * or if we haven't gotten around to LETTING the user select anything yet.
	 * @return
	 */
	protected String getNewPropValue(String pageID, String propID, String defaultVal) {
		Object obj = valueStore.get(pageID+MPIProjectWizardPage.DOT+propID);
		// if selection made on page, obj is non-null.
		String newValue = defaultVal;
		String msg=" ( used default value)"; //$NON-NLS-1$
		if (obj != null) {
			newValue = obj.toString();
			msg=""; //$NON-NLS-1$
		}
		if(traceOn)System.out.println("propID=" + propID + "  value=" + newValue+msg); //$NON-NLS-1$ //$NON-NLS-2$
		return newValue;
	}


	/**
	 * Add an include path for C compiling to the existing include paths of the given
	 * Configuration.  XLC is handled as a special case to find its include path option;
	 * for other tools, we assume there is a single option for include paths, so we take
	 * the first one.
	 * 
	 * @param cf
	 *            the configuration of the project (e.g. Release, Debug, etc.)
	 * @param newIncludePath
	 *            include path(s) to add.  If more than one, separate by
	 *            java.io.File.pathSeparator, which is semicolon for Windows, colon for Mac/Linux
	 */
	protected void addIncludePath(IConfiguration cf, String newIncludePath) {
		// note: could be > 1 path in 'newIncludePath'
		String ext = "c"; //$NON-NLS-1$
		ITool cfTool = cf.getToolFromInputExtension(ext);

		//String id = cfTool.getId(); // "cdt.managedbuild.tool.xlc.c.compiler.exe.debug.1423270745"
		String name = cfTool.getName();// "XL C Compiler"
		IOption option = null;
		if (name.startsWith("XL C")) { // special case for XL C compiler //$NON-NLS-1$
			option = cfTool.getOptionById("xlc.c.compiler.option.include.paths"); //$NON-NLS-1$
		} else { // otherwise we assume there is only one include path option.
			option = getFirstOptionByType(cf, cfTool, IOption.INCLUDE_PATH);
		}
		if (option != null) {
			String[] includePaths = null;
			try {
				includePaths = option.getIncludePaths();
			} catch (BuildException e) {
				e.printStackTrace();
			}
			String[] newIncludePaths = add(includePaths, newIncludePath);
			if (traceOn)
				System.out.println("        add " + newIncludePath + " to existing includePaths: " //$NON-NLS-1$ //$NON-NLS-2$
						+ unroll(includePaths));
			ManagedBuildManager.setOption(cf, cfTool, option, newIncludePaths);
		}
		else{
			System.out.println("MPIProjectProcess, no option for include paths found."); //$NON-NLS-1$
		}
	}


	/**
	 * Add a new linker option.  Assumes that there is ONE instance of an option
	 * of type <code>IOption.LIBRARY_PATHS</code> and <code>IOption.LIBRARIES</code>.
	 * This method adds the libName and libPath to these two options.
	 * @param cf the Configuration to which we want to add to linker options
	 * @param libName the lib name (e.g. "lib")
	 * @param libPath the library search path name (e.g. "c:/mypath/lib")
	 * 
	 */
	protected void addLinkerOpt(IConfiguration cf, String libName, String libPath) {
		String ext = "o"; //$NON-NLS-1$
		ITool cfTool = cf.getToolFromInputExtension(ext);
		if(cfTool==null) {
			MessageDialog.openWarning(null, Messages.MPIProjectProcess_unable_to_set_linker_opt, Messages.MPIProjectProcess_unable_to_set_linker_opt_toolchain_invalid_q);
			return;
		}
		IOption lpOpt = getFirstOptionByType(cf, cfTool, IOption.LIBRARY_PATHS);
		addOptionValue(cf, cfTool, lpOpt, libPath);

		IOption libOpt = getFirstOptionByType(cf, cfTool, IOption.LIBRARIES);
		addOptionValue(cf, cfTool, libOpt, libName);
	}                                                                                                                     

	
	protected void setCompileCommand(IConfiguration cf, String buildCmd) {
		if(traceOn)System.out.println("compile cmd: "+buildCmd); //$NON-NLS-1$
		ITool compiler = cf.getToolFromInputExtension("c"); //$NON-NLS-1$
		compiler.setToolCommand(buildCmd);
	}
	
	protected void setLinkCommand(IConfiguration cf, String buildCmd) {
		if(traceOn)System.out.println("link cmd: "+buildCmd); //$NON-NLS-1$
		ITool linker=cf.getToolFromInputExtension("o"); //$NON-NLS-1$
		if(linker==null) {
			MessageDialog.openWarning(null, Messages.MPIProjectProcess_unable_to_set_link_command, Messages.MPIProjectProcess_unable_to_set_link_command_toolchain_invalid_q);
			return;
		}
		linker.setToolCommand(buildCmd);
		
	}
	
	/**
	 * Add a value to a multi-valued tool option<br>
	 * (For example, add a path to include paths, or a lib to libraries list)
	 * @param cf the Configuration
	 * @param tool the tool in which to update the option
	 * @param option the option to update 
	 * @param value the new value to add to the list of existing values in the option
	 */
	protected void addOptionValue(IConfiguration cf, ITool tool, IOption option, String value) {
		try {
			int type = option.getValueType();
			String[] valueList = null;
			switch (type) {
			case IOption.INCLUDE_PATH:
				valueList = option.getIncludePaths();
				valueList = add(valueList,value);
				break;
			case IOption.LIBRARIES:
				valueList = option.getLibraries();
				valueList=addNotPath(valueList, value);
				break;
			case IOption.LIBRARY_PATHS:// this is type for library search path cdt 4.0 
				valueList=option.getBasicStringListValue();
				valueList=addNotPath(valueList,value);
				break;
			
			default:
				System.out.println("MPIProjectWizard Process postprocessing (MPIProjectProcess), can't get type of option for " + option.getName()); //$NON-NLS-1$
				return;
			}
			// update the option in the managed builder options
			ManagedBuildManager.setOption(cf, tool, option, valueList);

		} catch (BuildException e) {
			System.out.println("MPIProjectProcess.addOptionValue(), "+e.getMessage()); //$NON-NLS-1$
			System.out.println(e.getMessage());
			e.printStackTrace();
		}

	}

	/**
	 * Print the options for a project.<br>
	 * e.g. for Debug and Release configurations, get all the tools (compiler, linker etc.) then for each tool, 
	 * get all the options and print them.
	 * 
	 * IResource resource= ... ;// can be any resource, I use project.
     * IManagedBuildInfo mbo = ManagedBuildManager.getBuildInfo(resource);
     * IManagedProject mp=mbo.getManagedProject();
	 * <br>
	 * This helps in figuring out what they are, and what you want to change.
	 * Some sample output is at the bottom of this file.
	 * 
	 * @param proj the (managed) project for which print all this stuff.
	 */
	protected void showOptions(IManagedProject proj) {
		if(traceOn)System.out.println("Managed Project: "+proj.getName()); //$NON-NLS-1$
		if(traceOn)System.out.println("Path.SEPARATOR="+Path.SEPARATOR); //$NON-NLS-1$
		if(traceOn)System.out.println("Path.DEVICE_SEPARATOR="+Path.DEVICE_SEPARATOR); //$NON-NLS-1$
		IConfiguration[] configs = proj.getConfigurations();
		try {
			for (int i = 0; i < configs.length; i++) {
				IConfiguration cf = configs[i];
				ITool[] allTools = cf.getTools();

				int numTools = allTools.length;
				System.out.println("Config " + i + ": " + cf.getName()+ " has "+numTools+" tools."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$

				for (int k = 0; k < allTools.length; k++) {
					ITool tool = allTools[k];
					System.out.println("  Tool " + k + ": " + tool.getName()); //$NON-NLS-1$ //$NON-NLS-2$
					//boolean rc=tool.setToolCommand("foo");
					String toolCmd=tool.getToolCommand();
					String toolID=tool.getId();
					System.out.println("  cmd="+toolCmd+"  toolID="+toolID); //$NON-NLS-1$ //$NON-NLS-2$
					
					
					IOption[] options = tool.getOptions();

					for (int j = 0; j < options.length; j++) {
						IOption opt = options[j];
						String foundOptionID = opt.getId();
						int type=opt.getValueType();
						System.out.println("    option " + j + " " + opt.getName() + " id=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
								+ foundOptionID+"  type="+showType(type)); //$NON-NLS-1$
						if(opt.getValueType()==IOption.INCLUDE_PATH) {
							showIncludePaths(opt);
						}
					}
				}

				System.out.println("Config " + i + ": " + cf.getName() //$NON-NLS-1$ //$NON-NLS-2$
						+ "======= End of ALL tools "); //$NON-NLS-1$
				
				// another way to access Tool
				String ext = "c"; //$NON-NLS-1$
				ITool cfTool = cf.getToolFromInputExtension(ext);
				System.out.println("Tool by ext: " + ext + " is: " + cfTool.getName()); //$NON-NLS-1$ //$NON-NLS-2$
				
				// Look for include path
				IOption option = getFirstOptionByType(cf, cfTool, IOption.INCLUDE_PATH);
				if (option != null) {
					String oname = option.getName();
					System.out.println("Option " + option.getId() + " is " + oname); //$NON-NLS-1$ //$NON-NLS-2$
					showIncludePaths(option);
				}
				else System.out.println("No include path option found. "); //$NON-NLS-1$

			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	protected String showType(int type){
		if(type==IOption.INCLUDE_PATH) return type+" (IOption.INCLUDE_PATH)"; //$NON-NLS-1$
		if(type==IOption.LIBRARY_PATHS) return type+" (IOption.LIBRARY_PATHS)"; //$NON-NLS-1$
		if(type==IOption.LIBRARIES)     return type+" (IOption.LIBRARIES)"; //$NON-NLS-1$
		return type+" "; //$NON-NLS-1$
	}

	/**
	 * Display the list of include paths in an option which is presumed
	 * to be the include paths option.
	 * @param opt
	 * @throws BuildException
	 */
	protected void showIncludePaths(IOption opt) throws BuildException {
		assert opt.getValueType() == IOption.INCLUDE_PATH ;
		// if the option is a list of include paths, display them.
		String[] includePaths = opt.getIncludePaths();
		for (int index = 0; index < includePaths.length; index++) {
			String path = includePaths[index];
			System.out.println("   include path " + index + ": " + path); //$NON-NLS-1$ //$NON-NLS-2$
		}

	}

	/**
	 * Add one or more paths to the list of paths
	 * 
	 * @param existingPaths the existing list of paths to add to
	 * @param newPath the new path to add; may be >1 directory, with path delimiter java.io.File.pathSeparator 
	 * (usually semicolon or colon)
	 * @return the merged list
	 */
	protected String[] add(String[] existingPaths, String newPath) {
		String pathSep=java.io.File.pathSeparator;  // semicolon for windows, colon for Mac/Linux
		List<String> newPathList = new ArrayList<String>();
		String path;
		for (int i = 0; i < existingPaths.length; i++) {
			path = existingPaths[i];
			newPathList.add(path);
		}
		String[] newPathArray=newPath.split(pathSep);
		for (int i = 0; i < newPathArray.length; i++) {
			path = newPathArray[i];
			newPathList.add(path);
		}
		
		String[] newArray=(String[])newPathList.toArray(new String[0]);
		return newArray;
	}

	/**
	 * Add a single string to an array of strings
	 * @param strList
	 * @param newStr
	 * @return
	 */
	protected String[] addNotPath(String[] strList, String newStr) {
		int len = strList.length;
		String newList[] = new String[len + 1];
		System.arraycopy(strList, 0, newList, 0, len);
		newList[len] = newStr;
		return newList;
	}
	/**
	 * Simple string representation of items in a string array
	 * @param list
	 * @return
	 */
	protected String unroll (String[] list){
		StringBuffer result=new StringBuffer();
		//list = new String[]{"one","two"};
		//System.out.println(list);
		for (int i = 0; i < list.length; i++) {
			String string = list[i];
			result.append(string);
			result.append(", "); //$NON-NLS-1$
		}
		if (result.length() > 2) {
			result.delete(result.length() - 2, result.length() - 1);
		}
		return result.toString();
	}
	/**
	 * Get the options of a specific type.<br>
	 * We really need an ITool.getOptionsByType(int) so we don't have to do
	 * this.
	 * 
	 * @param cf
	 *            the IConfiguration in which to search
	 * @param cfTool
	 *            the ITool whose options are being searched
	 * @param optionType
	 *            the option type we are looking for, e.g. IOption.SOMETHING
	 * @return
	 */
	protected List<IOption> getOptionsByType(IConfiguration cf, ITool cfTool, int optionType) {

		// run thru ALL options and check type for each, returning the ones that match
		IOption[] allOptions = cfTool.getOptions();
		List<IOption> foundOptions = new ArrayList<IOption>();

		for (int i = 0; i < allOptions.length; i++) {
			IOption option = allOptions[i];

			int oType = 0;
			try {
				oType = option.getValueType();
			} catch (BuildException e) {
				e.printStackTrace();
				continue;
			}
			if (optionType == oType) {
				// add it to the list
				foundOptions.add(option);
			}

		}
		//IOption[] ret= foundOptions.toArray(new IOption[foundOptions.size()]);
		return foundOptions;
	}
	/**
	 * Returns the <i>first</i> option of the specified type from the tool
	 * @param cf
	 * @param cfTool
	 * @param optionType
	 * @return
	 */
	protected IOption getFirstOptionByType(IConfiguration cf, ITool cfTool, int optionType){
		List<IOption> allOptions=getOptionsByType(cf,cfTool,optionType);
		if(allOptions.size()>0){
			return allOptions.get(0);
		}
		return null;
	}
}

/**
 * 
 * Some sample tool data from showOptions() on Windows XP with cygwin Tool 1:
 * GCC C Compiler
 * <p>
 * 
 * option 0 Do not search system directories (-nostdinc)
 * id=gnu.c.compiler.option.preprocessor.nostdinc<br>
 * option 1 Preprocess only (-E)
 * id=gnu.c.compiler.option.preprocessor.preprocess<br>
 * option 2 Defined symbols (-D)
 * id=gnu.c.compiler.option.preprocessor.def.symbols<br>
 * option 3 Undefined symbols (-U)
 * id=gnu.c.compiler.option.preprocessor.undef.symbol<br>
 * option 4 Include paths (-I) id=gnu.c.compiler.option.include.paths<br>
 * option 5 Optimization Level
 * id=gnu.c.compiler.cygwin.exe.release.option.optimization.level<br>
 * option 6 Other optimization flags id=gnu.c.compiler.option.optimization.flags<br>
 * option 7 Debug Level
 * id=gnu.c.compiler.cygwin.exe.release.option.debugging.level<br>
 * option 8 Other debugging flags id=gnu.c.compiler.option.debugging.other<br>
 * option 9 Generate gprof information (-pg)
 * id=gnu.c.compiler.option.debugging.gprof<br>
 * option 10 Generate prof information (-p)
 * id=gnu.c.compiler.option.debugging.prof<br>
 * option 11 Check syntax only (-fsyntax-only)
 * id=gnu.c.compiler.option.warnings.syntax<br>
 * option 12 Pedantic (-pedantic) id=gnu.c.compiler.option.warnings.pedantic<br>
 * option 13 Pedantic warnings as errors (-pedantic-errors)
 * id=gnu.c.compiler.option.warnings.pedantic.error<br>
 * option 14 Inhibit all warnings (-w) id=gnu.c.compiler.option.warnings.nowarn<br>
 * option 15 All warnings (-Wall) id=gnu.c.compiler.option.warnings.allwarn<br>
 * option 16 Warnings as errors (-Werror)
 * id=gnu.c.compiler.option.warnings.toerrors<br>
 * option 17 Other flags id=gnu.c.compiler.option.misc.other<br>
 * option 18 Verbose (-v) id=gnu.c.compiler.option.misc.verbose<br>
 * option 19 Support ANSI programs (-ansi) id=gnu.c.compiler.option.misc.ansi<br>
 * 
 * Tool 2: GCC C Linker <br>
 * option 5 Libraries (-l) id=gnu.c.link.option.libs<br>
 * option 6 Library search path (-L) id=gnu.c.link.option.paths<br>
 * 
 */

