/*=============================================================================#
 # Copyright (c) 2009, 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.rj.servi.node;

import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.status.Status;
import org.eclipse.statet.jcommons.status.StatusException;

import org.eclipse.statet.internal.rj.servi.Utils;
import org.eclipse.statet.rj.renv.core.DefaultLocalConfigurator;
import org.eclipse.statet.rj.renv.core.REnvConfiguration;


/**
 * Configuration for an R node.
 */
@NonNullByDefault
public class RServiNodeConfig implements PropertiesBean {
	
	
	public static final String BEAN_ID= "rconfig";
	
	public static final String R_HOME_ID= "r_home.path";
	
	public static final String R_ARCH_ID= "r_arch.code";
	
	public static final String JAVA_HOME_ID= "java_home.path";
	
	public static final String JAVA_ARGS_ID= "java_cmd.args";
	private static final String JAVA_ARGS_OLD_ID= "java_args.path";
	
	public static final String NODE_ENVIRONMENT_VARIABLES_PREFIX= "node_environment.variables.";
	public static final String NODE_ARGS_ID= "node_cmd.args";
	
	public static final String BASE_WD_ID= "base_wd.path";
	
	/**
	 * Property id for R startup snippet
	 * 
	 * @see #setRStartupSnippet(String)
	 * @since 0.5
	 */
	public static final String R_STARTUP_SNIPPET_ID= "r_startup.snippet";
	
	public static final String CONSOLE_ENABLED_ID= "debug_console.enabled";
	
	public static final String VERBOSE_ENABLED_ID= "debug_verbose.enabled";
	
	/**
	 * Property id for timeout of start/stop of nodes
	 * 
	 * @see #setStartStopTimeout(long)
	 * @since 2.0
	 */
	public static final String STARTSTOP_TIMEOUT__ID= "startstop_timeout.millis";
	
	private static final long STARTSTOP_TIMEOUT_DEFAULT= 30 * 1000;
	
	
	private @Nullable String rHome;
	private @Nullable String rArch;
	
	private @Nullable String javaHome;
	private String javaArgs;
	
	private final Map<String, String> environmentVariables= new HashMap<>();
	private String nodeArgs;
	
	private @Nullable String baseWd;
	
	private String rStartupSnippet;
	
	private boolean enableConsole;
	private boolean enableVerbose;
	
	private long startStopTimeout;
	
	
	public RServiNodeConfig() {
		this.rHome= System.getenv("R_HOME");
		this.rArch= System.getenv("R_ARCH");
		this.javaArgs= "-server";
		this.nodeArgs= "";
		this.rStartupSnippet= "";
		this.startStopTimeout= STARTSTOP_TIMEOUT_DEFAULT;
	}
	
	public RServiNodeConfig(final RServiNodeConfig config) {
		this();
		synchronized (config) {
			load(config);
		}
	}
	
	
	@Override
	public String getBeanId() {
		return BEAN_ID;
	}
	
	public synchronized void load(final RServiNodeConfig templ) {
		this.rHome= templ.rHome;
		this.rArch= templ.rArch;
		this.javaHome= templ.javaHome;
		this.javaArgs= templ.javaArgs;
		this.environmentVariables.clear();
		this.environmentVariables.putAll(templ.environmentVariables);
		this.nodeArgs= templ.nodeArgs;
		this.baseWd= templ.baseWd;
		this.rStartupSnippet= templ.rStartupSnippet;
		this.enableConsole= templ.enableConsole;
		this.enableVerbose= templ.enableVerbose;
		this.startStopTimeout= templ.startStopTimeout;
	}
	
	public synchronized void load(final REnvConfiguration config) throws StatusException {
		{	final Status status= config.getValidationStatus();
			if (status.getSeverity() >= Status.ERROR) {
				throw new StatusException(status);
			}
		}
		
		final DefaultLocalConfigurator configurator= new DefaultLocalConfigurator(config);
		
		setRHome(config.getRHomeDirectoryPath().toString());
		setRArch(configurator.getRArch());
		this.environmentVariables.clear();
		this.environmentVariables.putAll(configurator.getEnvironmentsVariables(0));
	}
	
	@Override
	public synchronized void load(final Properties map) {
		setRHome(map.getProperty(R_HOME_ID));
		setRArch(map.getProperty(R_ARCH_ID));
		setJavaHome(map.getProperty(JAVA_HOME_ID));
		setJavaArgs(map.getProperty(JAVA_ARGS_ID));
		if (this.javaArgs.length() == 0) {
			setJavaArgs(map.getProperty(JAVA_ARGS_OLD_ID));
		}
		this.environmentVariables.clear();
		final int prefixLength= NODE_ENVIRONMENT_VARIABLES_PREFIX.length();
		for (final Entry<Object, Object> p : map.entrySet()) {
			final String name= (String) p.getKey();
			if (name != null && name.length() > prefixLength
					&& name.startsWith(NODE_ENVIRONMENT_VARIABLES_PREFIX)
					&& p.getValue() instanceof String) {
				this.environmentVariables.put(name.substring(prefixLength), (String) p.getValue());
			}
		}
		setNodeArgs(map.getProperty(NODE_ARGS_ID));
		setBaseWorkingDirectory(map.getProperty(BASE_WD_ID));
		setRStartupSnippet(map.getProperty(R_STARTUP_SNIPPET_ID));
		setEnableConsole(Boolean.parseBoolean(map.getProperty(CONSOLE_ENABLED_ID)));
		setEnableVerbose(Boolean.parseBoolean(map.getProperty(VERBOSE_ENABLED_ID)));
		{	final String s= map.getProperty(STARTSTOP_TIMEOUT__ID);
			this.startStopTimeout= ((s != null) ? Long.parseLong(s) : STARTSTOP_TIMEOUT_DEFAULT);
		}
	}
	
	@Override
	public synchronized void save(final Properties map) {
		Utils.setProperty(map, R_HOME_ID, this.rHome);
		Utils.setProperty(map, R_ARCH_ID, this.rArch);
		Utils.setProperty(map, JAVA_HOME_ID, this.javaHome);
		Utils.setProperty(map, JAVA_ARGS_ID, this.javaArgs);
		for (final Entry<String, String> variable : this.environmentVariables.entrySet()) {
			map.setProperty(NODE_ENVIRONMENT_VARIABLES_PREFIX + variable.getKey(), variable.getValue());
		}
		Utils.setProperty(map, NODE_ARGS_ID, this.nodeArgs);
		Utils.setProperty(map, BASE_WD_ID, this.baseWd);
		Utils.setProperty(map, R_STARTUP_SNIPPET_ID, this.rStartupSnippet);
		Utils.setProperty(map, CONSOLE_ENABLED_ID, Boolean.toString(this.enableConsole));
		Utils.setProperty(map, VERBOSE_ENABLED_ID, Boolean.toString(this.enableVerbose));
		Utils.setProperty(map, STARTSTOP_TIMEOUT__ID, Long.toString(this.startStopTimeout));
	}
	
	public synchronized void setRHome(final @Nullable String path) {
		this.rHome= path;
	}
	
	public synchronized @Nullable String getRHome() {
		return this.rHome;
	}
	
	public synchronized void setRArch(final @Nullable String code) {
		this.rArch= code;
	}
	
	public synchronized @Nullable String getRArch() {
		return this.rArch;
	}
	
	public synchronized @Nullable String getJavaHome() {
		return this.javaHome;
	}
	
	public synchronized void setJavaHome(final @Nullable String javaHome) {
		this.javaHome= (javaHome != null && javaHome.trim().length() > 0) ? javaHome : null;
	}
	
	public synchronized String getJavaArgs() {
		return this.javaArgs;
	}
	
	public synchronized void setJavaArgs(final @Nullable String args) {
		this.javaArgs= (args != null) ? args : "";
	}
	
	/**
	 * Additional environment variables for the R process.
	 * 
	 * @return a name - value map of the environment variables
	 */
	public synchronized Map<String, String> getEnvironmentVariables() {
		return this.environmentVariables;
	}
	
	public synchronized void addToClasspath(final String entry) {
		String cp= this.environmentVariables.get("CLASSPATH");
		if (cp != null) {
			cp+= File.pathSeparatorChar + entry;
		}
		else {
			cp= entry;
		}
		this.environmentVariables.put("CLASSPATH", cp);
	}
	
	public synchronized String getNodeArgs() {
		return this.nodeArgs;
	}
	
	public synchronized void setNodeArgs(final @Nullable String args) {
		this.nodeArgs= (args != null) ? args : "";
	}
	
	public synchronized void setBaseWorkingDirectory(final @Nullable String path) {
		this.baseWd= (path != null && path.trim().length() > 0) ? path : null;
	}
	
	public synchronized @Nullable String getBaseWorkingDirectory() {
		return this.baseWd;
	}
	
	/**
	 * Returns the R code snippet to run at startup of a node.
	 * 
	 * @return the code
	 * 
	 * @see #setRStartupSnippet(String)
	 * @since 0.5
	 */
	public synchronized String getRStartupSnippet() {
		return this.rStartupSnippet;
	}
	
	/**
	 * Sets the R code snippet to run at startup of a node.
	 * <p>
	 * Typical use case is to load required R packages. The default is an empty snippet.
	 * If the execution of the code throws an error, the startup of the node is canceled.</p>
	 * 
	 * @param code the R code to run
	 * 
	 * @since 0.5
	 */
	public synchronized void setRStartupSnippet(final @Nullable String code) {
		this.rStartupSnippet= (code != null) ? code : "";
	}
	
	public synchronized boolean getEnableConsole() {
		return this.enableConsole;
	}
	
	public synchronized void setEnableConsole(final boolean enable) {
		this.enableConsole= enable;
	}
	
	public synchronized boolean getEnableVerbose() {
		return this.enableVerbose;
	}
	
	public synchronized void setEnableVerbose(final boolean enable) {
		this.enableVerbose= enable;
	}
	
	/**
	 * Returns the timeout of start/stop of nodes
	 * 
	 * @return the timeout in milliseconds
	 * 
	 * @since 2.0
	 */
	public long getStartStopTimeout() {
		return this.startStopTimeout;
	}
	
	/**
	 * Sets the timeout of start/stop of nodes
	 * 
	 * @param milliseconds the timeout in milliseconds
	 * 
	 * @since 2.0
	 */
	public void setStartStopTimeout(final long milliseconds) {
		this.startStopTimeout= milliseconds;
	}
	
	
	@Override
	public synchronized boolean validate(final @Nullable Collection<ValidationMessage> messages) {
		boolean valid= true;
		
		if (this.rHome != null && !new File(this.rHome).exists()) {
			if (messages != null) {
				messages.add(new ValidationMessage(R_HOME_ID, "The directory does not exist."));
			}
			valid= false;
		}
		if (this.javaHome != null && !new File(this.javaHome).exists()) {
			if (messages != null) {
				messages.add(new ValidationMessage(JAVA_HOME_ID, "The directory does not exist."));
			}
			valid= false;
		}
		if (this.baseWd != null && !new File(this.baseWd).exists()) {
			if (messages != null) {
				messages.add(new ValidationMessage(BASE_WD_ID, "The directory does not exist."));
			}
			valid= false;
		}
		
		if (this.startStopTimeout != -1 && this.startStopTimeout < 0) {
			if (messages != null) {
				messages.add(new ValidationMessage(STARTSTOP_TIMEOUT__ID, "Value must be > 0 or -1 (infinite)."));
			}
			valid= false;
		}
		
		return valid;
	}
	
}
