/*******************************************************************************
 * Copyright (c) 2007, 2016 IBM Corporation 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:
 *     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();
				}
			}
			StringBuffer buffer = new StringBuffer(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();
		}
		
	}
}
