/*=============================================================================#
 # Copyright (c) 2008, 2020 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.r.console.ui.launching;

import java.net.InetAddress;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.statushandlers.StatusManager;

import org.eclipse.statet.jcommons.rmi.RMIAddress;
import org.eclipse.statet.jcommons.rmi.RMIRegistry;
import org.eclipse.statet.jcommons.rmi.RMIRegistryManager;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.jcommons.status.WarningStatus;
import org.eclipse.statet.jcommons.ts.core.SystemRunnable;
import org.eclipse.statet.jcommons.ts.core.Tool;
import org.eclipse.statet.jcommons.ts.core.ToolService;

import org.eclipse.statet.ecommons.debug.core.util.LaunchUtils;
import org.eclipse.statet.ecommons.debug.ui.util.UnterminatedLaunchAlerter;
import org.eclipse.statet.ecommons.runtime.core.util.StatusUtils;
import org.eclipse.statet.ecommons.ui.util.UIAccess;

import org.eclipse.statet.internal.r.console.ui.Messages;
import org.eclipse.statet.internal.r.console.ui.RConsoleUIPlugin;
import org.eclipse.statet.nico.core.runtime.ILogOutput;
import org.eclipse.statet.nico.core.runtime.ToolRunner;
import org.eclipse.statet.nico.core.util.HistoryTrackingConfiguration;
import org.eclipse.statet.nico.core.util.TrackingConfiguration;
import org.eclipse.statet.nico.ui.NicoUITools;
import org.eclipse.statet.nico.ui.console.NIConsoleColorAdapter;
import org.eclipse.statet.nico.ui.util.WorkbenchStatusHandler;
import org.eclipse.statet.r.console.core.IRDataAdapter;
import org.eclipse.statet.r.console.core.RProcess;
import org.eclipse.statet.r.console.core.RWorkspace;
import org.eclipse.statet.r.console.ui.RConsole;
import org.eclipse.statet.r.console.ui.launching.RConsoleLaunching;
import org.eclipse.statet.r.console.ui.tools.REnvAutoUpdater;
import org.eclipse.statet.r.console.ui.tools.REnvIndexAutoUpdater;
import org.eclipse.statet.r.core.RCore;
import org.eclipse.statet.r.core.pkgmanager.IRPkgManager;
import org.eclipse.statet.r.core.renv.IREnvConfiguration;
import org.eclipse.statet.r.launching.core.ILaunchDelegateAddon;
import org.eclipse.statet.r.launching.core.RLaunching;
import org.eclipse.statet.r.nico.RWorkspaceConfig;
import org.eclipse.statet.r.nico.impl.RjsController;
import org.eclipse.statet.r.nico.impl.RjsController.RjsConnection;
import org.eclipse.statet.rj.data.RDataUtils;
import org.eclipse.statet.rj.data.UnexpectedRDataException;
import org.eclipse.statet.rj.renv.core.REnvConfiguration;
import org.eclipse.statet.rj.server.RjsComConfig;
import org.eclipse.statet.rj.services.FunctionCall;
import org.eclipse.statet.rj.services.RVersion;


/**
 * Launch delegate for RJ based R console using local RJ server
 */
public class RConsoleRJLaunchDelegate extends LaunchConfigurationDelegate {
	
	
	static final long TIMEOUT= 60L * 1000000000L;
	
	static final RVersion VERSION_2_12_0= new RVersion(2, 12, 0);
	
	static class ConfigRunnable implements SystemRunnable {
		
		
		private final Tool tool;
		private final boolean enableRHelp;
		private final boolean enableRGraphics;
		private final boolean enableRDbgExt;
		private final boolean enableRDbg;
		
		public ConfigRunnable(final Tool tool, final boolean enableRHelp,
				final boolean enableRGraphics,
				final boolean enableRDbgExt, final boolean enableRDbg) {
			this.tool= tool;
			this.enableRHelp= enableRHelp;
			this.enableRGraphics= enableRGraphics;
			this.enableRDbgExt= enableRDbgExt;
			this.enableRDbg= enableRDbg;
		}
		
		
		@Override
		public String getTypeId() {
			return "r/integration"; //$NON-NLS-1$
		}
		
		@Override
		public String getLabel() {
			return "Initialize R-StatET Tools";
		}
		
		@Override
		public boolean canRunIn(final Tool tool) {
			return (tool == this.tool);
		}
		
		@Override
		public boolean changed(final int event, final Tool process) {
			if ((event & MASK_EVENT_GROUP) == REMOVING_EVENT_GROUP) {
				return false;
			}
			return true;
		}
		
		@Override
		public void run(final ToolService service, final ProgressMonitor m) throws StatusException {
			final IRDataAdapter r= (IRDataAdapter) service;
			r.briefAboutToChange();
			try {
				final RVersion rVersion= r.getPlatform().getRVersion();
				if (rVersion.compareTo(VERSION_2_12_0) < 0) {
					r.evalVoid("library('rj')", m); //$NON-NLS-1$
				}
				else {
					r.evalVoid("library('rj', quietly= TRUE)", m); //$NON-NLS-1$
				}
				if (this.enableRHelp) {
					final FunctionCall fcall= r.createFunctionCall(".statet.initHelp"); //$NON-NLS-1$
					fcall.evalVoid(m);
				}
				if (this.enableRGraphics) {
					try {
						final FunctionCall fcall= r.createFunctionCall(".rj.initGD"); //$NON-NLS-1$
						fcall.addLogi("default", true); //$NON-NLS-1$
						RDataUtils.checkSingleLogiValue(fcall.evalData(m));
					}
					catch (final StatusException | UnexpectedRDataException e) {
						r.handleStatus(new WarningStatus(RConsoleUIPlugin.BUNDLE_ID,
								"The graphic device for the R Graphic view cannot be initialized.", e),
								m );
					}
				}
				{	final FunctionCall fcall= r.createFunctionCall(".statet.initDebug"); //$NON-NLS-1$
					fcall.addLogi("mode", this.enableRDbg); //$NON-NLS-1$
					fcall.addLogi("ext", this.enableRDbgExt); //$NON-NLS-1$
					fcall.evalVoid(m);
				}
			}
			finally {
				r.briefChanged(RWorkspace.REFRESH_COMPLETE);
			}
		}
		
	}
	
	static RWorkspaceConfig createWorkspaceConfig(final ILaunchConfiguration configuration) throws CoreException {
		final RWorkspaceConfig config= new RWorkspaceConfig();
		config.setEnableObjectDB(configuration.getAttribute(RConsoleLaunching.ATTR_OBJECTDB_ENABLED, true));
		config.setEnableAutoRefresh(configuration.getAttribute(RConsoleLaunching.ATTR_OBJECTDB_AUTOREFRESH_ENABLED, true));
		return config;
	}
	
	static void initConsoleOptions(final RjsController controller,
			final REnvConfiguration rEnvConfig,
			final ILaunchConfiguration configuration, final String mode,
			final boolean isStartup) throws CoreException {
		if (rEnvConfig != null) {
			final IRPkgManager manager= RCore.getRPkgManager(rEnvConfig.getREnv());
			REnvAutoUpdater.connect(controller, manager);
			REnvIndexAutoUpdater.connect(controller.getTool(), manager);
		}
		controller.addStartupRunnable(new ConfigRunnable(
				controller.getTool(),
				(rEnvConfig != null && configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RHELP_ENABLED, true)),
				configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RGRAPHICS_ASDEFAULT, true),
				configuration.getAttribute(RConsoleOptionsTab.ATTR_INTEGRATION_RDBGEXT_ENABLED, true),
				mode.equals(ILaunchManager.DEBUG_MODE) ));
		if (isStartup) {
			RConsoleLaunching.scheduleStartupSnippet(controller, configuration);
		}
	}
	
	
	private ILaunchDelegateAddon addon;
	
	
	public RConsoleRJLaunchDelegate() {
	}
	
	public RConsoleRJLaunchDelegate(final ILaunchDelegateAddon addon) {
		this.addon= addon;
	}
	
	
	@Override
	public void launch(final ILaunchConfiguration configuration, final String mode, 
			final ILaunch launch, final IProgressMonitor monitor) throws CoreException {
		final SubMonitor m= LaunchUtils.initProgressMonitor(configuration, monitor, 25);
		final long timestamp= System.currentTimeMillis();
		
		final IWorkbenchPage page= UIAccess.getActiveWorkbenchPage(false);
		
		m.worked(1);
		if (m.isCanceled()) {
			return;
		}
		
		// load tracking configurations
		final List<TrackingConfiguration> trackingConfigs;
		{	final List<String> trackingIds= configuration.getAttribute(RConsoleOptionsTab.TRACKING_ENABLED_IDS, Collections.EMPTY_LIST);
			trackingConfigs= new ArrayList<>(trackingIds.size());
			for (final String id : trackingIds) {
				final TrackingConfiguration trackingConfig;
				if (id.equals(HistoryTrackingConfiguration.HISTORY_TRACKING_ID)) {
					trackingConfig= new HistoryTrackingConfiguration(id);
				}
				else {
					trackingConfig= new TrackingConfiguration(id);
				}
				RConsoleOptionsTab.TRACKING_UTIL.load(trackingConfig, configuration);
				trackingConfigs.add(trackingConfig);
			}
		}
		
		m.worked(1);
		if (m.isCanceled()) {
			return;
		}
		
		// r env
		final IREnvConfiguration rEnv= RLaunching.getREnvConfig(configuration, true);
		
		final RMIRegistry registry;
		boolean requireCodebase;
		{	final String s= System.getProperty("org.eclipse.statet.r.console.rmiRegistryPort");
			int port= -1;
			if (s != null && s.length() > 0) {
				try {
					m.subTask(Messages.LaunchDelegate_CheckingRegistry_subtask);
					port= Integer.parseInt(s);
					final RMIAddress registryAddress= new RMIAddress(InetAddress.getLoopbackAddress(), port, null);
					registry= new RMIRegistry(registryAddress, true);
					requireCodebase= true;
				}
				catch (final NumberFormatException e) {
					throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
							"The registry port specified by 'org.eclipse.statet.r.console.rmiRegistryPort' is invalid.", e ));
				}
				catch (final MalformedURLException e) {
					throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
							"The registry port specified by 'org.eclipse.statet.r.console.rmiRegistryPort' is invalid.", e ));
				}
				catch (final RemoteException e) {
					throw new CoreException(new Status(IStatus.ERROR, RConsoleUIPlugin.BUNDLE_ID, 0,
							"Connection setup to the registry specified by 'org.eclipse.statet.r.console.rmiRegistryPort' failed.", e ));
				}
			}
			else {
				try {
					registry= RMIRegistryManager.INSTANCE.getEmbeddedPrivateRegistry(
							StatusUtils.convertChild(m.newChild(1)) );
				}
				catch (final StatusException e) {
					throw StatusUtils.convert(e);
				}
				requireCodebase= false;
			}
		}
		
		m.worked(1);
		if (m.isCanceled()) {
			return;
		}
		
		// start server
		m.subTask(Messages.LaunchDelegate_StartREngine_subtask);
		try {
			final RMIAddress rmiAddress= new RMIAddress(InetAddress.getLoopbackAddress(), registry.getAddress().getPort(),
					"rjs-local-" + System.currentTimeMillis() ); //$NON-NLS-1$
			final RJEngineLaunchDelegate engineLaunchDelegate= new RJEngineLaunchDelegate(
					rmiAddress.getAddress(), requireCodebase, rEnv);
			
			RjsComConfig.setRMIClientSocketFactory(null);
			
			engineLaunchDelegate.launch(configuration, mode, launch, m.newChild(10));
			final IProcess[] processes= launch.getProcesses();
			if (processes.length == 0) {
				return;
			}
			
			m.worked(1);
			if (m.isCanceled()) {
				return;
			}
			
			// arguments
			final String[] rArgs= LaunchUtils.getProcessArguments(configuration, RConsoleLaunching.ATTR_OPTIONS);
			
			m.worked(1);
			if (m.isCanceled()) {
				return;
			}
			
			// create process
			UnterminatedLaunchAlerter.registerLaunchType(RConsoleLaunching.R_CONSOLE_CONFIGURATION_TYPE_ID);
			
			final RProcess process= new RProcess(launch, rEnv,
					LaunchUtils.createLaunchPrefix(configuration),
					rEnv.getName() + " / RJ " + LaunchUtils.createProcessTimestamp(timestamp), //$NON-NLS-1$
					rmiAddress.toString(),
					null, // wd is set at rjs startup
					timestamp );
			process.setAttribute(IProcess.ATTR_CMDLINE, rmiAddress.toString() + '\n' + Arrays.toString(rArgs));
			
			// Wait until the engine is started or died
			m.subTask(Messages.LaunchDelegate_WaitForR_subtask);
			final long t= System.nanoTime();
			WAIT: for (int i= 0; true; i++) {
				if (processes[0].isTerminated()) {
					final boolean silent= configuration.getAttribute(IDebugUIConstants.ATTR_CAPTURE_IN_CONSOLE, true);
					final IStatus logStatus= ToolRunner.createOutputLogStatus(
							processes[0].getAdapter(ILogOutput.class) );
					// move to R server?
					final StringBuilder sb= new StringBuilder();
					sb.append("Launching the R Console was cancelled, because it seems starting the R engine failed.");
					sb.append(engineLaunchDelegate.getDebugInfo());
					
					StatusManager.getManager().handle(new Status(silent ? IStatus.INFO : IStatus.ERROR,
							RConsoleUIPlugin.BUNDLE_ID, sb.toString(),
							(logStatus != null) ? new CoreException(logStatus) : null ),
							silent ? (StatusManager.LOG) : (StatusManager.LOG | StatusManager.SHOW) );
					return;
				}
				if (m.isCanceled()) {
					processes[0].terminate();
					throw new CoreException(Status.CANCEL_STATUS);
				}
				try {
					final String[] list= registry.getRegistry().list();
					for (final String entry : list) {
						if (entry.equals(rmiAddress.getName())) {
							break WAIT;
						}
					}
					if (i > 1 && System.nanoTime() - t > TIMEOUT) {
						break WAIT;
					}
				}
				catch (final RemoteException e) {
					if (i > 0 && System.nanoTime() - t > TIMEOUT / 3) {
						break WAIT;
					}
				}
				try {
					Thread.sleep(333);
				}
				catch (final InterruptedException e) {
					// continue, monitor and process is checked
				}
			}
			m.worked(5);
			
			final RjsConnection connection= RjsController.lookup(registry.getRegistry(), null, rmiAddress);
			
			final HashMap<String, Object> rjsProperties= new HashMap<>();
			rjsProperties.put(RjsComConfig.RJ_DATA_STRUCTS_LISTS_MAX_LENGTH_PROPERTY_ID,
					configuration.getAttribute(RConsoleLaunching.ATTR_OBJECTDB_LISTS_MAX_LENGTH, 10000));
			rjsProperties.put(RjsComConfig.RJ_DATA_STRUCTS_ENVS_MAX_LENGTH_PROPERTY_ID,
					configuration.getAttribute(RConsoleLaunching.ATTR_OBJECTDB_ENVS_MAX_LENGTH, 10000));
			rjsProperties.put("rj.session.startup.time", timestamp); //$NON-NLS-1$
			final RjsController controller= new RjsController(process, rmiAddress, connection, null,
					(RjsController.RJS_LOCAL | RjsController.RJS_SETUP_CONSOLE), rArgs, rjsProperties,
					engineLaunchDelegate.getWorkingDirectory(),
					createWorkspaceConfig(configuration), trackingConfigs);
			process.init(controller);
			RConsoleLaunching.registerDefaultHandlerTo(controller);
			
			m.worked(5);
			
			initConsoleOptions(controller, rEnv, configuration, mode, true);
			
			if (this.addon != null) {
				this.addon.init(configuration, mode, controller, m);
			}
			
			final RConsole console= new RConsole(process, new NIConsoleColorAdapter());
			NicoUITools.startConsoleLazy(console, page, 
					configuration.getAttribute(RConsoleLaunching.ATTR_PIN_CONSOLE, false));
			
			new ToolRunner().runInBackgroundThread(process, new WorkbenchStatusHandler());
		}
		finally {
			RjsComConfig.clearRMIClientSocketFactory();
		}
		
		m.done();
	}
	
}
