/*******************************************************************************
 * Copyright (c) 2015, 2016, 2017 Red Hat Inc. and others.
 * 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:
 *     Red Hat - Initial Contribution
 *******************************************************************************/
package org.eclipse.linuxtools.docker.ui.launch;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.linuxtools.docker.core.DockerConnectionManager;
import org.eclipse.linuxtools.docker.core.DockerException;
import org.eclipse.linuxtools.docker.core.EnumDockerLoggingStatus;
import org.eclipse.linuxtools.docker.core.IDockerConnection;
import org.eclipse.linuxtools.docker.core.IDockerContainerConfig;
import org.eclipse.linuxtools.docker.core.IDockerContainerExit;
import org.eclipse.linuxtools.docker.core.IDockerContainerInfo;
import org.eclipse.linuxtools.docker.core.IDockerHostConfig;
import org.eclipse.linuxtools.docker.core.IDockerImage;
import org.eclipse.linuxtools.docker.core.IDockerImageInfo;
import org.eclipse.linuxtools.docker.core.IDockerPortBinding;
import org.eclipse.linuxtools.docker.ui.Activator;
import org.eclipse.linuxtools.internal.docker.core.DockerConnection;
import org.eclipse.linuxtools.internal.docker.core.DockerContainerConfig;
import org.eclipse.linuxtools.internal.docker.core.DockerHostConfig;
import org.eclipse.linuxtools.internal.docker.core.DockerPortBinding;
import org.eclipse.linuxtools.internal.docker.ui.consoles.ConsoleOutputStream;
import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole;
import org.eclipse.linuxtools.internal.docker.ui.launch.ContainerCommandProcess;
import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;

public class ContainerLauncher {

	private static final String ERROR_CREATING_CONTAINER = "ContainerCreateError.msg"; //$NON-NLS-1$
	private static final String ERROR_LAUNCHING_CONTAINER = "ContainerLaunchError.msg"; //$NON-NLS-1$
	private static final String ERROR_NO_CONNECTIONS = "ContainerNoConnections.msg"; //$NON-NLS-1$
	private static final String ERROR_NO_CONNECTION_WITH_URI = "ContainerNoConnectionWithURI.msg"; //$NON-NLS-1$

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

	private static RunConsole console;

	private static Map<IProject, ID> fidMap = new HashMap<>();

	private static Object lockObject = new Object();
	private static Map<String, Map<String, Set<String>>> copiedVolumesMap = null;

	private class CopyVolumesJob extends Job {

		private static final String COPY_VOLUMES_JOB_TITLE = "ContainerLaunch.copyVolumesJob.title"; //$NON-NLS-1$
		private static final String COPY_VOLUMES_DESC = "ContainerLaunch.copyVolumesJob.desc"; //$NON-NLS-1$
		private static final String COPY_VOLUMES_TASK = "ContainerLaunch.copyVolumesJob.task"; //$NON-NLS-1$
		private static final String ERROR_COPYING_VOLUME = "ContainerLaunch.copyVolumesJob.error"; //$NON-NLS-1$

		private final Set<String> volumes;
		private final IDockerConnection connection;
		private final String containerId;

		public CopyVolumesJob(Set<String> volumes,
				IDockerConnection connection,
				String containerId) {
			super(Messages.getString(COPY_VOLUMES_JOB_TITLE));
			this.volumes = volumes;
			this.connection = connection;
			this.containerId = containerId;
		}

		@Override
		protected IStatus run(IProgressMonitor monitor) {
			monitor.beginTask(
					Messages.getFormattedString(COPY_VOLUMES_DESC, containerId),
					volumes.size());
			Iterator<String> iterator = volumes.iterator();
			IStatus status = Status.OK_STATUS;
			// for each remote volume, copy from host to Container volume
			while (iterator.hasNext()) {
				if (monitor.isCanceled()) {
					monitor.done();
					return Status.CANCEL_STATUS;
				}
				String directory = iterator.next();
				if (!directory.endsWith("/")) { //$NON-NLS-1$
					directory = directory + "/"; //$NON-NLS-1$
				}
				monitor.setTaskName(Messages
						.getFormattedString(COPY_VOLUMES_TASK, directory));
				try {
					((DockerConnection) connection).copyToContainer(directory,
							containerId, directory);
					monitor.worked(1);
				} catch (DockerException | InterruptedException
						| IOException e) {
					monitor.done();
					final String dir = directory;
					Display.getDefault().syncExec(() -> MessageDialog.openError(
							PlatformUI.getWorkbench().getActiveWorkbenchWindow()
									.getShell(),
							Messages.getFormattedString(ERROR_COPYING_VOLUME,
									new String[] { dir, containerId }),
							e.getMessage()));
					status = new Status(IStatus.ERROR, Activator.PLUGIN_ID,
							e.getMessage());
				} finally {
					monitor.done();
				}
			}
			return status;
		}

	}

	private class CopyVolumesFromImageJob extends Job {

		private static final String COPY_VOLUMES_FROM_JOB_TITLE = "ContainerLaunch.copyVolumesFromJob.title"; //$NON-NLS-1$
		private static final String COPY_VOLUMES_FROM_DESC = "ContainerLaunch.copyVolumesFromJob.desc"; //$NON-NLS-1$
		private static final String COPY_VOLUMES_FROM_TASK = "ContainerLaunch.copyVolumesFromJob.task"; //$NON-NLS-1$
		// private static final String ERROR_COPYING_VOLUME =
		// "ContainerLaunch.copyVolumesFromJob.error"; //$NON-NLS-1$

		private final List<String> volumes;
		private final IDockerConnection connection;
		private final String image;
		private final IPath target;
		private Set<String> dirList;

		public CopyVolumesFromImageJob(
				IDockerConnection connection,
				String image, List<String> volumes, IPath target) {
			super(Messages.getString(COPY_VOLUMES_FROM_JOB_TITLE));
			this.volumes = volumes;
			this.connection = connection;
			this.image = image;
			this.target = target;
			Map<String, Set<String>> dirMap = null;
			synchronized (lockObject) {
				String uri = connection.getUri();
				dirMap = copiedVolumesMap.get(uri);
				if (dirMap == null) {
					dirMap = new HashMap<>();
					copiedVolumesMap.put(uri, dirMap);
				}
				dirList = dirMap.get(image);
				if (dirList == null) {
					dirList = new HashSet<>();
					dirMap.put(image, dirList);
				}
			}
		}

		@Override
		protected IStatus run(final IProgressMonitor monitor) {
			monitor.beginTask(
					Messages.getFormattedString(COPY_VOLUMES_FROM_DESC, image),
					volumes.size());
			String containerId = null;
			try {
				IDockerImage dockerImage = ((DockerConnection) connection)
						.getImageByTag(image);
				// if there is a .image_id file, check the image id to ensure
				// the user hasn't loaded a new version which may have
				// different header files installed.
				IPath imageFilePath = target.append(".image_id"); //$NON-NLS-1$
				File imageFile = imageFilePath.toFile();
				boolean needImageIdFile = !imageFile.exists();
				if (!needImageIdFile) {
					try (FileReader reader = new FileReader(imageFile);
							BufferedReader bufferReader = new BufferedReader(
									reader);) {
						String imageId = bufferReader.readLine();
						if (!dockerImage.id().equals(imageId)) {
							// if image id has changed...all bets are off
							// and we must reload all directories
							dirList.clear();
							needImageIdFile = true;
						}
					} catch (IOException e) {
						// ignore
					}
				}
				if (needImageIdFile) {
					try (FileWriter writer = new FileWriter(imageFile);
							BufferedWriter bufferedWriter = new BufferedWriter(
									writer);) {
						bufferedWriter.write(dockerImage.id());
						bufferedWriter.newLine();
					} catch (IOException e) {
						// ignore
					}
				}
				DockerContainerConfig.Builder builder = new DockerContainerConfig.Builder()
						.cmd("/bin/sh").image(image); //$NON-NLS-1$
				IDockerContainerConfig config = builder.build();
				DockerHostConfig.Builder hostBuilder = new DockerHostConfig.Builder();
				IDockerHostConfig hostConfig = hostBuilder.build();
				containerId = ((DockerConnection) connection)
						.createContainer(config, hostConfig, null);
				for (String volume : volumes) {
					if (monitor.isCanceled()) {
						monitor.done();
						return Status.CANCEL_STATUS;
					}
					if (volume.contains("${ProjName}")) { //$NON-NLS-1$
						monitor.worked(1);
						continue;
					}
					// if we have already copied the directory either directly
					// or as part of a parent directory copy, then skip to next
					// volume.
					for (String path : dirList) {
						if (volume.equals(path)
								|| (volume.startsWith(path) && volume.charAt(
										path.length()) == File.separatorChar)) {
							monitor.worked(1);
							continue;
						}
					}
					try {
						monitor.setTaskName(Messages.getFormattedString(
								COPY_VOLUMES_FROM_TASK, volume));
						monitor.worked(1);


						InputStream in = ((DockerConnection) connection)
								.copyContainer(containerId, volume);

						synchronized (lockObject) {
							dirList.add(volume);
						}

						/*
						 * The input stream from copyContainer might be
						 * incomplete or non-blocking so we should wrap it in a
						 * stream that is guaranteed to block until data is
						 * available.
						 */
						TarArchiveInputStream k = new TarArchiveInputStream(
								new BlockingInputStream(in));
						TarArchiveEntry te = null;
						target.toFile().mkdirs();
						IPath currDir = target.append(volume)
								.removeLastSegments(1);
						currDir.toFile().mkdirs();
						while ((te = k.getNextTarEntry()) != null) {
							long size = te.getSize();
							IPath path = currDir;
							path = path.append(te.getName());
							File f = new File(path.toOSString());
							if (te.isDirectory()) {
								f.mkdir();
								continue;
							} else {
								f.createNewFile();
							}
							FileOutputStream os = new FileOutputStream(f);
							int bufferSize = ((int) size > 4096 ? 4096
									: (int) size);
							byte[] barray = new byte[bufferSize];
							int result = -1;
							while ((result = k.read(barray, 0,
									bufferSize)) > -1) {
								if (monitor.isCanceled()) {
									monitor.done();
									k.close();
									os.close();
									return Status.CANCEL_STATUS;
								}
								os.write(barray, 0, result);
							}
							os.close();
						}
						k.close();
					} catch (final DockerException e) {
						// ignore
					}
				}
			} catch (InterruptedException e) {
				// do nothing
			} catch (IOException e) {
				Activator.log(e);
			} catch (DockerException e1) {
				Activator.log(e1);
			} finally {
				if (containerId != null) {
					try {
						((DockerConnection) connection)
								.removeContainer(containerId);
					} catch (DockerException | InterruptedException e) {
						// ignore
					}
				}
				monitor.done();
			}
			return Status.OK_STATUS;
		}
	}

	/**
	 * A blocking input stream that waits until data is available.
	 */
	private class BlockingInputStream extends InputStream {
		private InputStream in;

		public BlockingInputStream(InputStream in) {
			this.in = in;
		}

		@Override
		public int read() throws IOException {
			return in.read();
		}
	}

	@Override
	protected void finalize() throws Throwable {
		synchronized (lockObject) {
			if (copiedVolumesMap != null) {
				IPath pluginPath = Platform.getStateLocation(
						Platform.getBundle(Activator.PLUGIN_ID));
				IPath path = pluginPath.append(DIRFILE_NAME);

				File dirFile = path.toFile();
				FileOutputStream f = new FileOutputStream(dirFile);
				try (ObjectOutputStream oos = new ObjectOutputStream(f)) {
					oos.writeObject(copiedVolumesMap);
				}
			}
		}
		super.finalize();
	}

	public ContainerLauncher() {
		initialize();
	}

	@SuppressWarnings("unchecked")
	private void initialize() {
		synchronized (lockObject) {
			if (copiedVolumesMap == null) {
				IPath pluginPath = Platform.getStateLocation(
						Platform.getBundle(Activator.PLUGIN_ID));
				IPath path = pluginPath.append(DIRFILE_NAME);

				File dirFile = path.toFile();
				if (dirFile.exists()) {
					try (FileInputStream f = new FileInputStream(dirFile)) {
						try (ObjectInputStream ois = new ObjectInputStream(f)) {
							copiedVolumesMap = (Map<String, Map<String, Set<String>>>) ois
									.readObject();
						} catch (ClassNotFoundException
								| FileNotFoundException e) {
							// should never happen
							e.printStackTrace();
						}
					} catch (IOException e) {
						// will handle this below
					}
				}
			}
			if (copiedVolumesMap == null) {
				copiedVolumesMap = new HashMap<>();
			}
		}
	}

	/**
	 * Perform a launch of a command in a container.
	 * 
	 * @param id
	 *            - id of caller to use to distinguish console owner
	 * @param listener
	 *            - optional listener of the run console
	 * @param connectionUri
	 *            - the specified connection to use
	 * @param image
	 *            - the image to use
	 * @param command
	 *            - command to run
	 * @param commandDir
	 *            - directory command requires or null
	 * @param workingDir
	 *            - working directory or null
	 * @param additionalDirs
	 *            - additional directories to mount or null
	 * @param origEnv
	 *            - original environment if we are appending to our existing
	 *            environment
	 * @param envMap
	 *            - map of environment variable settings
	 * @param ports
	 *            - ports to expose
	 * @param keep
	 *            - keep container after running
	 * @param stdinSupport
	 *            - true if stdin support is required, false otherwise
	 */
	public void launch(String id, IContainerLaunchListener listener,
			final String connectionUri,
			String image, String command, String commandDir, String workingDir,
			List<String> additionalDirs, Map<String, String> origEnv,
			Map<String, String> envMap, List<String> ports, boolean keep,
			boolean stdinSupport) {
		launch(id, listener, connectionUri, image, command, commandDir,
				workingDir, additionalDirs, origEnv, envMap, ports, keep,
				stdinSupport, false);
	}

	/**
	 * Perform a launch of a command in a container.
	 * 
	 * @param id
	 *            - id of caller to use to distinguish console owner
	 * @param listener
	 *            - optional listener of the run console
	 * @param connectionUri
	 *            - the specified connection to use
	 * @param image
	 *            - the image to use
	 * @param command
	 *            - command to run
	 * @param commandDir
	 *            - directory command requires or null
	 * @param workingDir
	 *            - working directory or null
	 * @param additionalDirs
	 *            - additional directories to mount or null
	 * @param origEnv
	 *            - original environment if we are appending to our existing
	 *            environment
	 * @param envMap
	 *            - map of environment variable settings
	 * @param ports
	 *            - ports to expose
	 * @param keep
	 *            - keep container after running
	 * @param stdinSupport
	 *            - true if stdin support is required, false otherwise
	 * @param privilegedMode
	 *            - true if privileged mode is required, false otherwise
	 * @since 2.1
	 */
	public void launch(String id, IContainerLaunchListener listener,
			final String connectionUri, String image, String command,
			String commandDir, String workingDir, List<String> additionalDirs,
			Map<String, String> origEnv, Map<String, String> envMap,
			List<String> ports, boolean keep, boolean stdinSupport,
			boolean privilegedMode) {
		launch(id, listener, connectionUri, image, command, commandDir,
				workingDir, additionalDirs, origEnv, envMap, ports, keep,
				stdinSupport, privilegedMode, null);
	}

	/**
	 * Perform a launch of a command in a container.
	 * 
	 * @param id
	 *            - id of caller to use to distinguish console owner
	 * @param listener
	 *            - optional listener of the run console
	 * @param connectionUri
	 *            - the specified connection to use
	 * @param image
	 *            - the image to use
	 * @param command
	 *            - command to run
	 * @param commandDir
	 *            - directory command requires or null
	 * @param workingDir
	 *            - working directory or null
	 * @param additionalDirs
	 *            - additional directories to mount or null
	 * @param origEnv
	 *            - original environment if we are appending to our existing
	 *            environment
	 * @param envMap
	 *            - map of environment variable settings
	 * @param ports
	 *            - ports to expose
	 * @param keep
	 *            - keep container after running
	 * @param stdinSupport
	 *            - true if stdin support is required, false otherwise
	 * @param privilegedMode
	 *            - true if privileged mode is required, false otherwise
	 * @param labels
	 *            - Map of labels for the container
	 * @since 2.2
	 */
	public void launch(String id, IContainerLaunchListener listener,
			final String connectionUri, String image, String command,
			String commandDir, String workingDir, List<String> additionalDirs,
			Map<String, String> origEnv, Map<String, String> envMap,
			List<String> ports, boolean keep, boolean stdinSupport,
			boolean privilegedMode, Map<String, String> labels) {

		final String LAUNCH_TITLE = "ContainerLaunch.title"; //$NON-NLS-1$
		final String LAUNCH_EXITED_TITLE = "ContainerLaunchExited.title"; //$NON-NLS-1$

		final List<String> env = new ArrayList<>();
		env.addAll(toList(origEnv));
		env.addAll(toList(envMap));


		final List<String> cmdList = getCmdList(command);

		final Set<String> exposedPorts = new HashSet<>();
		final Map<String, List<IDockerPortBinding>> portBindingsMap = new HashMap<>();

		if (ports != null) {
			for (String port : ports) {
				port = port.trim();
				if (port.length() > 0) {
					String[] segments = port.split(":"); //$NON-NLS-1$
					if (segments.length == 1) { // containerPort
						exposedPorts.add(segments[0]);
						portBindingsMap
								.put(segments[0],
										Arrays.asList((IDockerPortBinding) new DockerPortBinding(
												"", ""))); //$NON-NLS-1$ //$NON-NLS-2$
					} else if (segments.length == 2) { // hostPort:containerPort
						exposedPorts.add(segments[1]);
						portBindingsMap
								.put(segments[1],
										Arrays.asList((IDockerPortBinding) new DockerPortBinding(
												"", segments[0]))); //$NON-NLS-1$ //$NON-NLS-2$
					} else if (segments.length == 3) { // either
						// ip:hostPort:containerPort
						// or ip::containerPort
						exposedPorts.add(segments[1]);
						if (segments[1].isEmpty()) {
							portBindingsMap
									.put(segments[2],
											Arrays.asList((IDockerPortBinding) new DockerPortBinding(
													"", segments[0]))); //$NON-NLS-1$ //$NON-NLS-2$
						} else {
							portBindingsMap
									.put(segments[2],
											Arrays.asList((IDockerPortBinding) new DockerPortBinding(
													segments[0], segments[1]))); //$NON-NLS-1$ //$NON-NLS-2$
						}
					}
				}
			}

		}

		// Note we only pass volumes to the config if we have a
		// remote daemon. Local mounted volumes are passed
		// via the HostConfig binds setting

		DockerContainerConfig.Builder builder = new DockerContainerConfig.Builder()
				.openStdin(stdinSupport)
				.cmd(cmdList)
				.image(image)
				.workingDir(workingDir);
		// add any exposed ports as needed
		if (exposedPorts.size() > 0)
			builder = builder.exposedPorts(exposedPorts);

		// add any labels if specified
		if (labels != null)
			builder = builder.labels(labels);

		if (!DockerConnectionManager.getInstance().hasConnections()) {
			Display.getDefault()
					.syncExec(() -> MessageDialog.openError(
							PlatformUI.getWorkbench().getActiveWorkbenchWindow()
									.getShell(),
							DVMessages.getString(ERROR_LAUNCHING_CONTAINER),
							DVMessages.getString(ERROR_NO_CONNECTIONS)));
			return;
		}

		// Try and use the specified connection that was used before,
		// otherwise, open an error
		final IDockerConnection connection = DockerConnectionManager
				.getInstance().getConnectionByUri(connectionUri);
		if (connection == null) {
			Display.getDefault()
					.syncExec(() -> MessageDialog.openError(
							PlatformUI.getWorkbench().getActiveWorkbenchWindow()
									.getShell(),
							DVMessages.getString(ERROR_LAUNCHING_CONTAINER),
							DVMessages.getFormattedString(
									ERROR_NO_CONNECTION_WITH_URI,
									connectionUri)));
			return;
		}

		DockerHostConfig.Builder hostBuilder = new DockerHostConfig.Builder()
				.privileged(privilegedMode).securityOpt("seccomp:unconfined"); //$NON-NLS-1$


		final Set<String> remoteVolumes = new TreeSet<>();
		if (!((DockerConnection) connection).isLocal()) {
			// if using remote daemon, we have to
			// handle volume mounting differently.
			// Instead we mount empty volumes and copy
			// the host data over before starting.
			if (additionalDirs != null) {
				for (String dir : additionalDirs) {
					remoteVolumes.add(dir); // $NON-NLS-1$
				}
			}
			if (workingDir != null)
				remoteVolumes.add(workingDir); // $NON-NLS-1$
			if (commandDir != null)
				remoteVolumes.add(commandDir); // $NON-NLS-1$
			builder = builder.volumes(remoteVolumes);
		} else {
			// Running daemon on local host.
			// Add mounts for any directories we need to run the executable.
			// When we add mount points, we need entries of the form:
			// hostname:mountname:Z.
			// In our case, we want all directories mounted as-is so the
			// executable will run as the user expects.
			final List<String> volumes = new ArrayList<>();
			if (additionalDirs != null) {
				for (String dir : additionalDirs) {
					volumes.add(dir + ":" + dir + ":Z"); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
			if (workingDir != null) {
				volumes.add(workingDir + ":" + workingDir + ":Z"); //$NON-NLS-1$ //$NON-NLS-2$
			}
			if (commandDir != null) {
				volumes.add(commandDir + ":" + commandDir + ":Z"); //$NON-NLS-1$ //$NON-NLS-2$
			}
			hostBuilder = hostBuilder.binds(volumes);
		}

		final DockerContainerConfig config = builder.build();

		// add any port bindings if specified
		if (portBindingsMap.size() > 0)
			hostBuilder = hostBuilder.portBindings(portBindingsMap);

		final IDockerHostConfig hostConfig = hostBuilder.build();

		final String imageName = image;
		final boolean keepContainer = keep;
		final String consoleId = id;
		final IContainerLaunchListener containerListener = listener;

		Thread t = new Thread(() -> {
			// create the container
			String containerId = null;
			try {
				containerId = ((DockerConnection) connection)
						.createContainer(config, hostConfig, null);
				if (!((DockerConnection) connection).isLocal()) {
					// if daemon is remote, we need to copy
					// data over from the host.
					if (!remoteVolumes.isEmpty()) {
						CopyVolumesJob job = new CopyVolumesJob(remoteVolumes,
								connection, containerId);
						job.schedule();
						job.join();
						if (job.getResult() != Status.OK_STATUS)
							return;
					}
				}
				OutputStream stream = null;
				RunConsole oldConsole = getConsole();
				final RunConsole rc = RunConsole.findConsole(containerId,
						consoleId);
				setConsole(rc);
				rc.clearConsole();
				if (oldConsole != null)
					RunConsole.removeConsole(oldConsole);
				Display.getDefault()
						.syncExec(() -> rc.setTitle(Messages.getFormattedString(
								LAUNCH_TITLE, new String[] { cmdList.get(0),
										imageName })));
				// if (!rc.isAttached()) {
				rc.attachToConsole(connection, containerId);
				// }
				if (rc != null) {
					stream = rc.getOutputStream();
					if (containerListener != null) {
						((ConsoleOutputStream) stream)
								.addConsoleListener(containerListener);
					}
				}
				// Create a unique logging thread id which has container id
				// and console id
				String loggingId = containerId + "." + consoleId;
				((DockerConnection) connection).startContainer(containerId,
						loggingId, stream);
				if (rc != null)
					rc.showConsole();
				if (containerListener != null) {
					IDockerContainerInfo info = ((DockerConnection) connection)
							.getContainerInfo(containerId);
					containerListener.containerInfo(info);
				}

				// Wait for the container to finish
				final IDockerContainerExit status = ((DockerConnection) connection)
						.waitForContainer(containerId);
				Display.getDefault().syncExec(() -> {
					rc.setTitle(
							Messages.getFormattedString(LAUNCH_EXITED_TITLE,
									new String[] {
											status.statusCode().toString(),
											cmdList.get(0), imageName }));
					rc.showConsole();
				});

				// Let any container listener know that the container is
				// finished
				if (containerListener != null)
					containerListener.done();

				if (!keepContainer) {
					// Drain the logging thread before we remove the
					// container (we need to use the logging id)
					((DockerConnection) connection)
							.stopLoggingThread(loggingId);
					while (((DockerConnection) connection).loggingStatus(
							loggingId) == EnumDockerLoggingStatus.LOGGING_ACTIVE) {
						Thread.sleep(1000);
					}
					// Look for any Display Log console that the user may
					// have opened which would be
					// separate and make sure it is removed as well
					RunConsole rc2 = RunConsole
							.findConsole(((DockerConnection) connection)
									.getContainer(containerId));
					if (rc2 != null)
						RunConsole.removeConsole(rc2);
					((DockerConnection) connection)
							.removeContainer(containerId);
				}

			} catch (final DockerException e2) {
				// error in creation, try and remove Container if possible
				if (!keepContainer && containerId != null) {
					try {
						((DockerConnection) connection)
								.removeContainer(containerId);
					} catch (DockerException | InterruptedException e1) {
						// ignore exception
					}
				}
				Display.getDefault().syncExec(() -> MessageDialog.openError(
						PlatformUI.getWorkbench().getActiveWorkbenchWindow()
								.getShell(),
						DVMessages.getFormattedString(ERROR_CREATING_CONTAINER,
								imageName),
						e2.getMessage()));
			} catch (InterruptedException e3) {
				// for now
				// do nothing
			}
			((DockerConnection) connection).getContainers(true);
		});
		t.start();
	}

	private class ID {
		private Integer uid;
		private Integer gid;

		public ID(Integer uid, Integer gid) {
			this.uid = uid;
			this.gid = gid;
		}

		public Integer getuid() {
			return uid;
		}

		public Integer getgid() {
			return gid;
		}
	}

	/**
	 * @since 3.0
	 */
	public int fetchContainerDirs(String connectionUri, String imageName,
			List<String> containerDirs, IPath hostDir) {
		// Try and use the specified connection that was used before,
		// otherwise, open an error
		final IDockerConnection connection = DockerConnectionManager
				.getInstance().getConnectionByUri(connectionUri);
		if (connection == null) {
			Display.getDefault()
					.syncExec(() -> MessageDialog.openError(
							PlatformUI.getWorkbench().getActiveWorkbenchWindow()
									.getShell(),
							DVMessages.getString(ERROR_LAUNCHING_CONTAINER),
							DVMessages.getFormattedString(
									ERROR_NO_CONNECTION_WITH_URI,
									connectionUri)));
			return -1;
		}

		CopyVolumesFromImageJob job = new CopyVolumesFromImageJob(connection,
				imageName, containerDirs, hostDir);
		job.schedule();
		return 0;
	}

	/**
	 * @since 3.0
	 */
	public Process runCommand(String connectionName, String imageName, IProject project, 
			IErrorMessageHolder errMsgHolder, String command,
			String commandDir,
			String workingDir,
			List<String> additionalDirs, Map<String, String> origEnv,
			Properties envMap, boolean supportStdin,
			boolean privilegedMode, HashMap<String, String> labels,
			boolean keepContainer) {

		Integer uid = null;
		Integer gid = null;
		// For Unix, make sure that the user id is passed with the run
		// so any output files are accessible by this end-user
		String os = System.getProperty("os.name"); //$NON-NLS-1$
		if (os.indexOf("nux") > 0) { //$NON-NLS-1$
			// first try and see if we have already run a command on this
			// project
			ID ugid = fidMap.get(project);
			if (ugid == null) {
				try {
					uid = (Integer) Files.getAttribute(
							project.getLocation().toFile().toPath(),
							"unix:uid"); //$NON-NLS-1$
					gid = (Integer) Files.getAttribute(
							project.getLocation().toFile().toPath(),
							"unix:gid"); //$NON-NLS-1$
					ugid = new ID(uid, gid);
					// store the uid for possible later usage
					fidMap.put(project, ugid);
				} catch (IOException e) {
					// do nothing...leave as null
				} // $NON-NLS-1$
			} else {
				uid = ugid.getuid();
				gid = ugid.getgid();
			}
		}

		final List<String> env = new ArrayList<>();
		env.addAll(toList(origEnv));
		env.addAll(toList(envMap));

		final List<String> cmdList = getCmdList(command);

		final Map<String, List<IDockerPortBinding>> portBindingsMap = new HashMap<>();


		IDockerConnection[] connections = DockerConnectionManager
				.getInstance().getConnections();
		if (connections == null || connections.length == 0) {
			errMsgHolder.setErrorMessage(
					Messages.getString("ContainerLaunch.noConnections.error")); //$NON-NLS-1$
			return null;
		}

		IDockerConnection connection = null;
		for (IDockerConnection c : connections) {
			if (c.getUri().equals(connectionName)) {
				connection = c;
				break;
			}
		}

		if (connection == null) {
			errMsgHolder.setErrorMessage(Messages.getFormattedString(
					"ContainerLaunch.connectionNotFound.error", //$NON-NLS-1$
					connectionName));
			return null;
		}

		List<IDockerImage> images = connection.getImages();
		if (images.isEmpty()) {
			errMsgHolder.setErrorMessage(
					Messages.getString("ContainerLaunch.noImages.error")); //$NON-NLS-1$
			return null;
		}

		IDockerImageInfo info = connection.getImageInfo(imageName);
		if (info == null) {
			errMsgHolder.setErrorMessage(Messages.getFormattedString(
					"ContainerLaunch.imageNotFound.error", imageName)); //$NON-NLS-1$
			return null;
		}

		DockerContainerConfig.Builder builder = new DockerContainerConfig.Builder()
				.openStdin(supportStdin).cmd(cmdList).image(imageName)
				.workingDir(workingDir);

		// switch to user id for Linux so output is accessible
		if (uid != null) {
			builder = builder.user(uid.toString());
		}
		
		// TODO: add group id here when supported by DockerHostConfig.Builder

		// add any labels if specified
		if (labels != null)
			builder = builder.labels(labels);

		DockerHostConfig.Builder hostBuilder = new DockerHostConfig.Builder()
				.privileged(privilegedMode);

		// Note we only pass volumes to the config if we have a
		// remote daemon. Local mounted volumes are passed
		// via the HostConfig binds setting
		final Set<String> remoteVolumes = new TreeSet<>();
		if (!((DockerConnection) connection).isLocal()) {
			// if using remote daemon, we have to
			// handle volume mounting differently.
			// Instead we mount empty volumes and copy
			// the host data over before starting.
			if (additionalDirs != null) {
				for (String dir : additionalDirs) {
					IPath p = new Path(dir).removeTrailingSeparator();
					remoteVolumes.add(p.toPortableString());
				}
			}
			if (workingDir != null) {
				IPath p = new Path(workingDir).removeTrailingSeparator();
				remoteVolumes.add(p.toPortableString());
			}
			if (commandDir != null) {
				IPath p = new Path(commandDir).removeTrailingSeparator();
				remoteVolumes.add(p.toPortableString());
			}
			builder = builder.volumes(remoteVolumes);
		} else {
			// Running daemon on local host.
			// Add mounts for any directories we need to run the executable.
			// When we add mount points, we need entries of the form:
			// hostname:mountname:Z.
			// In our case, we want all directories mounted as-is so the
			// executable will run as the user expects.
			final Set<String> volumes = new TreeSet<>();
			if (additionalDirs != null) {
				for (String dir : additionalDirs) {
					IPath p = new Path(dir).removeTrailingSeparator();
					volumes.add(p.toPortableString() + ":" //$NON-NLS-1$
							+ p.toPortableString() + ":Z"); //$NON-NLS-1$
				}
			}
			if (workingDir != null) {
				IPath p = new Path(workingDir).removeTrailingSeparator();
				volumes.add(p.toPortableString() + ":" + p.toPortableString() //$NON-NLS-1$
						+ ":Z"); //$NON-NLS-1$
			}
			if (commandDir != null) {
				IPath p = new Path(commandDir).removeTrailingSeparator();
				volumes.add(p.toPortableString() + ":" + p.toPortableString() //$NON-NLS-1$
						+ ":Z"); //$NON-NLS-1$
			}
			List<String> volumeList = new ArrayList<>(volumes);
			hostBuilder = hostBuilder.binds(volumeList);
		}

		final DockerContainerConfig config = builder.build();

		// add any port bindings if specified
		if (portBindingsMap.size() > 0)
			hostBuilder = hostBuilder.portBindings(portBindingsMap);

		final IDockerHostConfig hostConfig = hostBuilder.build();

		// create the container
		String containerId = null;
		try {
			containerId = ((DockerConnection) connection)
					.createContainer(config, hostConfig, null);
		} catch (DockerException | InterruptedException e) {
			errMsgHolder.setErrorMessage(e.getMessage());
			return null;
		}
		
		final String id = containerId;
		final IDockerConnection conn = connection;
		Thread t = new Thread(() -> {
			if (!((DockerConnection) conn).isLocal()) {
				// if daemon is remote, we need to copy
				// data over from the host.
				if (!remoteVolumes.isEmpty()) {
					CopyVolumesJob job = new CopyVolumesJob(remoteVolumes,
							conn, id);
					job.schedule();
					try {
						job.join();
					} catch (InterruptedException e) {
						// ignore
					}
					if (job.getResult() != Status.OK_STATUS)
						return;
				}
			}
			try {
				((DockerConnection) conn).startContainer(id,
						null);
			} catch (DockerException | InterruptedException e) {
				// ignore
			}
		});

		t.start();

		return new ContainerCommandProcess(connection, imageName, containerId,
				keepContainer);
	}

	/**
	 * Clean up the container used for launching
	 * 
	 * @param connectionUri
	 *            the URI of the connection used
	 * @param info
	 *            the container info
	 */
	public void cleanup(String connectionUri, IDockerContainerInfo info) {
		if (!DockerConnectionManager.getInstance().hasConnections()) {
			return;
		}

		// Try and find the specified connection
		final IDockerConnection connection = DockerConnectionManager
				.getInstance().getConnectionByUri(connectionUri);
		if (connection == null) {
			return;
		}
		try {
			connection.killContainer(info.id());
		} catch (DockerException | InterruptedException e) {
			// do nothing
		}
	}

	/**
	 * Get the reusable run console for running C/C++ executables in containers.
	 * 
	 * @return
	 */
	private RunConsole getConsole() {
		// if (console == null) {
		// console = RunConsole.getContainerLessConsole();
		// }
		return console;
	}

	private void setConsole(RunConsole cons) {
		console = cons;
	}

	/**
	 * Take the command string and parse it into a list of strings.
	 * 
	 * @param s
	 * @return list of strings
	 */
	private List<String> getCmdList(String s) {
		ArrayList<String> list = new ArrayList<>();
		int length = s.length();
		boolean insideQuote1 = false; // single-quote
		boolean insideQuote2 = false; // double-quote
		boolean escaped = false;
		StringBuffer buffer = new StringBuffer();
		// Parse the string and break it up into chunks that are
		// separated by white-space or are quoted. Ignore characters
		// that have been escaped, including the escape character.
		for (int i = 0; i < length; ++i) {
			char c = s.charAt(i);
			if (escaped) {
				buffer.append(c);
				escaped = false;
			}
			switch (c) {
			case '\'':
				if (!insideQuote2)
					insideQuote1 = insideQuote1 ^ true;
				else
					buffer.append(c);
				break;
			case '\"':
				if (!insideQuote1)
					insideQuote2 = insideQuote2 ^ true;
				else
					buffer.append(c);
				break;
			case '\\':
				escaped = true;
				break;
			case ' ':
			case '\t':
			case '\r':
			case '\n':
				if (insideQuote1 || insideQuote2)
					buffer.append(c);
				else {
					String item = buffer.toString();
					buffer.setLength(0);
					if (item.length() > 0)
						list.add(item);
				}
				break;
			default:
				buffer.append(c);
				break;
			}
		}
		// add last item of string that will be in the buffer
		String item = buffer.toString();
		if (item.length() > 0)
			list.add(item);
		return list;
	}

	/**
	 * Convert map of environment variables to a {@link List} of KEY=VALUE
	 * String
	 * 
	 * @param variables
	 *            the entries to manipulate
	 * @return the concatenated key/values for each given variable entry
	 */
	private List<String> toList(
			@SuppressWarnings("rawtypes") final Map variables) {
		final List<String> result = new ArrayList<>();
		if (variables != null) {
			@SuppressWarnings({ "unchecked", "rawtypes" })
			Set<Map.Entry> entries = variables.entrySet();
			for (@SuppressWarnings("rawtypes")
			Map.Entry entry : entries) {
				final String key = (String) entry.getKey();
				final String value = (String) entry.getValue();

				final String envEntry = key + "=" + value; //$NON-NLS-1$
				result.add(envEntry);
			}
		}
		return result;

	}

	/**
	 * @since 3.0
	 */
	public Set<String> getCopiedVolumes(String connectionName,
			String imageName) {
		Set<String> copiedSet = new HashSet<>();
		if (copiedVolumesMap != null) {
			Map<String, Set<String>> connectionMap = copiedVolumesMap
					.get(connectionName);
			if (connectionMap != null) {
				Set<String> imageSet = connectionMap.get(imageName);
				if (imageSet != null) {
					copiedSet = imageSet;
				}
			}
		}
		return copiedSet;
	}

}
