/*******************************************************************************
 * Copyright (c) 2000, 2019 Keith Seitz 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:
 *     Keith Seitz (keiths@redhat.com) - initial implementation
 *     IBM Corporation - integration and code cleanup
 *     Jan Opacki (jan.opacki@gmail.com) bug 307139
 *     Axel Richard (Obeo) - Bug 41353 - Launch configurations prototypes
 *     Jens Reimann (jreimann@redhat.com) - add copy & paste support
 *******************************************************************************/
package org.eclipse.debug.ui;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.internal.ui.AbstractDebugCheckboxSelectionDialog;
import org.eclipse.debug.internal.ui.DebugPluginImages;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
import org.eclipse.debug.internal.ui.MultipleInputDialog;
import org.eclipse.debug.internal.ui.SWTFactory;
import org.eclipse.debug.internal.ui.launchConfigurations.EnvironmentVariable;
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsMessages;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.bindings.keys.ParseException;
import org.eclipse.jface.bindings.keys.SWTKeySupport;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.PlatformUI;

import com.ibm.icu.text.MessageFormat;

/**
 * Launch configuration tab for configuring the environment passed
 * into Runtime.exec(...) when a config is launched.
 * <p>
 * Clients may call {@link #setHelpContextId(String)} on this tab prior to control
 * creation to alter the default context help associated with this tab.
 * </p>
 * <p>
 * This class may be instantiated.
 * </p>
 * @since 3.0
 * @noextend This class is not intended to be sub-classed by clients.
 */
public class EnvironmentTab extends AbstractLaunchConfigurationTab {

	protected TableViewer environmentTable;
	protected String[] envTableColumnHeaders = {
		LaunchConfigurationsMessages.EnvironmentTab_Variable_1,
		LaunchConfigurationsMessages.EnvironmentTab_Value_2,
	};
	private static final String NAME_LABEL= LaunchConfigurationsMessages.EnvironmentTab_8;
	private static final String VALUE_LABEL= LaunchConfigurationsMessages.EnvironmentTab_9;
	protected static final String P_VARIABLE = "variable"; //$NON-NLS-1$
	protected static final String P_VALUE = "value"; //$NON-NLS-1$
	protected Button envAddButton;
	protected Button envEditButton;
	protected Button envRemoveButton;
	/**
	 * @since 3.14
	 */
	protected Button envCopyButton;
	/**
	 * @since 3.14
	 */
	protected Button envPasteButton;
	protected Button appendEnvironment;
	protected Button replaceEnvironment;
	protected Button envSelectButton;

	private KeyStroke copyKeyStroke;
	private KeyStroke pasteKeyStroke;

	/**
	 * Content provider for the environment table
	 */
	protected class EnvironmentVariableContentProvider implements IStructuredContentProvider {
		@Override
		public Object[] getElements(Object inputElement) {
			EnvironmentVariable[] elements = new EnvironmentVariable[0];
			ILaunchConfiguration config = (ILaunchConfiguration) inputElement;
			Map<String, String> m;
			try {
				m = config.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, (Map<String, String>) null);
			} catch (CoreException e) {
				DebugUIPlugin.log(new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), IStatus.ERROR, "Error reading configuration", e)); //$NON-NLS-1$
				return elements;
			}
			if (m != null && !m.isEmpty()) {
				elements = new EnvironmentVariable[m.size()];
				String[] varNames = new String[m.size()];
				m.keySet().toArray(varNames);
				for (int i = 0; i < m.size(); i++) {
					elements[i] = new EnvironmentVariable(varNames[i], m.get(varNames[i]));
				}
			}
			return elements;
		}
		@Override
		public void dispose() {
		}
		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			if (newInput == null){
				return;
			}
			if (viewer instanceof TableViewer){
				TableViewer tableViewer= (TableViewer) viewer;
				if (tableViewer.getTable().isDisposed()) {
					return;
				}
				tableViewer.setComparator(new ViewerComparator() {
					@Override
					public int compare(Viewer iviewer, Object e1, Object e2) {
						if (e1 == null) {
							return -1;
						} else if (e2 == null) {
							return 1;
						} else {
							return ((EnvironmentVariable)e1).getName().compareToIgnoreCase(((EnvironmentVariable)e2).getName());
						}
					}
				});
			}
		}
	}

	/**
	 * Label provider for the environment table
	 */
	public class EnvironmentVariableLabelProvider extends LabelProvider implements ITableLabelProvider {
		@Override
		public String getColumnText(Object element, int columnIndex) 	{
			String result = null;
			if (element != null) {
				EnvironmentVariable var = (EnvironmentVariable) element;
				switch (columnIndex) {
					case 0: // variable
						result = var.getName();
						break;
					case 1: // value
						result = var.getValue();
						break;
					default:
						break;
				}
			}
			return result;
		}
		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			if (columnIndex == 0) {
				return DebugPluginImages.getImage(IDebugUIConstants.IMG_OBJS_ENV_VAR);
			}
			return null;
		}
	}

	/**
	 * Constructs a new tab with default context help.
	 */
	public EnvironmentTab() {
		super();
		setHelpContextId(IDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_ENVIRONMENT_TAB);

		try {
			this.copyKeyStroke = KeyStroke.getInstance("M1+C"); //$NON-NLS-1$
		} catch (ParseException e) {
		}
		try {
			this.pasteKeyStroke = KeyStroke.getInstance("M1+V"); //$NON-NLS-1$
		} catch (ParseException e) {
		}
	}

	@Override
	public void createControl(Composite parent) {
		// Create main composite
		Composite mainComposite = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_HORIZONTAL);
		setControl(mainComposite);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), getHelpContextId());

		createEnvironmentTable(mainComposite);
		createTableButtons(mainComposite);
		createAppendReplace(mainComposite);

		Dialog.applyDialogFont(mainComposite);
	}

	/**
	 * Creates and configures the widgets which allow the user to
	 * choose whether the specified environment should be appended
	 * to the native environment or if it should completely replace it.
	 * @param parent the composite in which the widgets should be created
	 */
	protected void createAppendReplace(Composite parent) {
		Composite comp = SWTFactory.createComposite(parent, 1, 2, GridData.FILL_HORIZONTAL);
		appendEnvironment= createRadioButton(comp, LaunchConfigurationsMessages.EnvironmentTab_16);
		appendEnvironment.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				updateLaunchConfigurationDialog();
			}
		});
		replaceEnvironment= createRadioButton(comp, LaunchConfigurationsMessages.EnvironmentTab_17);
	}

	/**
	 * Updates the enablement of the append/replace widgets. The
	 * widgets should disable when there are no environment variables specified.
	 */
	protected void updateAppendReplace() {
		boolean enable= environmentTable.getTable().getItemCount() > 0;
		appendEnvironment.setEnabled(enable);
		replaceEnvironment.setEnabled(enable);
	}

	/**
	 * Creates and configures the table that displayed the key/value
	 * pairs that comprise the environment.
	 * @param parent the composite in which the table should be created
	 */
	protected void createEnvironmentTable(Composite parent) {
		Font font = parent.getFont();
		// Create label, add it to the parent to align the right side buttons with the top of the table
		SWTFactory.createLabel(parent, LaunchConfigurationsMessages.EnvironmentTab_Environment_variables_to_set__3, 2);
		// Create table composite
		Composite tableComposite = SWTFactory.createComposite(parent, font, 1, 1, GridData.FILL_BOTH, 0, 0);
		// Create table
		environmentTable = new TableViewer(tableComposite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
		Table table = environmentTable.getTable();
		table.setLayoutData(new GridData(GridData.FILL_BOTH));
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		table.setFont(font);
		environmentTable.setContentProvider(new EnvironmentVariableContentProvider());
		environmentTable.setLabelProvider(new EnvironmentVariableLabelProvider());
		environmentTable.setColumnProperties(new String[] {P_VARIABLE, P_VALUE});
		environmentTable.addSelectionChangedListener(new ISelectionChangedListener() {
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				handleTableSelectionChanged(event);
			}
		});
		environmentTable.addDoubleClickListener(new IDoubleClickListener() {
			@Override
			public void doubleClick(DoubleClickEvent event) {
				if (!environmentTable.getSelection().isEmpty()) {
					handleEnvEditButtonSelected();
				}
			}
		});
		// Create columns
		final TableColumn tc1 = new TableColumn(table, SWT.NONE, 0);
		tc1.setText(envTableColumnHeaders[0]);
		final TableColumn tc2 = new TableColumn(table, SWT.NONE, 1);
		tc2.setText(envTableColumnHeaders[1]);
		// Create table column layout
		TableColumnLayout tableColumnLayout = new TableColumnLayout(true);
		PixelConverter pixelConverter = new PixelConverter(font);
		tableColumnLayout.setColumnData(tc1, new ColumnWeightData(1, pixelConverter.convertWidthInCharsToPixels(20)));
		tableColumnLayout.setColumnData(tc2, new ColumnWeightData(2, pixelConverter.convertWidthInCharsToPixels(20)));
		tableComposite.setLayout(tableColumnLayout);

		environmentTable.getTable().addKeyListener(new KeyAdapter() {

			@Override
			public void keyReleased(KeyEvent e) {
				KeyStroke current = computeKeyStroke(e);
				if (current.equals(copyKeyStroke)) {
					handleEnvCopyButtonSelected();
				} else if (current.equals(pasteKeyStroke)) {
					handleEnvPasteButtonSelected();
				}
			}

		});
	}

	/**
	 * Responds to a selection changed event in the environment table
	 * @param event the selection change event
	 */
	protected void handleTableSelectionChanged(SelectionChangedEvent event) {
		int size = event.getStructuredSelection().size();
		envEditButton.setEnabled(size == 1);
		envRemoveButton.setEnabled(size > 0);
		envCopyButton.setEnabled(size > 0);
	}

	/**
	 * Creates the add/edit/remove buttons for the environment table
	 * @param parent the composite in which the buttons should be created
	 */
	protected void createTableButtons(Composite parent) {
		// Create button composite
		Composite buttonComposite = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_END, 0, 0);

		// Create buttons
		envAddButton = createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_New_4, null);
		envAddButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvAddButtonSelected();
			}
		});
		envSelectButton = createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_18, null);
		envSelectButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvSelectButtonSelected();
			}
		});
		envEditButton = createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_Edit_5, null);
		envEditButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvEditButtonSelected();
			}
		});
		envEditButton.setEnabled(false);
		envRemoveButton = createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_Remove_6, null);
		envRemoveButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvRemoveButtonSelected();
			}
		});
		envRemoveButton.setEnabled(false);
		envCopyButton = createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_Copy, null);
		envCopyButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvCopyButtonSelected();
			}
		});
		envCopyButton.setEnabled(false);
		envPasteButton = createPushButton(buttonComposite, LaunchConfigurationsMessages.EnvironmentTab_Paste, null);
		envPasteButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvPasteButtonSelected();
			}
		});
		envPasteButton.setEnabled(true);
	}

	/**
	 * Adds a new environment variable to the table.
	 */
	protected void handleEnvAddButtonSelected() {
		MultipleInputDialog dialog = new MultipleInputDialog(getShell(), LaunchConfigurationsMessages.EnvironmentTab_22);
		dialog.addTextField(NAME_LABEL, null, false);
		dialog.addVariablesField(VALUE_LABEL, null, true);

		if (dialog.open() != Window.OK) {
			return;
		}

		String name = dialog.getStringValue(NAME_LABEL);
		String value = dialog.getStringValue(VALUE_LABEL);

		if (name != null && value != null && name.length() > 0 && value.length() >0) {
			addVariable(new EnvironmentVariable(name.trim(), value.trim()));
			updateAppendReplace();
		}
	}

	/**
	 * Attempts to add the given variable. Returns whether the variable
	 * was added or not (as when the user answers not to overwrite an
	 * existing variable).
	 * @param variable the variable to add
	 * @return whether the variable was added
	 */
	protected boolean addVariable(EnvironmentVariable variable) {
		String name= variable.getName();
		TableItem[] items = environmentTable.getTable().getItems();
		for (int i = 0; i < items.length; i++) {
			EnvironmentVariable existingVariable = (EnvironmentVariable) items[i].getData();
			if (existingVariable.getName().equals(name)) {
				boolean overWrite = MessageDialog.openQuestion(getShell(), LaunchConfigurationsMessages.EnvironmentTab_12, MessageFormat.format(LaunchConfigurationsMessages.EnvironmentTab_13, new Object[] { name })); //
				if (!overWrite) {
					return false;
				}
				environmentTable.remove(existingVariable);
				break;
			}
		}
		environmentTable.add(variable);
		updateLaunchConfigurationDialog();
		return true;
	}

	/**
	 * Attempts to add the given variables. Returns the number of variables added
	 * (as when the user answers not to overwrite an existing variable).
	 *
	 * @param variables the variables to add
	 * @return the number of variables added
	 * @since 3.14
	 */
	protected int addVariables(List<EnvironmentVariable> variables) {
		if (variables.isEmpty()) {
			return 0;
		}

		List<EnvironmentVariable> remove = new LinkedList<>();
		List<EnvironmentVariable> conflicting = new LinkedList<>();
		Map<String, String> requested = variables.stream()
				.collect(Collectors.toMap(EnvironmentVariable::getName, EnvironmentVariable::getValue));

		for (TableItem item : environmentTable.getTable().getItems()) {
			EnvironmentVariable existingVariable = (EnvironmentVariable) item.getData();
			String name = existingVariable.getName();
			String currentValue = requested.get(name);
			if (currentValue != null) {
				remove.add(existingVariable);
				if (!currentValue.equals(existingVariable.getValue())) {
					conflicting.add(existingVariable);
				}
			}
		}

		if (!conflicting.isEmpty()) {
			String names = conflicting.stream().map(EnvironmentVariable::getName).collect(Collectors.joining(", ")); //$NON-NLS-1$
			boolean overWrite = MessageDialog.openQuestion(getShell(),
					LaunchConfigurationsMessages.EnvironmentTab_Paste_Overwrite_Title,
					MessageFormat.format(LaunchConfigurationsMessages.EnvironmentTab_Paste_Overwrite_Message,
							new Object[] { names })); //
			if (!overWrite) {
				return 0;
			}
		}

		remove.forEach(environmentTable::remove);
		variables.forEach(environmentTable::add);
		updateLaunchConfigurationDialog();

		return variables.size();
	}

	/**
	 * Displays a dialog that allows user to select native environment variables to
	 * add to the table.
	 */
	private void handleEnvSelectButtonSelected() {
		//get Environment Variables from the OS
		Map<String, EnvironmentVariable> envVariables = getNativeEnvironment();

		//get Environment Variables from the table
		TableItem[] items = environmentTable.getTable().getItems();
		for (int i = 0; i < items.length; i++) {
			EnvironmentVariable var = (EnvironmentVariable) items[i].getData();
			envVariables.remove(var.getName());
		}

		NativeEnvironmentSelectionDialog dialog = new NativeEnvironmentSelectionDialog(getShell(), envVariables);
		dialog.setTitle(LaunchConfigurationsMessages.EnvironmentTab_20);

		int button = dialog.open();
		if (button == Window.OK) {
			Object[] selected = dialog.getResult();
			for (int i = 0; i < selected.length; i++) {
				environmentTable.add(selected[i]);
			}
		}

		updateAppendReplace();
		updateLaunchConfigurationDialog();
	}

	/**
	 * Gets native environment variable from the LaunchManager. Creates EnvironmentVariable objects.
	 * @return Map of name - EnvironmentVariable pairs based on native environment.
	 */
	private Map<String, EnvironmentVariable> getNativeEnvironment() {
		Map<String, String> stringVars = DebugPlugin.getDefault().getLaunchManager().getNativeEnvironmentCasePreserved();
		HashMap<String, EnvironmentVariable> vars = new HashMap<>();
		for (Entry<String, String> entry : stringVars.entrySet()) {
			vars.put(entry.getKey(), new EnvironmentVariable(entry.getKey(), entry.getValue()));
		}
		return vars;
	}

	/**
	 * Creates an editor for the value of the selected environment variable.
	 */
	private void handleEnvEditButtonSelected() {
		IStructuredSelection sel = environmentTable.getStructuredSelection();
		EnvironmentVariable var= (EnvironmentVariable) sel.getFirstElement();
		if (var == null) {
			return;
		}
		String originalName= var.getName();
		String value= var.getValue();
		MultipleInputDialog dialog= new MultipleInputDialog(getShell(), LaunchConfigurationsMessages.EnvironmentTab_11);
		dialog.addTextField(NAME_LABEL, originalName, false);
		if(value != null && value.indexOf(System.getProperty("line.separator")) > -1) { //$NON-NLS-1$
			dialog.addMultilinedVariablesField(VALUE_LABEL, value, true);
		}
		else {
			dialog.addVariablesField(VALUE_LABEL, value, true);
		}

		if (dialog.open() != Window.OK) {
			return;
		}
		String name= dialog.getStringValue(NAME_LABEL);
		value= dialog.getStringValue(VALUE_LABEL);
		if (!originalName.equals(name)) {
			if (addVariable(new EnvironmentVariable(name, value))) {
				environmentTable.remove(var);
			}
		} else {
			var.setValue(value);
			environmentTable.update(var, null);
			updateLaunchConfigurationDialog();
		}
	}

	/**
	 * Removes the selected environment variable from the table.
	 */
	private void handleEnvRemoveButtonSelected() {
		IStructuredSelection sel = environmentTable.getStructuredSelection();
		try {
			environmentTable.getControl().setRedraw(false);
			for (Iterator<?> i = sel.iterator(); i.hasNext();) {
				EnvironmentVariable var = (EnvironmentVariable) i.next();
				environmentTable.remove(var);
			}
		} finally {
			environmentTable.getControl().setRedraw(true);
		}
		updateAppendReplace();
		updateLaunchConfigurationDialog();
	}

	/**
	 * Copy the currently selected table entries to the clipboard.
	 */
	private void handleEnvCopyButtonSelected() {
		Iterable<?> iterable = () -> environmentTable.getStructuredSelection().iterator();
		String data = StreamSupport.stream(iterable.spliterator(), false).filter(o -> o instanceof EnvironmentVariable)
				.map(EnvironmentVariable.class::cast).map(var -> String.format("%s=%s", var.getName(), var.getValue())) //$NON-NLS-1$
				.collect(Collectors.joining(System.lineSeparator()));

		Clipboard clipboard = new Clipboard(getShell().getDisplay());
		try {
			clipboard.setContents(new Object[] { data }, new Transfer[] { TextTransfer.getInstance() });
		} finally {
			clipboard.dispose();
		}
	}

	/**
	 * Extract the content from the clipboard and add the new content.
	 */
	private void handleEnvPasteButtonSelected() {
		Clipboard clipboard = new Clipboard(getShell().getDisplay());
		try {
			List<EnvironmentVariable> variables = convertEnvironmentVariablesFromData(
					clipboard.getContents(TextTransfer.getInstance()));
			addVariables(variables);
			updateAppendReplace();
		} finally {
			clipboard.dispose();
		}
	}

	/**
	 * Convert the clipboard data to a list of {@link EnvironmentVariable}s. <br>
	 * Only entries containing an equals sign ({@code =} will be considered.
	 *
	 * @param data The clipboard data. May be {@code null}, which will result in an
	 *             empty list.
	 * @return The resulting and valid {@link EnvironmentVariable}s in an
	 *         unmodifiable list.
	 */
	private static List<EnvironmentVariable> convertEnvironmentVariablesFromData(Object data) {
		if (!(data instanceof String)) {
			return Collections.emptyList();
		}

		String entries[] = ((String) data).split("\\R"); //$NON-NLS-1$
		List<EnvironmentVariable> result = new ArrayList<>(entries.length);
		for (String entry : entries) {
			int idx = entry.indexOf('=');
			if (idx < 1) {
				continue;
			}
			// the name is trimmed ...
			String name = entry.substring(0, idx).trim();
			// .. but the value is *not* trimmed
			String value = entry.substring(idx + 1);
			result.add(new EnvironmentVariable(name, value));
		}
		return Collections.unmodifiableList(result);
	}

	/**
	 * Updates the environment table for the given launch configuration
	 * @param configuration the configuration to use as input for the backing table
	 */
	protected void updateEnvironment(ILaunchConfiguration configuration) {
		environmentTable.setInput(configuration);
	}

	@Override
	public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
		configuration.removeAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES);
	}

	@Override
	public void initializeFrom(ILaunchConfiguration configuration) {
		boolean append= true;
		try {
			append = configuration.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
		} catch (CoreException e) {
			DebugUIPlugin.log(e.getStatus());
		}
		if (append) {
			appendEnvironment.setSelection(true);
			replaceEnvironment.setSelection(false);
		} else {
			replaceEnvironment.setSelection(true);
			appendEnvironment.setSelection(false);
		}
		updateEnvironment(configuration);
		updateAppendReplace();
	}

	/**
	 * Stores the environment in the given configuration
	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
	 */
	@Override
	public void performApply(ILaunchConfigurationWorkingCopy configuration) {
		// Convert the table's items into a Map so that this can be saved in the
		// configuration's attributes.
		TableItem[] items = environmentTable.getTable().getItems();
		Map<String, String> map = new HashMap<>(items.length);
		for (int i = 0; i < items.length; i++) {
			EnvironmentVariable var = (EnvironmentVariable) items[i].getData();
			map.put(var.getName(), var.getValue());
		}
		if (map.size() == 0) {
			configuration.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, (Map<String, String>) null);
		} else {
			configuration.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, map);
		}

		if(appendEnvironment.getSelection()) {
			ILaunchConfiguration orig = configuration.getOriginal();
			boolean hasTrueValue = false;
			if(orig != null) {
				try {
					hasTrueValue = orig.hasAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES) &&
						orig.getAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
				} catch (CoreException e) {
					DebugUIPlugin.log(e.getStatus());
				}
			}
			if (hasTrueValue) {
				configuration.setAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
			} else {
				configuration.removeAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES);
			}
		} else {
			configuration.setAttribute(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, false);
		}
	}

	@Override
	public String getName() {
		return LaunchConfigurationsMessages.EnvironmentTab_Environment_7;
	}

	/**
	 * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getId()
	 *
	 * @since 3.3
	 */
	@Override
	public String getId() {
		return "org.eclipse.debug.ui.environmentTab"; //$NON-NLS-1$
	}

	@Override
	public Image getImage() {
		return DebugPluginImages.getImage(IDebugUIConstants.IMG_OBJS_ENVIRONMENT);
	}

	@Override
	public void activated(ILaunchConfigurationWorkingCopy workingCopy) {
		// do nothing when activated
	}

	@Override
	public void deactivated(ILaunchConfigurationWorkingCopy workingCopy) {
		// do nothing when deactivated
	}

	/**
	 * @since 3.13
	 */
	@Override
	protected void initializeAttributes() {
		super.initializeAttributes();
		getAttributesLabelsForPrototype().put(ILaunchManager.ATTR_APPEND_ENVIRONMENT_VARIABLES, LaunchConfigurationsMessages.EnvironmentTab_AttributeLabel_AppendEnvironmentVariables);
		getAttributesLabelsForPrototype().put(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, LaunchConfigurationsMessages.EnvironmentTab_AttributeLabel_EnvironmentVariables);
	}

	private KeyStroke computeKeyStroke(KeyEvent e) {
		int accelerator = SWTKeySupport.convertEventToUnmodifiedAccelerator(e);
		return SWTKeySupport.convertAcceleratorToKeyStroke(accelerator);
	}

	/**
	 * This dialog allows users to select one or more known native environment variables from a list.
	 */
	private class NativeEnvironmentSelectionDialog extends AbstractDebugCheckboxSelectionDialog {

		private Object fInput;

		public NativeEnvironmentSelectionDialog(Shell parentShell, Object input) {
			super(parentShell);
			fInput = input;
			setShellStyle(getShellStyle() | SWT.RESIZE);
			setShowSelectAllButtons(true);
		}

		@Override
		protected String getDialogSettingsId() {
			return IDebugUIConstants.PLUGIN_ID + ".ENVIRONMENT_TAB.NATIVE_ENVIROMENT_DIALOG"; //$NON-NLS-1$
		}

		@Override
		protected String getHelpContextId() {
			return IDebugHelpContextIds.SELECT_NATIVE_ENVIRONMENT_DIALOG;
		}

		@Override
		protected Object getViewerInput() {
			return fInput;
		}

		@Override
		protected String getViewerLabel() {
			return LaunchConfigurationsMessages.EnvironmentTab_19;
		}

		@Override
		protected IBaseLabelProvider getLabelProvider() {
			return new ILabelProvider() {
				@Override
				public Image getImage(Object element) {
					return DebugPluginImages.getImage(IDebugUIConstants.IMG_OBJS_ENVIRONMENT);
				}
				@Override
				public String getText(Object element) {
					EnvironmentVariable var = (EnvironmentVariable) element;
					return MessageFormat.format(LaunchConfigurationsMessages.EnvironmentTab_7, new Object[] {
							var.getName(), var.getValue() });
				}
				@Override
				public void addListener(ILabelProviderListener listener) {
				}
				@Override
				public void dispose() {
				}
				@Override
				public boolean isLabelProperty(Object element, String property) {
					return false;
				}
				@Override
				public void removeListener(ILabelProviderListener listener) {
				}
			};
		}

		@Override
		protected IContentProvider getContentProvider() {
			return new IStructuredContentProvider() {
				@Override
				public Object[] getElements(Object inputElement) {
					EnvironmentVariable[] elements = null;
					if (inputElement instanceof HashMap) {
						Comparator<Object> comparator = new Comparator<Object>() {
							@Override
							public int compare(Object o1, Object o2) {
								String s1 = (String) o1;
								String s2 = (String) o2;
								return s1.compareTo(s2);
							}
						};
						TreeMap<Object, Object> envVars = new TreeMap<>(comparator);
						envVars.putAll((Map<?, ?>) inputElement);
						elements = new EnvironmentVariable[envVars.size()];
						int index = 0;
						for (Iterator<Object> iterator = envVars.keySet().iterator(); iterator.hasNext(); index++) {
							Object key = iterator.next();
							elements[index] = (EnvironmentVariable) envVars.get(key);
						}
					}
					return elements;
				}
				@Override
				public void dispose() {
				}
				@Override
				public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
				}
			};
		}
	}
}
