/*******************************************************************************
 * Copyright (c) 2007, 2016 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Google Inc - add support for accepting multiple connections
 *******************************************************************************/
package org.eclipse.jdt.internal.launching;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.jdi.TimeoutException;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.osgi.util.NLS;

import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
import com.sun.jdi.connect.ListeningConnector;
import com.sun.jdi.connect.TransportTimeoutException;

/**
 * A process that represents a VM listening connector that is waiting for some VM(s) to remotely connect. Allows the user to see the status of the
 * connection and terminate it. If a successful connection occurs, the debug target is added to the launch and, if a configured number of connections
 * have been reached, then this process is removed.
 *
 * @since 3.4
 * @see SocketListenConnector
 */
public class SocketListenConnectorProcess implements IProcess {
	/**
	 * Whether this process has been terminated.
	 */
	private boolean fTerminated = false;
	/**
	 * The launch this process belongs to
	 */
	private ILaunch fLaunch;
	/**
	 * The port this connector will listen on.
	 */
	private String fPort;
	/**
	 * The number of incoming connections to accept (0 = unlimited). Setting to 1 mimics previous behaviour.
	 */
	private int fConnectionLimit;
	/** The number of connections accepted so far. */
	private int fAccepted = 0;
	/**
	 * The system job that will wait for incoming VM connections.
	 */
	private WaitForConnectionJob fWaitForConnectionJob;

	/** Time when this instance was created (milliseconds) */
	private long fStartTime;

	/**
	 * Creates this process.  The label for this process will state
	 * the port the connector is listening at.
	 * @param launch the launch this process belongs to
	 * @param port the port the connector will wait on
	 * @param connectionLimit the number of incoming connections to accept (0 = unlimited)
	 */
	public SocketListenConnectorProcess(ILaunch launch, String port, int connectionLimit){
		fLaunch = launch;
		fPort = port;
		fConnectionLimit = connectionLimit;
	}

	/**
	 * Starts a job that will accept a VM remotely connecting to the
	 * given connector.  The #startListening() method must have been
	 * called on the connector with the same arguments before calling
	 * this method.  The 'port' argument in the map should have the same
	 * value as the port specified in this process' constructor.
	 *
	 * @param connector the connector that will accept incoming connections
	 * @param arguments map of arguments that are used by the connector
	 * @throws CoreException if a problem occurs trying to accept a connection
	 * @see SocketListenConnector
	 */
	public void waitForConnection(ListeningConnector connector, Map<String, Connector.Argument> arguments) throws CoreException{
		if (isTerminated()){
			throw new CoreException(getStatus(LaunchingMessages.SocketListenConnectorProcess_0, null, IJavaLaunchConfigurationConstants.ERR_REMOTE_VM_CONNECTION_FAILED));
		}
		fStartTime = System.currentTimeMillis();
		fAccepted = 0;
		// If the connector does not support multiple connections, accept a single connection
		try {
			if (!connector.supportsMultipleConnections()) {
				fConnectionLimit = 1;
			}
		}
		catch (IOException | IllegalConnectorArgumentsException ex) {
			fConnectionLimit = 1;
		}
		fLaunch.addProcess(this);
		fWaitForConnectionJob = new WaitForConnectionJob(connector,arguments);
		fWaitForConnectionJob.setPriority(Job.SHORT);
		fWaitForConnectionJob.setSystem(true);
		fWaitForConnectionJob.addJobChangeListener(new JobChangeAdapter(){
			@Override
			public void running(IJobChangeEvent event) {
				fireReadyToAcceptEvent();
			}
			@Override
			public void done(IJobChangeEvent event) {
				if (event.getResult().isOK() && continueListening()) {
					fWaitForConnectionJob.schedule();
				} else {
					try{
						terminate();
					} catch (DebugException e){}
				}
			}
		});
		fWaitForConnectionJob.schedule();
	}

	/**
	 * Return true if this connector should continue listening for further connections.
	 */
	protected boolean continueListening() {
		return !isTerminated() && (fWaitForConnectionJob != null && !fWaitForConnectionJob.fListeningStopped)
				&& (fConnectionLimit <= 0 || fConnectionLimit - fAccepted > 0);
	}

	/**
	 * Returns an error status using the passed parameters.
	 *
	 * @param message the status message
	 * @param exception lower level exception associated with the
	 *  error, or <code>null</code> if none
	 * @param code error code
	 * @return the new {@link IStatus}
	 */
	protected static IStatus getStatus(String message, Throwable exception, int code) {
		return new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), code, message, exception);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.model.IProcess#getExitValue()
	 */
	@Override
	public int getExitValue() throws DebugException {
		return 0;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.model.IProcess#getLabel()
	 */
	@Override
	public String getLabel() {
		return NLS.bind(LaunchingMessages.SocketListenConnectorProcess_1, new String[]{fPort});
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.model.IProcess#getLaunch()
	 */
	@Override
	public ILaunch getLaunch() {
		return fLaunch;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
	 */
	@Override
	public boolean canTerminate() {
		return !fTerminated;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
	 */
	@Override
	public boolean isTerminated() {
		return fTerminated;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.model.ITerminate#terminate()
	 */
	@Override
	public void terminate() throws DebugException {
		if (!fTerminated){
			fTerminated = true;
			fLaunch.removeProcess(this);
			if (fWaitForConnectionJob != null){
				fWaitForConnectionJob.cancel();
				fWaitForConnectionJob.stopListening();
				fWaitForConnectionJob = null;
			}
			fireTerminateEvent();
		}
	}

	/**
	 * Fires a terminate event.
	 */
	protected void fireTerminateEvent() {
		DebugPlugin manager= DebugPlugin.getDefault();
		if (manager != null) {
			manager.fireDebugEventSet(new DebugEvent[]{new DebugEvent(this, DebugEvent.TERMINATE)});
		}
	}

	/**
	 * Fires a custom model specific event when this connector is ready to accept incoming
	 * connections from a remote VM.
	 */
	protected void fireReadyToAcceptEvent(){
		DebugPlugin manager= DebugPlugin.getDefault();
		if (manager != null) {
			manager.fireDebugEventSet(new DebugEvent[]{new DebugEvent(this, DebugEvent.MODEL_SPECIFIC, IJavaLaunchConfigurationConstants.DETAIL_CONFIG_READY_TO_ACCEPT_REMOTE_VM_CONNECTION)});
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.model.IProcess#getStreamsProxy()
	 */
	@Override
	public IStreamsProxy getStreamsProxy() {
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.model.IProcess#getAttribute(java.lang.String)
	 */
	@Override
	public String getAttribute(String key) {
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.model.IProcess#setAttribute(java.lang.String, java.lang.String)
	 */
	@Override
	public void setAttribute(String key, String value) {
	}

	/* (non-Javadoc)
	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
	 */
	@Override
	public <T> T getAdapter(Class<T> adapter) {
		return null;
	}

	/**
	 * Return the time since this connector was started.
	 */
	private String getRunningTime() {
		long total = System.currentTimeMillis() - fStartTime;
		StringWriter result = new StringWriter();
		PrintWriter writer = new PrintWriter(result);
		int minutes = (int) (total / 60 / 1000);
		int seconds = (int) (total / 1000) % 60;
		int milliseconds = (int) (total / 1000) % 1000;
		writer.printf("%02d:%02d.%03d", minutes, seconds, milliseconds).close(); //$NON-NLS-1$
		return result.toString();
	}

	/**
	 * Job that waits for incoming VM connections. When a remote VM connection is accepted, a debug target is created.
	 */
	class WaitForConnectionJob extends Job{

		private ListeningConnector fConnector;
		private Map<String, Connector.Argument> fArguments;
		/**
		 * Flag that can be set to tell this job that waiting
		 * for incoming connections has been cancelled.  If true,
		 * IOExceptions will be ignored, allowing other threads
		 * to close the socket without generating an error.
		 */
		private boolean fListeningStopped = false;

		public WaitForConnectionJob(ListeningConnector connector, Map<String, Connector.Argument> arguments) {
			super(getLabel());
			fConnector = connector;
			fArguments = arguments;
		}

		@Override
		protected IStatus run(IProgressMonitor monitor) {
			try{
				// The following code sets a timeout (not officially supported in Sun's spec).
				// Allows polling for job cancellation. If the implementation does not support timeout
				// the job cannot be cancelled (but the launch can still be terminated).
				Connector.Argument timeout = fArguments.get("timeout"); //$NON-NLS-1$
				if (timeout != null){
					timeout.setValue("3000"); //$NON-NLS-1$
				}

				VirtualMachine vm = null;
				while (vm == null && !monitor.isCanceled()){
					try {
						vm = fConnector.accept(fArguments);
					} catch (TransportTimeoutException e){
					}
				}

				if (monitor.isCanceled()){
					fConnector.stopListening(fArguments);
					return Status.CANCEL_STATUS;
				}

				ILaunchConfiguration configuration = fLaunch.getLaunchConfiguration();
				boolean allowTerminate = false;
				if (configuration != null) {
					try{
						allowTerminate = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_ALLOW_TERMINATE, false);
					} catch (CoreException e) {
						LaunchingPlugin.log(e);
					}
				}
				Connector.Argument portArg= fArguments.get("port"); //$NON-NLS-1$
				String vmLabel = constructVMLabel(vm, portArg.value(), fLaunch.getLaunchConfiguration());
				IDebugTarget debugTarget= JDIDebugModel.newDebugTarget(fLaunch, vm, vmLabel, null, allowTerminate, true);
				fLaunch.addDebugTarget(debugTarget);
				fAccepted++;
				return Status.OK_STATUS;
			} catch (IOException e) {
				if (fListeningStopped){
					return Status.CANCEL_STATUS;
				}
				return getStatus(LaunchingMessages.SocketListenConnectorProcess_4, e, IJavaLaunchConfigurationConstants.ERR_REMOTE_VM_CONNECTION_FAILED);
			} catch (IllegalConnectorArgumentsException e) {
				return getStatus(LaunchingMessages.SocketListenConnectorProcess_4, e, IJavaLaunchConfigurationConstants.ERR_REMOTE_VM_CONNECTION_FAILED);
			}
		}

		/* (non-Javadoc)
		 * @see org.eclipse.core.runtime.jobs.Job#canceling()
		 */
		@Override
		protected void canceling() {
			stopListening();
		}

		/**
		 * Tells the listening connector to stop listening.  Ensures
		 * that the socket is closed and the port released.  Sets a flag
		 * so that the IOException thrown by the connector's accept method
		 * will be ignored.
		 */
		protected void stopListening() {
			if (!fListeningStopped){
				try{
					fListeningStopped = true;
					fConnector.stopListening(fArguments);
				} catch (IOException e) {
					done(getStatus(LaunchingMessages.SocketListenConnectorProcess_5, e, IJavaLaunchConfigurationConstants.ERR_REMOTE_VM_CONNECTION_FAILED));
				} catch (IllegalConnectorArgumentsException e) {
					done(getStatus(LaunchingMessages.SocketListenConnectorProcess_5, e, IJavaLaunchConfigurationConstants.ERR_REMOTE_VM_CONNECTION_FAILED));
				}
			}
		}

		/**
		 * Helper method that constructs a human-readable label for a remote VM.
		 * @param vm the VM
		 * @param port the port
		 * @param configuration the configuration
		 * @return the new VM label
		 */
		protected String constructVMLabel(VirtualMachine vm, String port, ILaunchConfiguration configuration) {
			String name = null;
			try {
				name = vm.name();
			} catch (TimeoutException e) {
				// do nothing
			} catch (VMDisconnectedException e) {
				// do nothing
			}
			if (name == null) {
				if (configuration == null) {
					name = ""; //$NON-NLS-1$
				} else {
					name = configuration.getName();
				}
			}
			StringBuilder buffer = new StringBuilder(name);
			if (fConnectionLimit != 1) {
				// if we're accepting multiple incoming connections,
				// append the time when each connection was accepted
				buffer.append('<').append(getRunningTime()).append('>');
			}
			buffer.append('[');
			buffer.append(port);
			buffer.append(']');
			return buffer.toString();
		}

	}
}
