/*******************************************************************************
 * Copyright (c) 2000, 2016 QNX Software Systems 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:
 *     QNX Software Systems - Initial API and implementation
 *     Baltasar Belyavsky (Texas Instruments) - bug 340219: Project metadata files are saved unnecessarily
 *******************************************************************************/
package org.eclipse.cdt.make.internal.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;

import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.extension.CBuildData;
import org.eclipse.cdt.core.settings.model.extension.CConfigurationData;
import org.eclipse.cdt.make.core.IMakeBuilderInfo;
import org.eclipse.cdt.make.core.IMakeCommonBuildInfo;
import org.eclipse.cdt.make.core.MakeCorePlugin;
import org.eclipse.cdt.make.core.MakeProjectNature;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.VariablesPlugin;

public class BuildInfoFactory {

	private static final String PREFIX = MakeCorePlugin.getUniqueIdentifier();

	static final String BUILD_COMMAND = PREFIX + ".buildCommand"; //$NON-NLS-1$
	static final String BUILD_LOCATION = PREFIX + ".buildLocation"; //$NON-NLS-1$
	static final String STOP_ON_ERROR = PREFIX + ".stopOnError"; //$NON-NLS-1$
	static final String USE_DEFAULT_BUILD_CMD = PREFIX + ".useDefaultBuildCmd"; //$NON-NLS-1$
	static final String BUILD_TARGET_AUTO = PREFIX + ".autoBuildTarget"; //$NON-NLS-1$
	static final String BUILD_TARGET_INCREMENTAL = PREFIX + ".incrementalBuildTarget"; //$NON-NLS-1$
	static final String BUILD_TARGET_FULL = PREFIX + ".fullBuildTarget"; //$NON-NLS-1$
	static final String BUILD_TARGET_CLEAN = PREFIX + ".cleanBuildTarget"; //$NON-NLS-1$
	static final String BUILD_FULL_ENABLED = PREFIX + ".enableFullBuild"; //$NON-NLS-1$
	static final String BUILD_CLEAN_ENABLED = PREFIX + ".enableCleanBuild"; //$NON-NLS-1$
	static final String BUILD_INCREMENTAL_ENABLED = PREFIX + ".enabledIncrementalBuild"; //$NON-NLS-1$
	static final String BUILD_AUTO_ENABLED = PREFIX + ".enableAutoBuild"; //$NON-NLS-1$
	static final String BUILD_ARGUMENTS = PREFIX + ".buildArguments"; //$NON-NLS-1$
	static final String ENVIRONMENT = PREFIX + ".environment"; //$NON-NLS-1$
	static final String BUILD_APPEND_ENVIRONMENT = PREFIX + ".append_environment"; //$NON-NLS-1$

	private abstract static class AbstractBuildInfo implements IMakeBuilderInfo {

		@Override
		public void setUseDefaultBuildCmd(boolean on) throws CoreException {
			putString(USE_DEFAULT_BUILD_CMD, String.valueOf(on));
		}

		@Override
		public boolean isDefaultBuildCmd() {
			if (getString(USE_DEFAULT_BUILD_CMD) == null) { // if no property
				// then default to
				// true
				return true;
			}
			return getBoolean(USE_DEFAULT_BUILD_CMD);
		}

		@Override
		public String getBuildAttribute(String name, String defaultValue) {
			String value = getString(name);
			if (value == null) {
				if (IMakeCommonBuildInfo.BUILD_COMMAND.equals(name)) {
					value = getString(BuildInfoFactory.BUILD_COMMAND);
				} else if (IMakeCommonBuildInfo.BUILD_ARGUMENTS.equals(name)) {
					value = getString(BuildInfoFactory.BUILD_ARGUMENTS);
				} else if (IMakeCommonBuildInfo.BUILD_LOCATION.equals(name)) {
					value = getString(BuildInfoFactory.BUILD_LOCATION);
				} else if (IMakeBuilderInfo.BUILD_TARGET_AUTO.equals(name)) {
					value = getString(BuildInfoFactory.BUILD_TARGET_AUTO);
				} else if (IMakeBuilderInfo.BUILD_TARGET_CLEAN.equals(name)) {
					value = getString(BuildInfoFactory.BUILD_TARGET_CLEAN);
				} else if (IMakeBuilderInfo.BUILD_TARGET_INCREMENTAL.equals(name)) {
					value = getString(BuildInfoFactory.BUILD_TARGET_INCREMENTAL);
				}
			}
			return value != null ? value : defaultValue != null ? defaultValue : ""; //$NON-NLS-1$
		}

		@Override
		public void setBuildAttribute(String name, String value) throws CoreException {
			putString(name, value);
		}

		@Override
		public Map<String, String> getExpandedEnvironment() {
			Map<String, String> env = getEnvironment();
			HashMap<String, String> envMap = new HashMap<>(env.entrySet().size());
			for (Map.Entry<String, String> entry : env.entrySet()) {
				String key = entry.getKey();
				String value = entry.getValue();
				// translate any string substitution variables
				String translated = value;
				try {
					translated = VariablesPlugin.getDefault().getStringVariableManager()
							.performStringSubstitution(value, false);
				} catch (CoreException e) {
				}
				envMap.put(key, translated);
			}
			return envMap;
		}

		@Override
		public void setBuildCommand(IPath location) throws CoreException {
			putString(IMakeCommonBuildInfo.BUILD_COMMAND, null);
			putString(BuildInfoFactory.BUILD_COMMAND, location.toString());
		}

		@Override
		public IPath getBuildCommand() {
			if (isDefaultBuildCmd()) {
				String command = getBuildParameter("defaultCommand"); //$NON-NLS-1$
				if (command == null) {
					return new Path("make"); //$NON-NLS-1$
				}
				return new Path(command);
			}
			String result = getBuildAttribute(IMakeCommonBuildInfo.BUILD_COMMAND,
					getString(BuildInfoFactory.BUILD_COMMAND));
			try {
				result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result,
						false);
			} catch (CoreException e) {
			}
			return new Path(result);
		}

		protected String getBuildParameter(String name) {
			IExtension extension = Platform.getExtensionRegistry().getExtension(ResourcesPlugin.PI_RESOURCES,
					ResourcesPlugin.PT_BUILDERS, getBuilderID());
			if (extension == null)
				return null;
			IConfigurationElement[] configs = extension.getConfigurationElements();
			if (configs.length == 0)
				return null;
			// The nature exists, or this builder doesn't specify a nature
			IConfigurationElement[] runElement = configs[0].getChildren("run"); //$NON-NLS-1$
			IConfigurationElement[] paramElement = runElement[0].getChildren("parameter"); //$NON-NLS-1$
			for (int i = 0; i < paramElement.length; i++) {
				if (paramElement[i].getAttribute("name").equals(name)) { //$NON-NLS-1$
					return paramElement[i].getAttribute("value"); //$NON-NLS-1$
				}
			}
			return null;
		}

		protected abstract String getBuilderID();

		@Override
		public void setBuildLocation(IPath location) throws CoreException {
			putString(IMakeCommonBuildInfo.BUILD_LOCATION, null);
			putString(BuildInfoFactory.BUILD_LOCATION, location.toString());
		}

		@Override
		public IPath getBuildLocation() {
			String result = getBuildAttribute(IMakeCommonBuildInfo.BUILD_LOCATION,
					getString(BuildInfoFactory.BUILD_LOCATION));
			try {
				result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result,
						false);
			} catch (CoreException e) {
			}
			return new Path(result);
		}

		@Override
		public String getBuildArguments() {
			String result = getBuildAttribute(IMakeCommonBuildInfo.BUILD_ARGUMENTS,
					getString(BuildInfoFactory.BUILD_ARGUMENTS));
			if (result == null) {
				return ""; //$NON-NLS-1$
			}
			try {
				result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result,
						false);
			} catch (CoreException e) {
			}
			return result;
		}

		@Override
		public void setBuildArguments(String args) throws CoreException {
			putString(IMakeCommonBuildInfo.BUILD_ARGUMENTS, null);
			putString(BuildInfoFactory.BUILD_ARGUMENTS, args);
		}

		@Override
		public void setStopOnError(boolean enabled) throws CoreException {
			putString(STOP_ON_ERROR, String.valueOf(enabled));
		}

		@Override
		public boolean isStopOnError() {
			return getBoolean(STOP_ON_ERROR);
		}

		@Override
		public void setAutoBuildTarget(String target) throws CoreException {
			putString(IMakeBuilderInfo.BUILD_TARGET_AUTO, null);
			putString(BuildInfoFactory.BUILD_TARGET_AUTO, target);
		}

		@Override
		public String getAutoBuildTarget() {
			String result = getBuildAttribute(IMakeBuilderInfo.BUILD_TARGET_AUTO,
					getString(BuildInfoFactory.BUILD_TARGET_AUTO));
			try {
				result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result,
						false);
			} catch (CoreException e) {
			}
			return result;
		}

		@Override
		public void setIncrementalBuildTarget(String target) throws CoreException {
			putString(IMakeBuilderInfo.BUILD_TARGET_INCREMENTAL, null);
			putString(BuildInfoFactory.BUILD_TARGET_INCREMENTAL, target);
		}

		@Override
		public String getIncrementalBuildTarget() {
			String result = getBuildAttribute(IMakeBuilderInfo.BUILD_TARGET_INCREMENTAL,
					getString(BuildInfoFactory.BUILD_TARGET_INCREMENTAL));
			try {
				result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result,
						false);
			} catch (CoreException e) {
			}
			return result;
		}

		@Override
		public void setFullBuildTarget(String target) throws CoreException {

		}

		@Override
		public String getFullBuildTarget() {
			String result = getBuildAttribute(IMakeBuilderInfo.BUILD_TARGET_INCREMENTAL,
					getString(BuildInfoFactory.BUILD_TARGET_INCREMENTAL));
			try {
				result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result,
						false);
			} catch (CoreException e) {
			}
			return result;
		}

		@Override
		public void setCleanBuildTarget(String target) throws CoreException {
			putString(IMakeBuilderInfo.BUILD_TARGET_CLEAN, null);
			putString(BuildInfoFactory.BUILD_TARGET_CLEAN, target);
		}

		@Override
		public String getCleanBuildTarget() {
			String result = getBuildAttribute(IMakeBuilderInfo.BUILD_TARGET_CLEAN,
					getString(BuildInfoFactory.BUILD_TARGET_CLEAN));
			try {
				result = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(result,
						false);
			} catch (CoreException e) {
			}
			return result;
		}

		@Override
		public void setAutoBuildEnable(boolean enabled) throws CoreException {
			putString(BUILD_AUTO_ENABLED, String.valueOf(enabled));
		}

		@Override
		public boolean isAutoBuildEnable() {
			return getBoolean(BUILD_AUTO_ENABLED);
		}

		@Override
		public void setIncrementalBuildEnable(boolean enabled) throws CoreException {
			putString(BUILD_INCREMENTAL_ENABLED, String.valueOf(enabled));
		}

		@Override
		public boolean isIncrementalBuildEnabled() {
			return getBoolean(BUILD_INCREMENTAL_ENABLED);
		}

		@Override
		public void setFullBuildEnable(boolean enabled) throws CoreException {
			putString(BUILD_FULL_ENABLED, String.valueOf(enabled));
		}

		@Override
		public boolean isFullBuildEnabled() {
			return getBoolean(BUILD_FULL_ENABLED);
		}

		@Override
		public void setCleanBuildEnable(boolean enabled) throws CoreException {
			putString(BUILD_CLEAN_ENABLED, String.valueOf(enabled));
		}

		@Override
		public boolean isCleanBuildEnabled() {
			return getBoolean(BUILD_CLEAN_ENABLED);
		}

		@Override
		public String[] getErrorParsers() {
			String parsers = getString(ErrorParserManager.PREF_ERROR_PARSER);
			if (parsers != null && !parsers.isEmpty()) {
				StringTokenizer tok = new StringTokenizer(parsers, ";"); //$NON-NLS-1$
				List<String> list = new ArrayList<>(tok.countTokens());
				while (tok.hasMoreElements()) {
					list.add(tok.nextToken());
				}
				return list.toArray(new String[list.size()]);
			}
			return new String[0];
		}

		@Override
		public void setErrorParsers(String[] parsers) throws CoreException {
			StringBuilder buf = new StringBuilder();
			for (int i = 0; i < parsers.length; i++) {
				buf.append(parsers[i]).append(';');
			}
			putString(ErrorParserManager.PREF_ERROR_PARSER, buf.toString());
		}

		@Override
		public Map<String, String> getEnvironment() {
			return decodeMap(getString(ENVIRONMENT));
		}

		@Override
		public void setEnvironment(Map<String, String> env) throws CoreException {
			putString(ENVIRONMENT, encodeMap(env));
		}

		@Override
		public boolean appendEnvironment() {
			if (getString(BUILD_APPEND_ENVIRONMENT) != null) {
				return getBoolean(BUILD_APPEND_ENVIRONMENT);
			}
			return true;
		}

		@Override
		public void setAppendEnvironment(boolean append) throws CoreException {
			putString(BUILD_APPEND_ENVIRONMENT, String.valueOf(append));
		}

		public boolean getBoolean(String property) {
			return Boolean.parseBoolean(getString(property));
		}

		protected Map<String, String> decodeMap(String value) {
			Map<String, String> map = new HashMap<>();
			if (value != null) {
				StringBuilder envStr = new StringBuilder(value);
				String escapeChars = "|\\"; //$NON-NLS-1$
				char escapeChar = '\\';
				try {
					while (envStr.length() > 0) {
						int ndx = 0;
						while (ndx < envStr.length()) {
							if (escapeChars.indexOf(envStr.charAt(ndx)) != -1) {
								if (envStr.charAt(ndx - 1) == escapeChar) {
									// escaped '|' - remove '\' and continue on.
									envStr.deleteCharAt(ndx - 1);
									if (ndx == envStr.length()) {
										break;
									}
								}
								if (envStr.charAt(ndx) == '|')
									break;
							}
							ndx++;
						}
						StringBuilder line = new StringBuilder(envStr.substring(0, ndx));
						int lndx = 0;
						while (lndx < line.length()) {
							if (line.charAt(lndx) == '=') {
								if (line.charAt(lndx - 1) == escapeChar) {
									// escaped '=' - remove '\' and continue on.
									line.deleteCharAt(lndx - 1);
								} else {
									break;
								}
							}
							lndx++;
						}
						map.put(line.substring(0, lndx), line.substring(lndx + 1));
						envStr.delete(0, ndx + 1);
					}
				} catch (StringIndexOutOfBoundsException e) {
				}
			}
			return map;
		}

		protected String encodeMap(Map<String, String> values) {
			StringBuilder str = new StringBuilder();
			for (Entry<String, String> entry : values.entrySet()) {
				str.append(escapeChars(entry.getKey(), "=|\\", '\\')); //$NON-NLS-1$
				str.append("="); //$NON-NLS-1$
				str.append(escapeChars(entry.getValue(), "|\\", '\\')); //$NON-NLS-1$
				str.append("|"); //$NON-NLS-1$
			}
			return str.toString();
		}

		protected String escapeChars(String string, String escapeChars, char escapeChar) {
			StringBuilder str = new StringBuilder(string);
			for (int i = 0; i < str.length(); i++) {
				if (escapeChars.indexOf(str.charAt(i)) != -1) {
					str.insert(i, escapeChar);
					i++;
				}
			}
			return str.toString();
		}

		protected abstract void putString(String name, String value) throws CoreException;

		protected abstract String getString(String property);
	}

	private static class BuildInfoPreference extends AbstractBuildInfo {

		private Preferences prefs;
		private String builderID;
		private boolean useDefaults;

		BuildInfoPreference(Preferences prefs, String builderID, boolean useDefaults) {
			this.prefs = prefs;
			this.builderID = builderID;
			this.useDefaults = useDefaults;
		}

		@Override
		protected void putString(String name, String value) {
			if (useDefaults) {
				if (value != null) {
					prefs.setDefault(name, value);
				}
			} else {
				if (value == null) {
					prefs.setValue(name, prefs.getDefaultString(name));
					return;
				}
				prefs.setValue(name, value);
			}
		}

		@Override
		protected String getString(String property) {
			if (!prefs.contains(property)) {
				return null;
			}
			if (useDefaults) {
				return prefs.getDefaultString(property);
			}
			return prefs.getString(property);
		}

		@Override
		protected String getBuilderID() {
			return builderID;
		}
	}

	private static class BuildInfoProject extends AbstractBuildInfo {

		private IProject project;
		private String builderID;
		private Map<String, String> args;

		BuildInfoProject(IProject project, String builderID) throws CoreException {
			this.project = project;
			this.builderID = builderID;

			ICommand builder = null;

			// first, give the build-system a chance to return the build-command overlayed with data managed by it
			ICProjectDescription cProjectDescription = CoreModel.getDefault().getProjectDescription(project, false);
			if (cProjectDescription != null) {
				ICConfigurationDescription cConfigDescription = cProjectDescription.getActiveConfiguration();
				CConfigurationData configurationData = cConfigDescription.getConfigurationData();
				if (configurationData != null) {
					CBuildData buildData = configurationData.getBuildData();
					if (buildData != null) {
						builder = buildData.getBuildSpecCommand();
					}
				}
			}

			if (builder == null) {
				builder = MakeProjectNature.getBuildSpec(project.getDescription(), builderID);
				if (builder == null) {
					throw new CoreException(new Status(IStatus.ERROR, MakeCorePlugin.getUniqueIdentifier(), -1,
							MakeMessages.getString("BuildInfoFactory.Missing_Builder") + builderID, null)); //$NON-NLS-1$
				}
			}

			Map<String, String> builderArgs = builder.getArguments();
			args = builderArgs;
		}

		@Override
		protected void putString(String name, String value) throws CoreException {
			String curValue = args.get(name);
			if (curValue != null && curValue.equals(value)) {
				return;
			}
			if (value == null) {
				args.remove(name);
			} else {
				args.put(name, value);
			}
			IProjectDescription description = project.getDescription();
			ICommand builder = MakeProjectNature.getBuildSpec(description, builderID);
			builder.setArguments(args);
			builder.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, isAutoBuildEnable());
			builder.setBuilding(IncrementalProjectBuilder.FULL_BUILD, isFullBuildEnabled());
			builder.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, isIncrementalBuildEnabled());
			builder.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, isCleanBuildEnabled());
			MakeProjectNature.setBuildSpec(description, builder);
			project.setDescription(description, null);
		}

		@Override
		protected String getString(String name) {
			return args.get(name);
		}

		@Override
		protected String getBuilderID() {
			return builderID;
		}
	}

	private static class BuildInfoMap extends AbstractBuildInfo {

		private Map<String, String> args;
		private String builderID;

		BuildInfoMap(Map<String, String> args, String builderID) {
			this.args = args;
			this.builderID = builderID;
		}

		@Override
		protected void putString(String name, String value) {
			if (value == null) {
				args.remove(name);
			} else {
				args.put(name, value);
			}
		}

		@Override
		protected String getString(String name) {
			return args.get(name);
		}

		@Override
		protected String getBuilderID() {
			return builderID;
		}
	}

	public static IMakeBuilderInfo create(Preferences prefs, String builderID, boolean useDefaults) {
		return new BuildInfoFactory.BuildInfoPreference(prefs, builderID, useDefaults);
	}

	public static IMakeBuilderInfo create(IProject project, String builderID) throws CoreException {
		return new BuildInfoFactory.BuildInfoProject(project, builderID);
	}

	public static IMakeBuilderInfo create(Map<String, String> args, String builderID) {
		return new BuildInfoFactory.BuildInfoMap(args, builderID);
	}
}
