/*******************************************************************************
 * Copyright (c) 2009, 2010 Nokia 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:
 * Nokia - Initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.debug.edc.launch;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.launch.ServicesLaunchSequence;
import org.eclipse.cdt.debug.edc.internal.snapshot.SnapshotLaunchSequence;
import org.eclipse.cdt.debug.edc.internal.snapshot.SnapshotUtils;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Sequence;
import org.eclipse.cdt.dsf.debug.service.IDsfDebugServicesFactory;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.launch.AbstractCLaunchDelegate2;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
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.ILaunchManager;

abstract public class EDCLaunchDelegate extends AbstractCLaunchDelegate2 {

	class UncancelableMonitor extends SubProgressMonitor {

		private boolean canceled;

		public UncancelableMonitor(IProgressMonitor monitor, int ticks,
				int style) {
			super(monitor, ticks, style);
			this.canceled = false;
		}

		@Override
		public void setCanceled(boolean b) {
			canceled = b;
		}

		@Override
		public boolean isCanceled() {
			return canceled;
		}
		
	}
	
	public EDCLaunchDelegate() {
		super(false);
	}

	public EDCLaunchDelegate(boolean requireCProject) {
		super(requireCProject);
	}

	public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
			throws CoreException {
		
		org.eclipse.cdt.launch.LaunchUtils.enableActivity("org.eclipse.cdt.debug.edc.ui.edcActivity", true); //$NON-NLS-1$
		
		if (monitor == null) {
			monitor = new NullProgressMonitor();
		}
		
		monitor.beginTask("Launching...", 10);
		if (monitor.isCanceled()) {
			return;
		}

		try {
			final EDCLaunch edcLaunch = (EDCLaunch) launch;
			
			edcLaunch.initialize();
			
			boolean forDebug = mode.equals(ILaunchManager.DEBUG_MODE);

			monitor.worked(1);
			
			if (edcLaunch.isFirstLaunch())
			{
				// First launch for this session, we need to create all of the services
				edcLaunch.setServiceFactory(newServiceFactory());

				if (forDebug) {
					edcLaunch.initializeSnapshotSupport();
				}
				// Create and invoke the launch sequence to create the debug control and
				// services
				IProgressMonitor subMon1 = new SubProgressMonitor(monitor, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
				final ServicesLaunchSequence servicesLaunchSequence = new ServicesLaunchSequence(edcLaunch.getSession(), edcLaunch,
						subMon1);

				edcLaunch.getSession().getExecutor().execute(servicesLaunchSequence);
				try {
					getOrCancelSequence(servicesLaunchSequence, subMon1);
				} catch (InterruptedException e1) {
					throw new DebugException(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, DebugException.INTERNAL_ERROR,
							"Interrupted Exception in dispatch thread.\n" + e1.getLocalizedMessage(), e1)); //$NON-NLS-1$
				} catch (CancellationException e) {
					throw new CoreException(Status.CANCEL_STATUS);
				} catch (ExecutionException e1) {
					throw new DebugException(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, DebugException.REQUEST_FAILED,
							"Error in services launch sequence.", e1.getCause())); //$NON-NLS-1$
				}

				if (monitor.isCanceled())
					return;

				// The initializeControl method should be called after the
				// ICommandControlService
				// be initialized in the ServicesLaunchSequence above. This is because
				// it is that
				// service that will trigger the launch cleanup (if we need it during
				// this launch)
				// through an ICommandControlShutdownDMEvent
				if (forDebug) {
					edcLaunch.initializeMemoryRetrieval();
				}

				monitor.worked(1);
				
			}


			// Create and invoke the final launch sequence to setup the debugger
			IProgressMonitor subMon2 = new UncancelableMonitor(monitor, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
			final Sequence finalLaunchSequence = getFinalLaunchSequence(edcLaunch.getSession().getExecutor(), edcLaunch, subMon2);

			edcLaunch.getSession().getExecutor().execute(finalLaunchSequence);
			boolean succeed = false;
			try {
				getOrCancelSequence(finalLaunchSequence, subMon2);
				succeed = true;
			} catch (InterruptedException e1) {
				IStatus exceptionStatus = new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, DebugException.INTERNAL_ERROR,
						"Interrupted Exception in dispatch thread.\n" + e1.getLocalizedMessage(), e1);
				if (edcLaunch.isFirstLaunch())
					throw new DebugException(exceptionStatus); //$NON-NLS-1$
				else
					EDCDebugger.getMessageLogger().log(exceptionStatus);
			} catch (CancellationException e) {
				if (edcLaunch.isFirstLaunch())
					throw new CoreException(Status.CANCEL_STATUS);
			} catch (ExecutionException e1) {
				Throwable cause = e1.getCause();
				if (cause instanceof CoreException) {
					IStatus s = ((CoreException) cause).getStatus();
					if (s.getSeverity() == IStatus.CANCEL && edcLaunch.isFirstLaunch())
						throw (CoreException) cause;
				}
				IStatus errorStatus = EDCDebugger.getMessageLogger().createStatus(IStatus.ERROR, null, e1.getCause());
				if (edcLaunch.isFirstLaunch())
					throw new DebugException(errorStatus);
				else
					EDCDebugger.getMessageLogger().log(errorStatus);
			} finally {
				if (!succeed && edcLaunch.isFirstLaunch()) {
					Query<Object> launchShutdownQuery = new Query<Object>() {
						@Override
						protected void execute(DataRequestMonitor<Object> rm) {
							edcLaunch.shutdownSession(rm);
						}
					};

					edcLaunch.getSession().getExecutor().execute(launchShutdownQuery);

					// Wait for the shutdown to finish. The Query.get() method is a
					// synchronous call which blocks until the query completes.
					try {
						// not cancellable
						launchShutdownQuery.get();
					} catch (InterruptedException e) {
						throw new DebugException(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID,
								DebugException.INTERNAL_ERROR,
								"InterruptedException while shutting down debugger launch " + launch, e)); //$NON-NLS-1$ 
					} catch (ExecutionException e) {
						throw new DebugException(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID,
								DebugException.REQUEST_FAILED, "Error in shutting down debugger launch " + launch, e)); //$NON-NLS-1$
					}
				}
				
				if (!forDebug) {
					// just running, so go ahead and shutdown the session
					edcLaunch.shutdownSession(new RequestMonitor(ImmediateExecutor.getInstance(), null));
				}
				
				edcLaunch.setLaunching(false);
			}
		} finally {
			monitor.done();
		}
	}

	/**
	 * Wait for a sequence to finish, periodically checking whether
	 * it has been cancelled. 
	 * @param sequence
	 * @param monitor
	 * @return the value of the sequence
	 * @throws ExecutionException 
	 * @throws InterruptedException
	 * @throws CancellationException  
	 */
	private Object getOrCancelSequence(Sequence sequence,
			IProgressMonitor monitor) throws InterruptedException, ExecutionException {
		while (!monitor.isCanceled()) {
			try {
				return sequence.get(1, TimeUnit.SECONDS);
			} catch (TimeoutException e) {
				// fine, keep looping
			}
		}
		// cancelled
		sequence.cancel(true);  /* flag is ignored */
		throw new CancellationException();
	}

	@Override
	public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
		// Need to configure the source locator before creating the launch
		// because once the launch is created and added to launch manager,
		// the adapters will be created for the whole session, including
		// the source lookup adapter.

		EDCLaunch launch = findExistingLaunch(configuration, mode);
		if (launch == null)
		{
			launch = createLaunch(configuration, mode);
		}
		else
		{
			launch.addAffiliatedLaunchConfiguration(configuration);
			launch.setFirstLaunch(false);
		}

		launch.setActiveLaunchConfiguration(configuration);

		return launch;
	}

	/**
	 * @since 2.0
	 */
	abstract public EDCLaunch createLaunch(ILaunchConfiguration configuration,
			String mode);

	private EDCLaunch findExistingLaunch(ILaunchConfiguration configuration,
			String mode) {
		if (!SnapshotUtils.isSnapshotLaunchConfig(configuration)) // Snapshot launches never join existing ones.
		{ 
	        ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
	        List<ILaunch> launchList = Arrays.asList(manager.getLaunches());
	        
	        for (ILaunch iLaunch : launchList) {		
	        	if (!iLaunch.isTerminated() && iLaunch instanceof EDCLaunch)
	        	{
	        		EDCLaunch edcLaunch = (EDCLaunch) iLaunch;
	        		// The launch may be in the process of terminating. Test for that but
	        		// first synchronize around the launch so it can't begin termination
	        		// while we are checking here.

	        		if (DsfSession.isSessionActive(edcLaunch.getSession().getId())
	        				&& isSameTarget(edcLaunch, configuration, mode))
	        		{
	        			if (edcLaunch.isTerminating())
	        				this.waitForLaunchToTerminate(edcLaunch);
		        		synchronized (edcLaunch)
		        		{
		        			if (!edcLaunch.isTerminating())
		        			{
			        			edcLaunch.setLaunching(true);
			        			return edcLaunch;
		        			}
		        		}
	        		}
	         	}
			}
		}
		return null;
	}

	private void waitForLaunchToTerminate(final EDCLaunch edcLaunch) {

		Job waitForTerminate = new Job("Waiting for " + edcLaunch.getDescription() + " to terminate") {

			@Override
			protected IStatus run(IProgressMonitor monitor) {
				monitor.beginTask("Waiting for termination",
						IProgressMonitor.UNKNOWN);
				try {
					while (!edcLaunch.isTerminated()) {
						Thread.sleep(500);
						if (monitor.isCanceled())
							return Status.CANCEL_STATUS;
						monitor.worked(1);
					}
				} catch (InterruptedException e) {
					EDCDebugger.getMessageLogger().logError(null, e);
				}
				finally {
					monitor.done();
				}

				return Status.OK_STATUS;
			}
		};

		waitForTerminate.schedule();
		try {
			waitForTerminate.join();
		} catch (InterruptedException e) {
			EDCDebugger.getMessageLogger().logError(null, e);
		}
	}

	abstract public String getDebugModelID();

	abstract protected Sequence getLiveLaunchSequence(DsfExecutor executor, EDCLaunch launch, IProgressMonitor pm);

	protected Sequence getSnapshotLaunchSequence(DsfExecutor executor, EDCLaunch launch, IProgressMonitor pm) {
		return new SnapshotLaunchSequence(executor, launch, pm);
	};

	protected Sequence getFinalLaunchSequence(DsfExecutor executor, EDCLaunch launch, IProgressMonitor pm) {
		if (launch.isSnapshotLaunch())
			return getSnapshotLaunchSequence(executor, launch, pm);
		else
			return getLiveLaunchSequence(executor, launch, pm);
	};

	abstract protected IDsfDebugServicesFactory newServiceFactory();
	

	/**
	 * @param existingLaunch 
	 * @since 2.0
	 */
	abstract protected boolean isSameTarget(EDCLaunch existingLaunch, ILaunchConfiguration configuration, String mode);

}
