/*******************************************************************************
 * Copyright (c) 2008, 2017 xored software, 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:
 *     xored software, Inc. - initial API and Implementation (Alex Panchenko)
 *******************************************************************************/
package org.eclipse.dltk.ruby.testing.internal;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.ILaunchShortcut;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IModelElementVisitor;
import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.IScriptFolder;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.internal.testing.launcher.DLTKTestingMigrationDelegate;
import org.eclipse.dltk.launching.ScriptLaunchConfigurationConstants;
import org.eclipse.dltk.ruby.core.RubyNature;
import org.eclipse.dltk.testing.DLTKTestingConstants;
import org.eclipse.dltk.testing.ITestingEngine;
import org.eclipse.dltk.testing.TestingEngineDetectResult;
import org.eclipse.dltk.testing.TestingEngineManager;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.ScriptElementLabels;
import org.eclipse.dltk.ui.util.ExceptionHandler;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;

public class RubyTestingLaunchShortcut implements ILaunchShortcut {

	/**
	 * Default constructor.
	 */
	public RubyTestingLaunchShortcut() {
	}

	@Override
	public void launch(IEditorPart editor, String mode) {
		IModelElement element = DLTKUIPlugin.getEditorInputModelElement(editor.getEditorInput());
		if (element != null) {
			launch(new Object[] { element }, mode);
		} else {
			showNoTestsFoundDialog();
		}
	}

	@Override
	public void launch(ISelection selection, String mode) {
		if (selection instanceof IStructuredSelection) {
			launch(((IStructuredSelection) selection).toArray(), mode);
		} else {
			showNoTestsFoundDialog();
		}
	}

	private void launch(Object[] elements, String mode) {
		try {
			IModelElement elementToLaunch = null;

			if (elements.length == 1) {
				Object selected = elements[0];
				if (selected instanceof IFolder) {
					performLaunch((IFolder) selected, mode);
					return;
				}
				if (!(selected instanceof IModelElement) && selected instanceof IAdaptable) {
					selected = ((IAdaptable) selected).getAdapter(IModelElement.class);
				}
				if (selected instanceof IModelElement) {
					IModelElement element = (IModelElement) selected;
					switch (element.getElementType()) {
					case IModelElement.SCRIPT_PROJECT: {
						IProject project = ((IScriptProject) element).getProject();
						List<ILaunchConfiguration> configs = new ArrayList<>();
						IFolder specFolder = project.getFolder("test"); //$NON-NLS-1$
						if (specFolder != null && specFolder.exists())
							configs.add(findOrCreateLaunch(specFolder, mode));
						specFolder = project.getFolder("spec"); //$NON-NLS-1$
						if (specFolder != null && specFolder.exists())
							configs.add(findOrCreateLaunch(specFolder, mode));
						ILaunchConfiguration config = null;
						if (configs.size() == 1) {
							config = configs.get(0);
						} else if (configs.size() > 1) {
							config = chooseConfiguration(configs, mode);
						}
						if (config != null) {
							if (config.getAttribute(DLTKTestingConstants.ATTR_ENGINE_ID, (String) null) == null) {
								MessageDialog.openInformation(getShell(), Messages.RubyTestingLaunchShortcut_testLaunch,
										Messages.RubyTestingLaunchShortcut_theSelectedLaunchConfigurationDoesntHaveATestingEngineConfigured);
								return;
							}
							DebugUITools.launch(config, mode);
						}
						return;
					}
					case IModelElement.PROJECT_FRAGMENT:
					case IModelElement.SCRIPT_FOLDER: {
						performLaunch((IFolder) element.getResource(), mode);
						return;
					}
					case IModelElement.SOURCE_MODULE:
					case IModelElement.TYPE:
					case IModelElement.METHOD:
						elementToLaunch = element;
						break;
					}
				}
			}
			if (elementToLaunch == null) {
				showNoTestsFoundDialog();
				return;
			}
			performLaunch(elementToLaunch, mode);
		} catch (InterruptedException e) {
			// OK, silently move on
		} catch (CoreException e) {
			ExceptionHandler.handle(e, getShell(), Messages.RubyTestingLaunchShortcut_testLaunch,
					Messages.RubyTestingLaunchShortcut_testLaunchUnexpectedlyFailed);
		}
	}

	private void showNoTestsFoundDialog() {
		MessageDialog.openInformation(getShell(), Messages.RubyTestingLaunchShortcut_testLaunch,
				Messages.RubyTestingLaunchShortcut_unableToLocateAnyTestsInTheSpecifiedSelection);
	}

	private void performLaunch(IModelElement element, String mode) throws InterruptedException, CoreException {
		ILaunchConfigurationWorkingCopy temporary = createLaunchConfiguration(element);
		if (temporary == null) {
			return;
		}
		ILaunchConfiguration config = findExistingLaunchConfiguration(temporary, mode);
		if (config == null) {
			// no existing found: create a new one
			final IResource resource = element.getUnderlyingResource();
			if (resource != null) {
				temporary.setMappedResources(new IResource[] { resource });
			}
			config = temporary.doSave();
		} else {
			config = DLTKTestingMigrationDelegate.fixMappedResources(config);
		}
		if (config.getAttribute(DLTKTestingConstants.ATTR_ENGINE_ID, (String) null) == null) {
			MessageDialog.openInformation(getShell(), Messages.RubyTestingLaunchShortcut_testLaunch,
					Messages.RubyTestingLaunchShortcut_theSelectedLaunchConfigurationDoesntHaveATestingEngineConfigured);
			return;
		}
		DebugUITools.launch(config, mode);
	}

	private ILaunchConfiguration findOrCreateLaunch(IFolder folder, String mode)
			throws InterruptedException, CoreException {
		String name = folder.getName();
		String testName = name.substring(name.lastIndexOf(IPath.SEPARATOR) + 1);

		ILaunchConfigurationType configType = getLaunchManager()
				.getLaunchConfigurationType(getLaunchConfigurationTypeId());
		final ILaunchConfigurationWorkingCopy wc = configType.newInstance(null,
				getLaunchManager().generateLaunchConfigurationName(testName));

		wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME, folder.getProject().getName());

		// wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_TEST_NAME,
		// EMPTY_STRING);
		IModelElement element = DLTKCore.create(folder);
		if (element != null) {
			wc.setAttribute(DLTKTestingConstants.ATTR_TEST_CONTAINER, element.getHandleIdentifier());
			// wc.setAttribute(ScriptLaunchConfigurationConstants.
			// ATTR_TEST_ELEMENT_NAME, EMPTY_STRING);

			final ITestingEngine[] engines = TestingEngineManager.getEngines(RubyNature.NATURE_ID);
			element.accept(new IModelElementVisitor() {

				private boolean detected;

				@Override
				public boolean visit(IModelElement element) {
					if (detected)
						return false;
					if (element instanceof ISourceModule) {
						TestingEngineDetectResult detection = TestingEngineManager.detect(engines,
								(ISourceModule) element);
						if (detection != null) {
							wc.setAttribute(DLTKTestingConstants.ATTR_ENGINE_ID, detection.getEngine().getId());
							detected = true;
							return false;
						}
					}
					return element instanceof IScriptFolder || element instanceof IProjectFragment
							|| element instanceof IScriptProject;
				}

			});
		}

		wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_SCRIPT_NATURE, RubyNature.NATURE_ID);

		ILaunchConfiguration config = findExistingLaunchConfiguration(wc, mode);
		if (config == null) {
			// no existing found: create a new one
			wc.setMappedResources(new IResource[] { folder });
			config = wc.doSave();
		} else {
			config = DLTKTestingMigrationDelegate.fixMappedResources(config);
		}
		return config;
	}

	private void performLaunch(IFolder folder, String mode) throws InterruptedException, CoreException {
		ILaunchConfiguration config = findOrCreateLaunch(folder, mode);
		if (config.getAttribute(DLTKTestingConstants.ATTR_ENGINE_ID, (String) null) == null) {
			MessageDialog.openInformation(getShell(), Messages.RubyTestingLaunchShortcut_testLaunch,
					Messages.RubyTestingLaunchShortcut_theSelectedLaunchConfigurationDoesntHaveATestingEngineConfigured);
			return;
		}
		DebugUITools.launch(config, mode);
	}

	private Shell getShell() {
		return DLTKUIPlugin.getActiveWorkbenchShell();
	}

	private ILaunchManager getLaunchManager() {
		return DebugPlugin.getDefault().getLaunchManager();
	}

	/**
	 * Show a selection dialog that allows the user to choose one of the specified
	 * launch configurations. Return the chosen config, or <code>null</code> if the
	 * user cancelled the dialog.
	 *
	 * @param configList
	 * @param mode
	 * @return ILaunchConfiguration
	 * @throws InterruptedException
	 */
	private ILaunchConfiguration chooseConfiguration(List<ILaunchConfiguration> configList, String mode)
			throws InterruptedException {
		IDebugModelPresentation labelProvider = DebugUITools.newDebugModelPresentation();
		ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider);
		dialog.setElements(configList.toArray());
		dialog.setTitle(Messages.RubyTestingLaunchShortcut_selectTestConfiguration);
		if (mode.equals(ILaunchManager.DEBUG_MODE)) {
			dialog.setMessage(Messages.RubyTestingLaunchShortcut_selectConfigurationToDebug);
		} else {
			dialog.setMessage(Messages.RubyTestingLaunchShortcut_selectConfigurationToRun);
		}
		dialog.setMultipleSelection(false);
		int result = dialog.open();
		if (result == Window.OK) {
			return (ILaunchConfiguration) dialog.getFirstResult();
		}
		throw new InterruptedException(); // cancelled by user
	}

	/**
	 * Returns the launch configuration type id of the launch configuration this
	 * shortcut will create. Clients can override this method to return the id of
	 * their launch configuration.
	 *
	 * @return the launch configuration type id of the launch configuration this
	 *         shortcut will create
	 */
	protected String getLaunchConfigurationTypeId() {
		return "org.eclipse.dltk.ruby.testing.launchConfig"; //$NON-NLS-1$
	}

	/**
	 * Creates a launch configuration working copy for the given element. The launch
	 * configuration type created will be of the type returned by
	 * {@link #getLaunchConfigurationTypeId}. The element type can only be of type
	 * {@link IJavaProject}, {@link IPackageFragmentRoot}, {@link IPackageFragment},
	 * {@link IType} or {@link IMethod}.
	 *
	 * Clients can extend this method (should call super) to configure additional
	 * attributes on the launch configuration working copy.
	 *
	 * @return a launch configuration working copy for the given element
	 */
	protected ILaunchConfigurationWorkingCopy createLaunchConfiguration(IModelElement element) throws CoreException {
		String testFileName;

		String name = ScriptElementLabels.getDefault().getTextLabel(element, ScriptElementLabels.F_FULLY_QUALIFIED);
		String testName = name.substring(name.lastIndexOf(IPath.SEPARATOR) + 1);

		switch (element.getElementType()) {
		case IModelElement.SOURCE_MODULE:
		case IModelElement.TYPE: {
			testFileName = element.getResource().getProjectRelativePath().toPortableString();
		}
			break;
		case IModelElement.METHOD: {
			testFileName = element.getResource().getProjectRelativePath().toPortableString();
		}
			break;
		default:
			throw new IllegalArgumentException(
					"Invalid element type to create a launch configuration: " + element.getClass().getName()); //$NON-NLS-1$
		}

		ILaunchConfigurationType configType = getLaunchManager()
				.getLaunchConfigurationType(getLaunchConfigurationTypeId());
		ILaunchConfigurationWorkingCopy wc = configType.newInstance(null,
				getLaunchManager().generateLaunchConfigurationName(testName));

		wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME,
				element.getScriptProject().getElementName());
		wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_MAIN_SCRIPT_NAME, testFileName);
		wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_SCRIPT_NATURE, RubyNature.NATURE_ID);
		wc.setAttribute(IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE, "true"); //$NON-NLS-1$
		// wc.setAttribute(XUnitLaunchConfigurationConstants.ATTR_TEST_NAME,
		// testFileName);
		// wc.setAttribute(ScriptLaunchConfigurationConstants.ATTR_CONTAINER_PATH
		// , containerHandleId);
		// wc.setAttribute(XUnitLaunchConfigurationConstants.
		// ATTR_TEST_ELEMENT_NAME, testElementName);
		// XUnitMigrationDelegate.mapResources(wc);
		ITestingEngine[] engines = TestingEngineManager.getEngines(RubyNature.NATURE_ID);
		ISourceModule module = (ISourceModule) element.getAncestor(IModelElement.SOURCE_MODULE);
		TestingEngineDetectResult detection = TestingEngineManager.detect(engines, module);
		if (detection != null) {
			wc.setAttribute(DLTKTestingConstants.ATTR_ENGINE_ID, detection.getEngine().getId());
		}

		return wc;
	}

	/**
	 * Returns the attribute names of the attributes that are compared when looking
	 * for an existing similar launch configuration. Clients can override and
	 * replace to customize.
	 *
	 * @return the attribute names of the attributes that are compared
	 */
	protected String[] getAttributeNamesToCompare() {
		return new String[] { ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME,
				DLTKTestingConstants.ATTR_TEST_CONTAINER, ScriptLaunchConfigurationConstants.ATTR_MAIN_SCRIPT_NAME,
				// IDLTKTestingConstants.ENGINE_ID_ATR,
				ScriptLaunchConfigurationConstants.ATTR_SCRIPT_NATURE
				// XUnitLaunchConfigurationConstants.ATTR_TEST_NAME,
				// XUnitLaunchConfigurationConstants.ATTR_TEST_ELEMENT_NAME
		};
	}

	private static boolean hasSameAttributes(ILaunchConfiguration config1, ILaunchConfiguration config2,
			String[] attributeToCompare) {
		try {
			for (int i = 0; i < attributeToCompare.length; i++) {
				String val1 = config1.getAttribute(attributeToCompare[i], Util.EMPTY_STRING);
				String val2 = config2.getAttribute(attributeToCompare[i], Util.EMPTY_STRING);
				if (!val1.equals(val2)) {
					return false;
				}
			}
			return true;
		} catch (CoreException e) {
			// ignore access problems here, return false
		}
		return false;
	}

	private ILaunchConfiguration findExistingLaunchConfiguration(ILaunchConfigurationWorkingCopy temporary, String mode)
			throws InterruptedException, CoreException {
		ILaunchConfigurationType configType = temporary.getType();

		ILaunchConfiguration[] configs = getLaunchManager().getLaunchConfigurations(configType);
		String[] attributeToCompare = getAttributeNamesToCompare();

		ArrayList<ILaunchConfiguration> candidateConfigs = new ArrayList<>(configs.length);
		for (int i = 0; i < configs.length; i++) {
			ILaunchConfiguration config = configs[i];
			if (hasSameAttributes(config, temporary, attributeToCompare)) {
				candidateConfigs.add(config);
			}
		}

		// If there are no existing configs associated with the IType, create
		// one.
		// If there is exactly one config associated with the IType, return it.
		// Otherwise, if there is more than one config associated with the
		// IType, prompt the
		// user to choose one.
		int candidateCount = candidateConfigs.size();
		if (candidateCount == 0) {
			return null;
		} else if (candidateCount == 1) {
			return candidateConfigs.get(0);
		} else {
			// Prompt the user to choose a config. A null result means the user
			// cancelled the dialog, in which case this method returns null,
			// since cancelling the dialog should also cancel launching
			// anything.
			ILaunchConfiguration config = chooseConfiguration(candidateConfigs, mode);
			if (config != null) {
				return config;
			}
		}
		return null;
	}

}
