/*******************************************************************************
 * 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 java.util.concurrent.ExecutionException;

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 execute(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 Object inject(Object content, boolean uiThread) throws ExecutionException {
		final Script script = (content instanceof Script) ? (Script) content : new Script(content);

		// injected code shall not trigger a new event, therefore notifyListerners needs to be false
		return inject(script, false, uiThread).get();
	}

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

			if (e instanceof ScriptExecutionException)
				script.setException((ScriptExecutionException) e);
			else
				script.setException(new ScriptExecutionException(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 ScriptEngineCancellationException();
		}
	}

	@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
		}
	}
}
