/*******************************************************************************
 * 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
 *     Andrew Obuchowicz (aobuchow@redhat.com) - Bug 548344
 *******************************************************************************/
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.TextGetSetEditingSupport;
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.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerEditor;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
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.TableViewerColumn;
import org.eclipse.jface.viewers.TableViewerEditor;
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.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
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);
			}
		});

		// Setup right-click context menu
		Menu menuTable = new Menu(table);
		table.setMenu(menuTable);

		// Create add environment variable menu item
		MenuItem miAdd = new MenuItem(menuTable, SWT.NONE);
		miAdd.setText(LaunchConfigurationsMessages.EnvironmentTab_Add_4);

		miAdd.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvAddButtonSelected();
			}
		});

		// Create copy environment variable menu item
		MenuItem miCopy = new MenuItem(menuTable, SWT.NONE);
		miCopy.setText(LaunchConfigurationsMessages.EnvironmentTab_Copy);

		miCopy.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvCopyButtonSelected();
			}
		});

		// Create paste environment variable menu item
		MenuItem miPaste = new MenuItem(menuTable, SWT.NONE);
		miPaste.setText(LaunchConfigurationsMessages.EnvironmentTab_Paste);

		miPaste.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvPasteButtonSelected();
			}
		});

		// Create remove environment variable menu item
		MenuItem miRemove = new MenuItem(menuTable, SWT.NONE);
		miRemove.setText(LaunchConfigurationsMessages.EnvironmentTab_Remove_6);
		miRemove.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				handleEnvRemoveButtonSelected();
			}
		});

		environmentTable.addSelectionChangedListener(new ISelectionChangedListener() {
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				IStructuredSelection selection = environmentTable.getStructuredSelection();
				if (selection.size() == 1) {
					miRemove.setText(LaunchConfigurationsMessages.EnvironmentTab_Remove_6);
				} else if (selection.size() > 1) {
					miRemove.setText(LaunchConfigurationsMessages.EnvironmentTab_Remove_All);
				}
			}
		});

		// Disable certain context menu item's if no table item is selected
		table.addListener(SWT.MenuDetect, new Listener() {
			@Override
			public void handleEvent(Event event) {
				if (table.getSelectionCount() <= 0) {
					miRemove.setEnabled(false);
					miCopy.setEnabled(false);
				} else {
					miRemove.setEnabled(true);
					miCopy.setEnabled(true);
				}
			}
		});


		// Setup and create Columns
		ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(environmentTable) {
			@Override
			protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
				return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
						|| event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
						|| event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
			}
		};

		int feature = ColumnViewerEditor.TABBING_HORIZONTAL | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
				| ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION;

		TableViewerEditor.create(environmentTable, actSupport, feature);

		// Setup environment variable name column
		final TableViewerColumn tcv1 = new TableViewerColumn(environmentTable, SWT.NONE, 0);
		tcv1.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				return ((EnvironmentVariable) element).getName();
			}
		});

		TableColumn tc1 = tcv1.getColumn();
		tc1.setText(envTableColumnHeaders[0]);
		tcv1.setEditingSupport(new TextGetSetEditingSupport<>(tcv1.getViewer(), EnvironmentVariable::getName,
				(EnvironmentVariable envVar, String value) -> {
					// Trim environment variable names
					String newName = value.trim();
					if (newName != null && !newName.isEmpty()) {
						if (!newName.equals(envVar.getName())) {
							if (canRenameVariable(newName)) {
								envVar.setName(newName);
								updateAppendReplace();
								updateLaunchConfigurationDialog();
							}
						}
					}
				}));

		// Setup environment variable value column
		final TableViewerColumn tcv2 = new TableViewerColumn(environmentTable, SWT.NONE, 1);
		tcv2.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				return ((EnvironmentVariable) element).getValue();
			}
		});

		TableColumn tc2 = tcv2.getColumn();
		tc2.setText(envTableColumnHeaders[1]);
		tcv2.setEditingSupport(
				new TextGetSetEditingSupport<>(tcv2.getViewer(), EnvironmentVariable::getValue, (envVar, value) -> {
					// Don't trim environment variable values
					envVar.setValue(value);
					updateAppendReplace();
					updateLaunchConfigurationDialog();
				}));

		// 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_Add_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) {
			// Trim the environment variable name but *NOT* the value
			addVariable(new EnvironmentVariable(name.trim(), value));
			updateAppendReplace();
		}
	}

	/**
	 * Returns whether the environment variable can be renamed to the given variable
	 * name. If the name is already used for another variable, the user decides with
	 * a dialog whether to overwrite the existing variable
	 *
	 * @param newVariableName the chosen name to give to the variable
	 * @return whether the new name should be used or not
	 */
	private boolean canRenameVariable(String newVariableName) {
		TableItem[] items = environmentTable.getTable().getItems();
		for (int i = 0; i < items.length; i++) {
			EnvironmentVariable existingVariable = (EnvironmentVariable) items[i].getData();
			if (existingVariable.getName().equals(newVariableName)) {

				boolean overWrite = MessageDialog.openQuestion(getShell(),
						LaunchConfigurationsMessages.EnvironmentTab_12,
						MessageFormat.format(LaunchConfigurationsMessages.EnvironmentTab_13,
								new Object[] { newVariableName }));
				if (!overWrite) {
					return false;
				}
				environmentTable.remove(existingVariable);
				return true;
			}
		}
		return true;
	}

	/**
	 * 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.contains(System.getProperty("line.separator"))) { //$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)) {
			// Trim the environment variable name but *NOT* the value
			if (addVariable(new EnvironmentVariable(name.trim(), 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.isEmpty()) {
			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) {
				}
			};
		}
	}
}
