/*******************************************************************************
 * Copyright (c) 2014 Christian Pontesegger and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * Contributors:
 *     Christian Pontesegger - initial API and implementation
 *******************************************************************************/
package org.eclipse.ease.modules.platform;

import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.ease.AbstractScriptEngine;
import org.eclipse.ease.IDebugEngine;
import org.eclipse.ease.IExecutionListener;
import org.eclipse.ease.IScriptEngine;
import org.eclipse.ease.IScriptable;
import org.eclipse.ease.Logger;
import org.eclipse.ease.Script;
import org.eclipse.ease.ScriptResult;
import org.eclipse.ease.modules.AbstractScriptModule;
import org.eclipse.ease.modules.ScriptParameter;
import org.eclipse.ease.modules.WrapToScript;
import org.eclipse.ease.service.EngineDescription;
import org.eclipse.ease.service.IScriptService;
import org.eclipse.ease.service.ScriptService;
import org.eclipse.ease.service.ScriptType;
import org.eclipse.ease.tools.ResourceTools;
import org.eclipse.ease.ui.launching.EaseLaunchDelegate;
import org.eclipse.ui.PlatformUI;

/**
 * Commands to launch additional script engines.
 */
public class ScriptingModule extends AbstractScriptModule {

	/** Module identifier. */
	public static final String MODULE_ID = "/System/Scripting";

	/**
	 * Create a new script engine instance.
	 *
	 * @param identifier
	 *            engine ID, literal engine name or accepted file extension
	 * @return script engine instance (not started) or <code>null</code>
	 */
	@WrapToScript
	public static IScriptEngine createScriptEngine(final String identifier) {
		IScriptService scriptService;
		try {
			scriptService = PlatformUI.getWorkbench().getService(IScriptService.class);
		} catch (final IllegalStateException e) {
			// in headless mode the workbench is not ready
			scriptService = ScriptService.getInstance();
		}

		// by ID
		EngineDescription engine = scriptService.getEngineByID(identifier);
		if (engine != null)
			return engine.createEngine();

		// by literal name
		final Collection<EngineDescription> engines = scriptService.getEngines();
		for (final EngineDescription description : engines) {
			if (description.getName().equals(identifier))
				return description.createEngine();
		}

		// by script type
		engine = scriptService.getEngine(identifier);
		if (engine != null)
			return engine.createEngine();

		// giving up
		return null;
	}

	/**
	 * Retrieve a list of available script engines.
	 *
	 * @return array of engine IDs
	 */
	@WrapToScript
	public static String[] listScriptEngines() {
		final List<String> result = new ArrayList<>();

		IScriptService scriptService;
		try {
			scriptService = PlatformUI.getWorkbench().getService(IScriptService.class);
		} catch (final IllegalStateException e) {
			// in headless mode the workbench is not ready
			scriptService = ScriptService.getInstance();
		}

		for (final EngineDescription description : scriptService.getEngines())
			result.add(description.getID());

		return result.toArray(new String[result.size()]);
	}

	/**
	 * Fork a new script engine and execute provided resource.
	 *
	 * @param resource
	 *            resource to execute (path, URI or file instance)
	 * @param arguments
	 *            optional script arguments delimited by commas ','. When the string arguments contains commas ',', or for arguments that are not string, the
	 *            caller may set a shared object with {@module #setSharedObject(String, Object, boolean, boolean)} and pass the key here. The callee can then
	 *            retrieve it with the {@module #getSharedObject(String)} method.
	 * @param engineID
	 *            engine ID to be used
	 * @return execution result
	 */
	@WrapToScript
	public ScriptResult fork(final Object resource, @ScriptParameter(defaultValue = ScriptParameter.NULL) final String arguments,
			@ScriptParameter(defaultValue = ScriptParameter.NULL) String engineID) {

		final ILaunch currentLaunch = getScriptEngine().getLaunch();
		final boolean useDebugger = (currentLaunch != null) && (currentLaunch.getDebugTarget() != null);

		IScriptService scriptService;
		try {
			scriptService = PlatformUI.getWorkbench().getService(IScriptService.class);
		} catch (final IllegalStateException e) {
			// in headless mode the workbench is not ready
			scriptService = ScriptService.getInstance();
		}

		EngineDescription description = null;
		if (engineID != null) {
			description = scriptService.getEngineByID(engineID);

			if (description == null)
				throw new RuntimeException("No script engine found for ID = \"" + engineID + "\"");
		}

		if (description == null) {
			// try to find engine for script type
			final String location = ResourceTools.toAbsoluteLocation(resource, getScriptEngine().getExecutedFile());
			final ScriptType scriptType = scriptService.getScriptType(location);
			if (scriptType != null) {
				if (useDebugger)
					description = scriptType.getDebugEngine();

				if (description == null)
					description = scriptType.getEngine();
			}
		}

		if (description != null) {
			final IScriptEngine engine = description.createEngine();

			// connect streams
			engine.setOutputStream(getScriptEngine().getOutputStream());
			engine.setErrorStream(getScriptEngine().getErrorStream());
			engine.setInputStream(getScriptEngine().getInputStream());
			engine.setCloseStreamsOnTerminate(false);

			// setup debugger
			if ((useDebugger) && (engine instanceof IDebugEngine)) {
				final ILaunchConfiguration launchConfiguration = currentLaunch.getLaunchConfiguration();
				if (launchConfiguration != null) {
					((IDebugEngine) engine).setupDebugger(currentLaunch, EaseLaunchDelegate.getSuspendOnStartupValue(launchConfiguration),
							EaseLaunchDelegate.getSuspendOnScriptLoadValue(launchConfiguration),
							EaseLaunchDelegate.getDisplayDynamicCodeValue(launchConfiguration));

				}
			}

			// set input parameters
			engine.setVariable("argv", AbstractScriptEngine.extractArguments(arguments));

			Object scriptObject = ResourceTools.resolve(resource, getScriptEngine().getExecutedFile());
			if (scriptObject == null) {
				// no file available, try to resolve URI
				scriptObject = URI.create(resource.toString());
			}

			final ScriptResult result = engine.executeAsync(scriptObject);
			engine.schedule();
			return result;
		}

		throw new RuntimeException("No script engine found for source \"" + resource + "\"");
	}

	/**
	 * Wait for a script engine to shut down. If <i>timeout</i> is set to 0 this method will wait endlessly.
	 *
	 * @param engine
	 *            script engine to wait for
	 * @param timeout
	 *            time to wait for shutdown [ms]
	 * @return <code>true</code> when engine is shut down
	 */
	@WrapToScript
	public static boolean join(final IScriptEngine engine, @ScriptParameter(defaultValue = "0") final long timeout) {
		if (engine instanceof Job) {
			final long stopWaitingTime = System.currentTimeMillis() + timeout;
			try {
				while (((Job) engine).getState() != Job.NONE) {
					final long now = System.currentTimeMillis();
					if (timeout == 0)
						Thread.sleep(1000);

					else if (stopWaitingTime > now)
						Thread.sleep(Math.min(stopWaitingTime - now, 1000));

					else
						// timeout depleted
						return false;
				}
			} catch (final InterruptedException e) {
				// we got interrupted - ev the current engine is shutting down?
				return false;
			}

			// job terminated
			return true;
		}

		// cannot evaluate engine state
		throw new RuntimeException("Cannot evaluate engine state");
	}

	/**
	 * Run a code fragment in a synchronized block. Executes <i>code</i> within a synchronized block on the <i>monitor</i> object. The code object might be a
	 * {@link String}, {@link File}, {@link IFile} or any other object that can be adapted to {@link IScriptable}.
	 *
	 * @param monitor
	 *            monitor to synchronize on
	 * @param code
	 *            code to run.
	 * @return execution result of executed code
	 */
	@WrapToScript
	public Object executeSync(final Object monitor, final Object code) {
		synchronized (monitor) {
			return getScriptEngine().inject(code);
		}
	}

	/**
	 * Causes the current thread to wait until either another thread invokes the {@link java.lang.Object#notify()} method or the
	 * {@link java.lang.Object#notifyAll()} method for this object, or a specified amount of time has elapsed. Calls the java method monitor.wait(timeout).
	 *
	 * @param monitor
	 *            monitor to wait for
	 * @param timeout
	 *            max timeout (0 does not time out)
	 * @throws InterruptedException
	 *             when wait gets interrupted
	 */
	@WrapToScript
	public static void wait(final Object monitor, @ScriptParameter(defaultValue = "0") final long timeout) throws InterruptedException {
		synchronized (monitor) {
			monitor.wait(timeout);
		}
	}

	/**
	 * Wakes up a single thread that is waiting on the monitor. Calls the java method monitor.notify().
	 *
	 * @param monitor
	 *            monitor to notify
	 */
	@WrapToScript
	public static void notify(final Object monitor) {
		synchronized (monitor) {
			monitor.notify();
		}
	}

	/**
	 * Wakes up all threads that are waiting on the monitor. Calls the java method monitor.notifyAll().
	 *
	 * @param monitor
	 *            monitor to notify
	 */
	@WrapToScript
	public static void notifyAll(final Object monitor) {
		synchronized (monitor) {
			monitor.notifyAll();
		}
	}

	/**
	 * Add an object to the shared object store. The shared object store allows to share java instances between several script engines. By default objects are
	 * stored until the script engine providing it is terminated. This helps to avoid polluting the java heap. When <i>permanent</i> is set to <code>true</code>
	 * , this object will be stored forever.
	 *
	 * @param key
	 *            key to store the object
	 * @param object
	 *            instance to store
	 * @param permanent
	 *            flag indicating permanent storage
	 * @param writable
	 *            flag indicating that any engine may write this value
	 * @throws IllegalAccessException
	 *             when scriptEngine is not the owner of the shared object
	 */
	@WrapToScript
	public void setSharedObject(final String key, final Object object, @ScriptParameter(defaultValue = "false") final boolean permanent,
			@ScriptParameter(defaultValue = "false") final boolean writable) throws IllegalAccessException {
		ScriptStorage.getInstance().put(key, object, getScriptEngine(), permanent, writable);
	}

	/**
	 * Get an object from the shared object store.
	 *
	 * @param key
	 *            key to retrieve object for
	 * @return shared object or <code>null</code>
	 */
	@WrapToScript
	public Object getSharedObject(final String key) {
		return ScriptStorage.getInstance().get(key);
	}

	/**
	 * Storage element for {@link ScriptStorage}.
	 */
	private static class StorageElement {
		public Object fElement;
		public Object fOwner;
		public boolean fPermanent;
		private final boolean fWritable;

		public StorageElement(final Object element, final Object owner, final boolean permanent, final boolean writable) {
			fElement = element;
			fOwner = owner;
			fPermanent = permanent;
			fWritable = writable;
		}
	}

	/**
	 * Storage singleton to share objects. This class is synchronized.
	 */
	private static class ScriptStorage implements IExecutionListener {
		private static ScriptStorage fInstance = null;

		/**
		 * Get the singleton instance.
		 *
		 * @return singleton ScriptStorage
		 */
		public synchronized static ScriptStorage getInstance() {
			if (fInstance == null)
				fInstance = new ScriptStorage();

			return fInstance;
		}

		/** Stored elements. */
		private final Map<String, StorageElement> fElements = new HashMap<>();

		/**
		 * Retrieve a shared object.
		 *
		 * @param key
		 *            key to retrieve object for
		 * @return shared object or <code>null</code>
		 */
		public synchronized Object get(final String key) {
			final StorageElement storedElement = fElements.get(key);
			return (storedElement != null) ? storedElement.fElement : null;
		}

		/**
		 * @param key
		 *            key to store the object
		 * @param object
		 *            instance to store
		 * @param scriptEngine
		 *            script engine asking for storage
		 * @param permanent
		 *            flag indicating permanent storage
		 * @param writable
		 *            flag indicating that any engine may write this value
		 * @throws IllegalAccessException
		 *             when scriptEngine is not the owner of the shared object
		 */
		public synchronized void put(final String key, final Object object, final IScriptEngine scriptEngine, final boolean permanent, final boolean writable)
				throws IllegalAccessException {
			if (fElements.containsKey(key))
				remove(key, scriptEngine);

			fElements.put(key, new StorageElement(object, getOwner(scriptEngine), permanent, writable));

			if (!permanent)
				scriptEngine.addExecutionListener(this);
		}

		/**
		 * @param key
		 * @param scriptEngine
		 * @throws IllegalAccessException
		 *             when scriptEngine is not the owner of the shared object
		 */
		public synchronized void remove(final String key, final IScriptEngine scriptEngine) throws IllegalAccessException {
			if (fElements.containsKey(key)) {
				// verify that current scriptEngine is the owner of this value or the object is writable
				final StorageElement element = fElements.get(key);
				if ((element.fWritable) || (element.fOwner.equals(getOwner(scriptEngine)))) {

					// remove element
					fElements.remove(key);
				} else
					throw new IllegalAccessException("Engine is not the owner of shared object \"" + key + "\"");
			}
		}

		/**
		 * Get unique token for object owner.
		 *
		 * @param engine
		 *            script engine owner
		 * @return owner token
		 */
		private static Object getOwner(final IScriptEngine engine) {
			// we do not want to keep the whole script engine around as owner for permanent objects as script engines are big objects.
			return engine.hashCode();
		}

		@Override
		public synchronized void notify(final IScriptEngine engine, final Script script, final int status) {
			if (status == IExecutionListener.ENGINE_END) {

				// clean up owned elements
				for (final String key : new HashSet<>(fElements.keySet())) {
					final StorageElement element = fElements.get(key);
					if ((element.fOwner.equals(getOwner(engine)) && (!element.fPermanent))) {
						try {
							remove(key, engine);
						} catch (final IllegalAccessException e) {
							// we already checked that we are the owner, so this should not happen
							Logger.error(PluginConstants.PLUGIN_ID, "Error while cleaning up shared objects", e);
						}
					}
				}

				if (fElements.isEmpty())
					// we are empty, clean up singleton
					fInstance = null;

				engine.removeExecutionListener(this);
			}
		}
	}
}
