/*******************************************************************************
 * Copyright (c) 2013 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;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.ease.ISecurityCheck.ActionType;
import org.eclipse.ease.debugging.EaseDebugFrame;
import org.eclipse.ease.debugging.IScriptDebugFrame;
import org.eclipse.ease.debugging.ScriptStackTrace;
import org.eclipse.ease.security.ScriptUIAccess;
import org.eclipse.ease.service.EngineDescription;
import org.eclipse.ease.tools.ListenerList;
import org.eclipse.ease.tools.ResourceTools;
import org.eclipse.ui.internal.progress.ProgressManager.JobMonitor;
import org.osgi.framework.Version;

/**
 * Base implementation for a script engine. Handles Job implementation of script engine, adding script code for execution, module loading support and a basic
 * online help system.
 */
public abstract class AbstractScriptEngine extends Job implements IScriptEngine {

	/**
	 * Get the current script engine. Works only if executed from the script engine thread.
	 *
	 * @return script engine or <code>null</code>
	 */
	public static IScriptEngine getCurrentScriptEngine() {
		if (Job.getJobManager().currentJob() instanceof IScriptEngine)
			return (IScriptEngine) Job.getJobManager().currentJob();

		return null;
	}

	/**
	 * Get the beautified name of a file to be set as part of the job title.
	 *
	 * @param file
	 *            executed file
	 * @return beautified name or <code>null</code>
	 */
	private static String getFilename(Object file) {
		if (file instanceof IFile) {
			return ResourceTools.toAbsoluteLocation(file, null);
		} else if (file instanceof File) {
			return ResourceTools.toAbsoluteLocation(file, null);
		} else {
			return null;
		}
	}

	/** List of code junks to be executed. */
	private final List<Script> fScheduledScripts = Collections.synchronizedList(new ArrayList<Script>());

	private final ListenerList<IExecutionListener> fExecutionListeners = new ListenerList<>();

	private PrintStream fOutputStream = null;

	private PrintStream fErrorStream = null;

	private InputStream fInputStream = null;

	private final ScriptStackTrace fStackTrace = new ScriptStackTrace();

	private EngineDescription fDescription;

	private boolean fSetupDone = false;

	/** Variables tried to set before engine was started. */
	private final Map<String, Object> fBufferedVariables = new HashMap<>();

	private boolean fCloseStreamsOnTerminate;

	/** Registered security checks for engine actions. */
	private final HashMap<ActionType, List<ISecurityCheck>> fSecurityChecks = new HashMap<>();

	private Object fExecutionRootFile;;

	/** Launch associated with this engine. */
	private ILaunch fLaunch = null;

	private IProgressMonitor fMonitor;

	/**
	 * Constructor. Sets the name for the underlying job.
	 *
	 * @param name
	 *            name of script engine job
	 */
	public AbstractScriptEngine(final String name) {
		super("[EASE " + name + " Engine]");

		// by default an engine shall be visible to the user. If the engine
		setSystem(false);
	}

	@Override
	public EngineDescription getDescription() {
		return fDescription;
	}

	@Override
	public final ScriptResult executeAsync(final Object content) {
		final Script script = (content instanceof Script) ? (Script) content : new Script(content);
		fScheduledScripts.add(script);

		synchronized (this) {
			notifyAll();
		}

		return script.getResult();
	}

	@Override
	public final ScriptResult executeSync(final Object content) throws InterruptedException {

		// we need to schedule the script first or the engine might finish before we can schedule the script
		final ScriptResult result = executeAsync(content);

		if (getState() == NONE)
			// automatically schedule engine as it is not started yet
			schedule();

		result.waitForResult();

		return result;
	}

	@Override
	public final Object inject(final Object content) {
		return internalInject(content, false);
	}

	@Override
	public final Object injectUI(final Object content) {
		return internalInject(content, true);
	}

	private final Object internalInject(final Object content, final boolean uiThread) {
		// injected code shall not trigger a new event, therefore notifyListerners needs to be false
		ScriptResult result;
		if (content instanceof Script)
			result = inject((Script) content, false, uiThread);
		else
			result = inject(new Script(content), false, uiThread);

		if (result.hasException()) {
			// re-throw previous exception

			if (result.getException() instanceof RuntimeException)
				throw (RuntimeException) result.getException();

			throw new RuntimeException(result.getException().getMessage(), result.getException());
		}

		return result.getResult();
	}

	/**
	 * Inject script code to the script engine. Injected code is processed synchronous by the current thread unless <i>uiThread</i> is set to <code>true</code>.
	 * Nevertheless this is a blocking call.
	 *
	 * @param script
	 *            script to be executed
	 * @param notifyListeners
	 *            <code>true</code> when listeners should be informed of code fragment
	 * @param uiThread
	 *            when set to <code>true</code> run injected code in UI thread
	 * @return script execution result
	 */
	private ScriptResult inject(final Script script, final boolean notifyListeners, final boolean uiThread) {

		try {
			Logger.trace(Activator.PLUGIN_ID, TRACE_SCRIPT_ENGINE, "Executing script (" + script.getTitle() + "):", script.getCode());
			final String filename = getFilename(script.getFile());
			fStackTrace.add(0, new EaseDebugFrame(script, 0, IScriptDebugFrame.TYPE_FILE, filename));
			updateJobName(filename);

			// apply security checks
			final List<ISecurityCheck> securityChecks = fSecurityChecks.get(ActionType.INJECT_CODE);
			if (securityChecks != null) {
				for (final ISecurityCheck check : securityChecks) {
					if (!check.doIt(ActionType.INJECT_CODE, script, uiThread))
						throw new ScriptEngineException("Security check failed: " + check.toString());
				}
			}

			// execution
			if (notifyListeners)
				notifyExecutionListeners(script, IExecutionListener.SCRIPT_START);
			else
				notifyExecutionListeners(script, IExecutionListener.SCRIPT_INJECTION_START);

			script.setResult(execute(script, script.getFile(), fStackTrace.get(0).getName(), uiThread));

		} catch (final BreakException e) {
			script.setResult(e.getCondition());

		} catch (final Throwable e) {
			// only do the printing if this is the last script on the stack
			// otherwise we will print multiple times for each rethrow
			if (fStackTrace.size() <= 1)
				e.printStackTrace(getErrorStream());

			script.setException(e);

		} finally {
			if (notifyListeners)
				notifyExecutionListeners(script, IExecutionListener.SCRIPT_END);
			else
				notifyExecutionListeners(script, IExecutionListener.SCRIPT_INJECTION_END);

			if (!fStackTrace.isEmpty())
				fStackTrace.remove(0);
		}

		return script.getResult();
	}

	private void updateJobName(String filename) {
		if (filename != null) {
			String baseName = getName();
			if (baseName.contains("]"))
				baseName = baseName.substring(0, baseName.indexOf(']') + 1);

			setName(baseName + " " + filename);
		}
	}

	@Override
	protected IStatus run(final IProgressMonitor monitor) {
		fMonitor = monitor;

		addStopButtonMonitor();

		IStatus returnStatus = setupRun();
		if (Status.OK_STATUS.equals(returnStatus)) {
			// main loop
			while (!shallTerminate()) {

				// execute code
				if (!fScheduledScripts.isEmpty()) {
					final Script piece = fScheduledScripts.remove(0);
					inject(piece, true, false);

				} else {
					synchronized (this) {
						try {
							Logger.trace(Activator.PLUGIN_ID, TRACE_SCRIPT_ENGINE, "Engine idle: " + getName());
							wait();
						} catch (final InterruptedException e) {
						}
					}
				}
			}
		}

		if (getMonitor().isCanceled())
			returnStatus = Status.CANCEL_STATUS;

		return cleanupRun(returnStatus);
	}

	private IStatus setupRun() {
		Logger.trace(Activator.PLUGIN_ID, TRACE_SCRIPT_ENGINE, "Engine started: " + getName());

		addSecurityCheck(ActionType.INJECT_CODE, ScriptUIAccess.getInstance());

		try {
			setupEngine();
			fSetupDone = true;

			// engine is initialized, set buffered variables
			for (final Entry<String, Object> entry : fBufferedVariables.entrySet()) {
				setVariable(entry.getKey(), entry.getValue());
			}

			fBufferedVariables.clear();

			// setup new trace
			fStackTrace.clear();

			notifyExecutionListeners(null, IExecutionListener.ENGINE_START);

		} catch (final ScriptEngineException e) {
			return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Could not setup script engine", e);
		}

		return Status.OK_STATUS;
	}

	private IStatus cleanupRun(IStatus returnStatus) {

		// discard pending code pieces
		synchronized (fScheduledScripts) {
			for (final Script script : fScheduledScripts)
				script.setException(new ScriptExecutionException("Engine got terminated"));
		}

		fScheduledScripts.clear();

		notifyExecutionListeners(null, IExecutionListener.ENGINE_END);

		try {
			teardownEngine();
		} catch (final ScriptEngineException e) {
			if (returnStatus.getSeverity() < IStatus.ERROR) {
				// We were almost all OK (or just warnings/infos) but then we failed at shutdown
				// Note we don't override a CANCEL
				returnStatus = new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Could not teardown script engine", e);
			}
		} finally {
			synchronized (this) {
				notifyAll();
			}

			closeStreams();

			Logger.trace(Activator.PLUGIN_ID, TRACE_SCRIPT_ENGINE, "Engine terminated: " + getName());

			fMonitor.done();
			fMonitor = null;
		}

		return returnStatus;
	}

	/**
	 * Add monitor to detect clicks on the stop button in the Progress view. This functionality improves usability, but is not essential to scripting.
	 */
	private void addStopButtonMonitor() {
		if (fMonitor instanceof JobMonitor) {
			final Version workbenchBundleVersion = Platform.getBundle("org.eclipse.ui.workbench").getVersion();
			if (workbenchBundleVersion.compareTo(Version.valueOf("3.120.0")) >= 0) {
				addStopButtonMonitorForEclipse2020v09();

			} else if (workbenchBundleVersion.compareTo(Version.valueOf("3.110.1")) >= 0) {
				addStopButtonMonitorForEclipseOxygenTo2020v06();
			} else {
				// JobMonitor is a private class up to 3.110.1 (Eclipse Oxygen)
			}
		}
	}

	private void addStopButtonMonitorForEclipseOxygenTo2020v06() {
		// JobMonitor changed its API from
		// addProgressListener(IProgressMonitor)
		// to
		// addProgressListener(IProgressMonitorWithBlocking)
		// in 2020.09
		try {
			final Method addProgressListener = JobMonitor.class.getDeclaredMethod("addProgressListener", new Class[] { IProgressMonitorWithBlocking.class });
			addProgressListener.invoke(fMonitor, new ScriptEngineMonitor());
		} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			// silently ignore
		}
	}

	private void addStopButtonMonitorForEclipse2020v09() {
		((JobMonitor) fMonitor).addProgressListener(new ScriptEngineMonitor());
	}

	/**
	 * Evaluate if the engine shall terminate.
	 *
	 * @return <code>true</code> when termination is requested or there is no more work to be done
	 */
	protected boolean shallTerminate() {
		return getMonitor().isCanceled() || fScheduledScripts.isEmpty();
	}

	@Override
	public void terminate() {

		final IProgressMonitor monitor = getMonitor();
		if ((monitor != null) && (!monitor.isCanceled()))
			monitor.setCanceled(true);

		terminateCurrent();

		synchronized (this) {
			notify();
		}
	}

	/**
	 * Check engine for cancellation request and terminate if indicated by the monitor.
	 */
	public void checkForCancellation() {
		final IProgressMonitor monitor = getMonitor();
		if ((monitor != null) && (monitor.isCanceled())) {
			if (Thread.currentThread().equals(getThread()))
				throw new ScriptExecutionException("Engine got terminated");
		}
	}

	@Override
	public boolean isFinished() {
		// setup was done, hence we were started
		return (Job.NONE == getState()) && fSetupDone;
	}

	@Override
	public void joinEngine() throws InterruptedException {
		if (!Thread.currentThread().equals(getThread())) {
			// we cannot join our own thread

			synchronized (this) {
				while (!isFinished())
					wait(1000);
			}
		}
	}

	@Override
	public void joinEngine(final long timeout) throws InterruptedException {
		if (!Thread.currentThread().equals(getThread())) {
			// we cannot join our own thread

			synchronized (this) {
				if (!isFinished())
					wait(timeout);
			}
		}
	}

	@Override
	public IProgressMonitor getMonitor() {
		return fMonitor;
	}

	private void closeStreams() {
		if (fCloseStreamsOnTerminate) {
			// gracefully close I/O streams
			try {
				if ((getInputStream() != null) && (!System.in.equals(getInputStream())))
					getInputStream().close();
			} catch (final IOException e) {
			}
			try {
				if ((getOutputStream() != null) && (!System.out.equals(getOutputStream())))
					getOutputStream().close();
			} catch (final Exception e) {
			}
			try {
				if ((getErrorStream() != null) && (!System.err.equals(getErrorStream())))
					getErrorStream().close();
			} catch (final Exception e) {
			}
		}

		fOutputStream = null;
		fErrorStream = null;
		fInputStream = null;
	}

	@Override
	public void setCloseStreamsOnTerminate(final boolean closeStreams) {
		fCloseStreamsOnTerminate = closeStreams;
	}

	@Override
	public PrintStream getOutputStream() {
		return (fOutputStream != null) ? fOutputStream : System.out;
	}

	@Override
	public void setOutputStream(final OutputStream outputStream) {
		if (outputStream instanceof PrintStream)
			fOutputStream = (PrintStream) outputStream;

		else if (outputStream != null)
			fOutputStream = new PrintStream(outputStream);
		else
			fOutputStream = null;
	}

	@Override
	public InputStream getInputStream() {
		return (fInputStream != null) ? fInputStream : System.in;
	}

	@Override
	public void setInputStream(final InputStream inputStream) {
		fInputStream = inputStream;
	}

	@Override
	public PrintStream getErrorStream() {
		return (fErrorStream != null) ? fErrorStream : System.err;
	}

	@Override
	public void setErrorStream(final OutputStream errorStream) {
		if (errorStream instanceof PrintStream)
			fErrorStream = (PrintStream) errorStream;

		else if (errorStream != null)
			fErrorStream = new PrintStream(errorStream);
		else
			fErrorStream = null;
	}

	@Override
	public void addExecutionListener(final IExecutionListener listener) {
		fExecutionListeners.add(listener);
	}

	@Override
	public void removeExecutionListener(final IExecutionListener listener) {
		fExecutionListeners.remove(listener);
	}

	protected void notifyExecutionListeners(final Script script, final int status) {
		for (final Object listener : fExecutionListeners.getListeners())
			((IExecutionListener) listener).notify(this, script, status);
	}

	public ScriptStackTrace getStackTrace() {
		return fStackTrace;
	}

	@Override
	public Object getExecutedFile() {
		for (final IScriptDebugFrame trace : getStackTrace()) {
			if (trace.getType() == IScriptDebugFrame.TYPE_FILE) {
				if (trace.getScript() != null) {
					final Object file = trace.getScript().getFile();
					if (file != null)
						return file;
				}
			}
		}

		return fExecutionRootFile;
	}

	public void setExecutionRootFile(Object executionRootFile) {
		fExecutionRootFile = executionRootFile;
	}

	public void setEngineDescription(final EngineDescription description) {
		fDescription = description;
	}

	@Override
	public void setVariable(final String name, final Object content) {
		if (fSetupDone)
			internalSetVariable(name, content);

		else
			fBufferedVariables.put(name, content);
	}

	@Override
	public Object getVariable(final String name) {
		if (fSetupDone)
			return internalGetVariable(name);

		return fBufferedVariables.get(name);
	}

	@Override
	public boolean hasVariable(final String name) {
		if (fSetupDone)
			return internalHasVariable(name);

		return fBufferedVariables.containsKey(name);
	}

	@Override
	public Map<String, Object> getVariables() {
		if (fSetupDone)
			return internalGetVariables();

		return Collections.unmodifiableMap(fBufferedVariables);
	}

	/**
	 * Split a string with comma separated arguments.
	 *
	 * @param arguments
	 *            comma separated arguments
	 * @return trimmed list of arguments
	 */
	public static final String[] extractArguments(final String arguments) {
		final ArrayList<String> args = new ArrayList<>();
		if (arguments != null) {

			final String[] tokens = arguments.split(",");
			for (final String token : tokens) {
				if (!token.trim().isEmpty())
					args.add(token.trim());
			}
		}

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

	@Override
	public void addSecurityCheck(ActionType type, ISecurityCheck check) {
		if (!fSecurityChecks.containsKey(type))
			fSecurityChecks.put(type, new ArrayList<ISecurityCheck>());

		if (!fSecurityChecks.get(type).contains(check))
			fSecurityChecks.get(type).add(check);
	}

	@Override
	public void removeSecurityCheck(ISecurityCheck check) {
		for (final List<ISecurityCheck> entry : fSecurityChecks.values()) {
			entry.remove(check);
		}
	}

	protected List<Script> getScheduledScripts() {
		return fScheduledScripts;
	}

	public void setLaunch(ILaunch launch) {
		fLaunch = launch;
	}

	@Override
	public ILaunch getLaunch() {
		return fLaunch;
	}

	/**
	 * Internal version of {@link #getVariable(String)}. Only called after script engine was initialized successfully.
	 */
	protected abstract Object internalGetVariable(String name);

	/**
	 * Internal version of {@link #getVariables()}. Only called after script engine was initialized successfully.
	 */
	protected abstract Map<String, Object> internalGetVariables();

	/**
	 * Internal version of {@link #hasVariable(String)}. Only called after script engine was initialized successfully.
	 */
	protected abstract boolean internalHasVariable(String name);

	/**
	 * Internal version of {@link #setVariable(String, Object)}. Only called after script engine was initialized successfully.
	 */
	protected abstract void internalSetVariable(String name, Object content);

	/**
	 * Setup method for script engine. Run directly after the engine is activated.
	 *
	 * Unresolvable errors should be indicated by throwing a ScriptEngineException with details as to what went wrong.
	 */
	protected abstract void setupEngine() throws ScriptEngineException;

	/**
	 * Teardown engine. Called immediately before the engine terminates. This method is called even when {@link #setupEngine()} fails.
	 */
	protected abstract void teardownEngine() throws ScriptEngineException;

	/**
	 * Execute script code.
	 *
	 * @param fileName
	 *            name of file executed
	 * @param uiThread
	 * @param reader
	 *            reader for script data to be executed
	 * @param uiThread
	 *            when set to <code>true</code> run code in UI thread
	 * @return execution result
	 * @throws Throwable
	 *             any exception thrown during script execution
	 */
	protected abstract Object execute(Script script, Object reference, String fileName, boolean uiThread) throws Throwable;

	/**
	 * Simple monitor to forward cancellation requests to the script engine.
	 */
	private class ScriptEngineMonitor extends NullProgressMonitor implements IProgressMonitorWithBlocking {

		@Override
		public void setCanceled(boolean cancelled) {
			super.setCanceled(cancelled);

			if (isCanceled())
				terminate();
		}

		@Override
		public void setBlocked(IStatus reason) {
			// nothing to do
		}

		@Override
		public void clearBlocked() {
			// nothing to do
		}
	}
}
