/*****************************************************************************
 * Copyright (c) 2019 CEA LIST and others.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   CEA LIST - Initial API and implementation
 *   
 *****************************************************************************/
package org.eclipse.papyrus.ease.lang.python.jupyter.internal;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.channels.SocketChannel;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.ease.ScriptEngineException;
import org.eclipse.ease.lang.python.py4j.internal.IPythonSideEngine;
import org.eclipse.papyrus.ease.lang.python.jupyter.Activator;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;

import py4j.ClientServer;
import py4j.ClientServer.ClientServerBuilder;
import py4j.JavaServer;

public class JupyterProxy {

	private static final int PYTHON_SHUTDOWN_TIMEOUT_SECONDS = 10;
	private static final int PYTHON_STARTUP_TIMEOUT_SECONDS = 60;

	/**
	 * Path within this plug-in to the main python file.
	 */
	private static final String PYSRC_EASE_PY4J_MAIN_DIR = "/pysrc/";

	/**
	 * The ID of the py4j sources plug-in, needs to match the name of the dependent
	 * plug-in.
	 */
	private static final String PY4J_PYTHON_BUNDLE_ID = "py4j-python";

	private static final String EASE_PY4J_BUNDLE_ID = "org.eclipse.ease.lang.python.py4j";

	private static final String JUPYTER_PATH = "JUPYTER_PATH";

	private static final String PYTHON_PATH = "PYTHONPATH";

	private static final String EASE_PYTHON_COMMON_BUNDLE_ID = "org.eclipse.ease.lang.python";

	private static final String PY4J_PATH = "PY4J_PATH";

	private static final String EASE_PYTHON_COMMON_SRC = "EASE_PYTHON_COMMON_SRC";

	private static final String EASE_PY4J_SRC = "EASE_PY4J_SRC";
	private static final String JUPYTER_TOKEN = "JUPYTER_TOKEN";
	private static final String EASE_JAVA_PORT = "EASE_JAVA_PORT";

	private int notebookPort = -1;
	private String notebookToken = UUID.randomUUID().toString();
	private String notebookDirectory = System.getProperty("user.home");

	private boolean startBrowser = false;
	private boolean debug = false;

	private CountDownLatch pythonStartupComplete;
	private ClientServer gatewayServer;
	private IPythonSideEngine pythonSideEngine;
	private Process jupyterProcess;
	private String notebookName;
	
	private String pythonInterpreter = getPythonInterpreterExec();

	public JupyterProxy() {

	}

	public int getNotebookPort() {
		return notebookPort;
	}

	public JupyterProxy setNotebookPort(int notebookPort) {
		this.notebookPort = notebookPort;
		return this;
	}

	public String getNotebookToken() {
		return notebookToken;
	}

	public JupyterProxy setNotebookToken(String notebookToken) {
		this.notebookToken = notebookToken;
		return this;
	}

	public String getNotebookDirectory() {
		return notebookDirectory;
	}

	public JupyterProxy setNotebookDirectory(String notebookDirectory) {
		this.notebookDirectory = notebookDirectory;
		return this;
	}

	public JupyterProxy setStartBrowser(boolean startBrowser) {
		this.startBrowser = startBrowser;
		return this;
	}

	public ClientServer getGatewayServer() {
		return gatewayServer;
	}

	public boolean isDebug() {
		return debug;
	}

	public JupyterProxy setDebug(boolean debug) {
		this.debug = debug;
		return this;
	}

	public IPythonSideEngine getPythonSideEngine() {
		return pythonSideEngine;
	}

	public Process getJupyterProcess() throws MalformedURLException, IOException, URISyntaxException, CoreException,
			InterruptedException, ScriptEngineException {
		if (jupyterProcess == null) {
			startJupyterProcess();
		}
		return jupyterProcess;
	}

	public void startJupyterProcess() throws InterruptedException, ScriptEngineException, IOException, URISyntaxException {

		notebookPort = getFreePort(8888);

		
		gatewayServer = new ClientServerBuilder(this).javaPort(0).pythonPort(0).build();
		gatewayServer.startServer(true);
		final int javaListeningPort = ((JavaServer) gatewayServer.getJavaServer()).getListeningPort();
		
		final ProcessBuilder pb = new ProcessBuilder();

		
		

		// we use Py4J python interpreter, should include Jupyter
		pb.command().add(pythonInterpreter);
		pb.command().add("-m");
		pb.command().add("notebook");
		pb.command().add("--notebook-dir=" + notebookDirectory);
		String fullPath = notebookDirectory+File.separator+"static";
		fullPath = fullPath.replace("\\", "\\\\");
		pb.command().add("--NotebookApp.extra_static_paths=['"+fullPath+"']");
		if (notebookPort > -1) {
			pb.command().add("--port=" + notebookPort);
		}
		if (!startBrowser) {
			pb.command().add("--no-browser");
		}

		if (debug) {
			pb.command().add("--debug");
		}

		// JUPYTER_PATH is modified to add our new kernel description
		// see http://jupyter-client.readthedocs.io/en/stable/kernels.html#kernel-specs
		pb.environment().put(JUPYTER_PATH,
				appendToCurrentEnvPath(JUPYTER_PATH, getJupyterPathDirectory().getAbsolutePath()));

		// we also add the kernel directory in PYTHON_PATH in order to allow the
		// first-level python to load our custom python kernel
		pb.environment().put(PYTHON_PATH,
				appendToCurrentEnvPath(PYTHON_PATH, getJupyterKernelDirectory().getAbsolutePath()));
		
		
		// we now add several environment variable that will be read during our easepy4j
		// kernel startup to establish connection
		// with Py4J java side initiated by EASE
		pb.environment().put(EASE_JAVA_PORT, String.valueOf(javaListeningPort));

		pb.environment().put(JUPYTER_TOKEN, notebookToken);

		pb.environment().put(PY4J_PATH, getPy4jPythonSrc().getAbsolutePath());
		pb.environment().put(EASE_PYTHON_COMMON_SRC, getEASEPythonCommonSrc().getAbsolutePath());
		pb.environment().put(EASE_PY4J_SRC, getPy4jEaseMainDir().getAbsolutePath());

		
		jupyterProcess = pb.start();

		

		
		pythonStartupComplete = new CountDownLatch(1);

		

	}

	private String getPythonInterpreterExec() {
		String interpreter = Platform.getPreferencesService().getString("org.eclipse.ease.lang.python.py4j",
				"org.eclipse.ease.lang.python.py4j.INTERPRETER", "python", null);
		final IStringVariableManager variableManager = VariablesPlugin.getDefault().getStringVariableManager();
		try {
			interpreter = variableManager.performStringSubstitution(interpreter);
		} catch (CoreException e) {
			interpreter = "python";
		}
		return interpreter;
	}

	private void waitForJupyterStartup() throws InterruptedException, ScriptEngineException, IOException{
		boolean scanning=true;
		SocketAddress address = new InetSocketAddress("localhost", notebookPort);
		
		int attempts = 0;
		while(scanning && attempts < 200){
		    try{
		    	attempts++;
		    	SocketChannel.open(address);
		        scanning=false;
		    }
		    catch(IOException e){
		        Thread.sleep(100);//0.1 second
		    } 
		}
		if (scanning) {
			throw new ScriptEngineException("Jupyter notebook did not start within 20 seconds");
		}
	}

	public void waitForKernelStartup() throws InterruptedException, ScriptEngineException, IOException {
		
		waitForJupyterStartup();
		
		//web browser will start the kernel if a notebook has been selected to be run as EASE script
		//else user will have to manually start the kernel in the browser
		openWebBrowser();
		
		// We wait here for the main notebook python process initialization
		if (!pythonStartupComplete.await(PYTHON_STARTUP_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
			throw new ScriptEngineException(
					"Kernel process did not start within " + PYTHON_STARTUP_TIMEOUT_SECONDS + " seconds");
		}

	}

	public void pythonStartupComplete(final int pythonPort, final IPythonSideEngine pythonSideEngine) {
		final JavaServer javaServer = (JavaServer) gatewayServer.getJavaServer();
		javaServer.resetCallbackClient(javaServer.getCallbackClient().getAddress(), pythonPort);

		this.pythonSideEngine = pythonSideEngine;

		pythonStartupComplete.countDown();

	}

	private void openWebBrowser() {

		Display.getDefault().asyncExec(new Runnable() {

			@Override
			public void run() {

				try {
					// even if we wait for python startup, still have to wait for server startup to
					// avoid to have to refresh the page
					TimeUnit.SECONDS.sleep(3);
					IWebBrowser browser = PlatformUI.getWorkbench().getBrowserSupport().createBrowser(null);
					browser.openURL(getNoteBookURL());

				} catch (PartInitException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		});

	}

	private URL getNoteBookURL() throws MalformedURLException {
		String urlString = "http://localhost:" + notebookPort;
		if (notebookName != null) {
			urlString += "/notebooks/" + notebookName;
		}
		urlString += "?token=" + notebookToken;

		return new URL(urlString);
	}

	private File getEASEPythonCommonSrc() throws IOException {

		final File easePythonCommonBundleFile = FileLocator
				.getBundleFile(Platform.getBundle(EASE_PYTHON_COMMON_BUNDLE_ID));
		final File easePythonCommonSrc = new File(easePythonCommonBundleFile, "/pysrc");

		if (!easePythonCommonSrc.exists() || !easePythonCommonSrc.isDirectory()) {
			throw new IOException(
					"Failed to find EASE commong python directory, expected it here: " + easePythonCommonSrc);
		}
		return easePythonCommonSrc;
	}

	private File getPy4jPythonSrc() throws IOException {
		final File py4jPythonBundleFile = FileLocator.getBundleFile(Platform.getBundle(PY4J_PYTHON_BUNDLE_ID));
		final File py4jPythonSrc = new File(py4jPythonBundleFile, "/src");
		//final File py4j = new File(py4jPythonSrc, "py4j");
		if (!py4jPythonSrc.exists() || !py4jPythonSrc.isDirectory()) {
			throw new IOException("Failed to find py4j python directory, expected it here: " + py4jPythonSrc);
		}
		return py4jPythonSrc;
	}

	private File getPy4jEaseMainDir() throws MalformedURLException, IOException, URISyntaxException {
		final URL url = new URL("platform:/plugin/" + EASE_PY4J_BUNDLE_ID + PYSRC_EASE_PY4J_MAIN_DIR);
		final URL fileURL = FileLocator.toFileURL(url);
		final File py4jEaseMain = new File(URIUtil.toURI(fileURL).normalize());
		if (!py4jEaseMain.exists() && !py4jEaseMain.isDirectory()) {
			throw new IOException("Failed to find " + PYSRC_EASE_PY4J_MAIN_DIR + ", expected it here: " + py4jEaseMain);
		}
		return py4jEaseMain;
	}
	private File getJupyterPathDirectory() throws IOException, URISyntaxException {
		final URL url = new URL("platform:/plugin/"+Activator.PLUGIN_ID+"/jupyter");
		final URL fileURL = FileLocator.toFileURL(url);		
		final File rootDir =  new File(URIUtil.toURI(fileURL).normalize());
		if (!rootDir.exists() || !rootDir.isDirectory()) {
			throw new IOException(
					"Failed to find ease-py4j Jupyter kernel root directory, expected it here: " + rootDir);
		}
		return rootDir;
	}

	private File getJupyterKernelDirectory() throws IOException, URISyntaxException {
		final File jupyterPath = getJupyterPathDirectory();
		final File kernelDirectory = new File(jupyterPath, "/kernels/ease_py4j_kernel");
		if (!kernelDirectory.exists() || !kernelDirectory.isDirectory()) {
			throw new IOException(
					"Failed to find ease-py4j Jupyter kernel  directory, expected it here: " + kernelDirectory);
		}
		return kernelDirectory;
	}

	private String appendToCurrentEnvPath(String variableName, String value) {
		String currentPath = System.getenv(variableName);

		if (currentPath == null) {
			currentPath = value;
		} else {
			currentPath = value + File.pathSeparator + currentPath;
		}
		return currentPath;
	}

	/**
	 * Tries to find a new free port close to the given start port.
	 * <p>
	 * Not that there is a (unlikely but) possible race condition if the returned
	 * port is being used between calling this and actually starting a server.
	 * Handle blocked servers appropriately.
	 * 
	 * @param startPort
	 *            Lowest desired port number.
	 * @return Free port (hopefully) close to startPort.
	 */
	public static int getFreePort(int startPort) {
		ServerSocket socket = null;
		while (true) {
			try {
				// Try to create server for port number
				socket = new ServerSocket(startPort);

				// Make reusable to timeout state problems
				socket.setReuseAddress(true);

				// No exception -> port is free
				return startPort;
			} catch (IOException ignore) {
				// IOException most (!) likely because of used port
				startPort++;
			} finally {
				if (socket != null) {
					try {
						socket.close();
					} catch (IOException ignore) {
						// Should not occur
					}
				}
			}
		}
	}

	public JupyterProxy setNotebook(IFile scriptFile) {
		notebookDirectory = scriptFile.getParent().getLocation().toOSString();
		notebookName = scriptFile.getName();
		return this;
	}

	public void shutDown() {

		
		ProcessBuilder stopProcess = new ProcessBuilder().command(
				pythonInterpreter, 
				"-m",
				"notebook",
				"stop",
				Integer.toString(notebookPort)
				);
		
		try {
			Process process =stopProcess.start();
			process.waitFor(PYTHON_SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS);
			
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		

		if (gatewayServer != null) {
			gatewayServer.shutdown();
		}
		
	}

}
