/*=============================================================================#
 # Copyright (c) 2008, 2019 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.server.srv;

import java.io.StreamCorruptedException;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.AlreadyBoundException;
import java.rmi.NoSuchObjectException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.UnmarshalException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
import java.security.Policy;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.LogRecord;

import org.eclipse.statet.jcommons.rmi.RMIAddress;
import org.eclipse.statet.jcommons.rmi.RMIRegistry;

import org.eclipse.statet.rj.RjException;
import org.eclipse.statet.rj.RjInvalidConfigurationException;
import org.eclipse.statet.rj.server.RjsComConfig;
import org.eclipse.statet.rj.server.Server;
import org.eclipse.statet.rj.server.srv.engine.SrvEngineServer;
import org.eclipse.statet.rj.server.srvext.ServerAuthMethod;
import org.eclipse.statet.rj.server.srvext.ServerRuntimePlugin;
import org.eclipse.statet.rj.server.util.ServerUtils;
import org.eclipse.statet.rj.server.util.ServerUtils.ArgKeyValue;


public class RMIServerControl extends ServerControl {
	
	
	public static final int EXIT_REGISTRY_PROBLEM= 150;
	public static final int EXIT_REGISTRY_INVALID_ADDRESS= 151;
	public static final int EXIT_REGISTRY_CONNECTING_ERROR= 151;
	public static final int EXIT_REGISTRY_SERVER_STILL_ACTIVE= 152;
	public static final int EXIT_REGISTRY_ALREADY_BOUND= 153;
	public static final int EXIT_REGISTRY_CLEAN_FAILED= 155;
	public static final int EXIT_REGISTRY_BIND_FAILED= 156;
	public static final int EXIT_START_RENGINE_ERROR= 161;
	
	
	protected final String logPrefix;
	
	private final RMIAddress rmiAddress;
	
	private final RMIClientSocketFactory rmiCsf;
	private final RMIServerSocketFactory rmiSsf;
	
	private Server mainServer;
	private boolean isPublished;
	
	
	public RMIServerControl(final String name, final Map<String, String> options) {
		super(options);
		final int lastSegment= name.lastIndexOf('/');
		this.logPrefix= "[Control:"+((lastSegment >= 0) ? name.substring(lastSegment+1) : name)+"]";
		
		{	RMIAddress address= null;
			Exception error= null;
			try {
				address= new RMIAddress(name);
			}
			catch (final MalformedURLException e) {
				error= e;
			}
			catch (final UnknownHostException e) {
				error= e;
			}
			if (address == null) {
				final LogRecord record= new LogRecord(Level.SEVERE,
						"{0} the server address ''{1}'' is invalid.");
				record.setParameters(new Object[] { this.logPrefix, name });
				record.setThrown(error);
				LOGGER.log(record);
				
				exit(EXIT_REGISTRY_INVALID_ADDRESS);
			}
			this.rmiAddress= address;
		}
		
		if (options != null) {
			if (options.containsKey("verbose")) {
				initVerbose();
			}
		}
		
		this.rmiCsf= RjsComConfig.getRMIServerClientSocketFactory(
				this.rmiAddress.isSsl() );
		this.rmiSsf= RjsComConfig.getRMIServerServerSocketFactory(
				this.rmiAddress.isSsl() );
	}
	
	
	public RMIClientSocketFactory getRmiClientSocketFactory() {
		return this.rmiCsf;
	}
	
	public RMIServerSocketFactory getRmiServerSocketFactory() {
		return this.rmiSsf;
	}
	
	
	public SrvEngineServer initServer() {
		LOGGER.log(Level.INFO, "{0} Initializing R engine server...", this.logPrefix);
		try {
			final String serverType= getOptions().get("server"); //$NON-NLS-1$
			if (serverType == null) {
				final ServerAuthMethod auth= createServerAuth(getOptions().remove("auth")); //$NON-NLS-1$
				return new SrvEngineServer(this, auth);
			}
			else {
				final Class<SrvEngineServer> serverClass= (Class<SrvEngineServer>) Class.forName(serverType);
				final Constructor<SrvEngineServer> constructor= serverClass.getConstructor(RMIServerControl.class);
				return constructor.newInstance(this);
			}
		}
		catch (final Exception e) {
			final LogRecord record= new LogRecord(Level.SEVERE,
					"{0} Failed to initialize R engine server.");
			record.setParameters(new Object[] { this.logPrefix });
			record.setThrown(e);
			LOGGER.log(record);
			
			exit(EXIT_INIT_RENGINE_ERROR);
			throw new RuntimeException();
		}
	}
	
	protected RMIRegistry getRmiRegistry() throws RemoteException {
		return new RMIRegistry(this.rmiAddress.getRegistryAddress(), false);
	}
	
	public String getName() {
		return this.rmiAddress.getName();
	}
	
	public Remote exportObject(final Remote obj) throws RemoteException {
		return UnicastRemoteObject.exportObject(obj, 0, this.rmiCsf, this.rmiSsf);
	}
	
	
	protected void publishServer(final SrvEngineServer server) {
		try {
			{	final Policy policy= Policy.getPolicy();// load security file first!
				System.setSecurityManager(new SecurityManager());
			}
			final RMIRegistry rmiRegistry= getRmiRegistry();
			Server stub= (Server) exportObject(server);
			this.mainServer= server;
			try {
				rmiRegistry.getRegistry().bind(getName(), stub);
			}
			catch (final AlreadyBoundException boundException) {
				if (server.getConfigUnbindOnStartup() && unbindDead() == 0) {
					rmiRegistry.getRegistry().bind(getName(), stub);
				}
				else {
					throw boundException;
				}
			}
			catch (final RemoteException remoteException) {
				if (!this.rmiAddress.isSsl()
						&& remoteException.getCause() instanceof UnmarshalException
						&& remoteException.getCause().getCause() instanceof StreamCorruptedException
						&& RjsComConfig.getRMIServerClientSocketFactory(false) != null) {
					stub= null;
					try {
						UnicastRemoteObject.unexportObject(server, true);
						stub= (Server) UnicastRemoteObject.exportObject(server, 0,
								null, RjsComConfig.getRMIServerServerSocketFactory(false) );
					}
					catch (final Exception testException) {}
					if (stub != null) {
						final LogRecord record= new LogRecord(Level.SEVERE,
								"{0} caught StreamCorruptedException \nretrying without socket factory to reveal other potential problems.");
						record.setParameters(new Object[] { this.logPrefix });
						record.setThrown(remoteException);
						LOGGER.log(record);
						rmiRegistry.getRegistry().bind(getName(), stub);
						rmiRegistry.getRegistry().unbind(getName());
						throw new RjException("No error without socket factory, use the Java property 'org.eclipse.statet.rj.rmi.disableSocketFactory' to disable the factory.");
					}
				}
				throw remoteException;
			}
			Runtime.getRuntime().addShutdownHook(new Thread() {
				@Override
				public void run() {
					checkCleanup();
				}
			});
			this.isPublished= true;
			LOGGER.log(Level.INFO, "{0} server is added to registry - ready.", this.logPrefix);
			
			return;
		}
		catch (final Exception e) {
			final LogRecord record= new LogRecord(Level.SEVERE,
					"{0} init server failed.");
			record.setParameters(new Object[] { this.logPrefix });
			record.setThrown(e);
			LOGGER.log(record);
			
			if (e instanceof AlreadyBoundException) {
				exit(EXIT_REGISTRY_ALREADY_BOUND);
			}
			
			checkCleanup();
			exit(EXIT_REGISTRY_BIND_FAILED);
		}
	}
	
	/**
	 * @return <code>true</code> if it was removed, otherwise <code>false</code>
	 */
	protected int unbindDead() {
		Remote remote;
		try {
			final RMIRegistry registry= getRmiRegistry();
			remote= registry.getRegistry().lookup(getName());
		}
		catch (final NotBoundException lookupException) {
			return 0;
		}
		catch (final RemoteException lookupException) {
			return EXIT_REGISTRY_CONNECTING_ERROR;
		}
		if (!(remote instanceof Server)) {
			return 2;
		}
		try {
			((Server) remote).getInfo();
			return EXIT_REGISTRY_SERVER_STILL_ACTIVE;
		}
		catch (final RemoteException deadException) {
			try {
				final RMIRegistry rmiRegistry= getRmiRegistry();
				rmiRegistry.getRegistry().unbind(getName());
				LOGGER.log(Level.INFO,
						"{0} dead server removed from registry.",
						this.logPrefix);
				return 0;
			}
			catch (final Exception unbindException) {
				return EXIT_REGISTRY_CLEAN_FAILED;
			}
		}
	}
	
	public void checkCleanup() {
		if (this.mainServer == null) {
			return;
		}
		LOGGER.log(Level.INFO, "{0} cleaning up server resources...", this.logPrefix);
		try {
			final RMIRegistry rmiRegistry= getRmiRegistry();
			rmiRegistry.getRegistry().unbind(getName());
		}
		catch (final NotBoundException e) {
			// ok
		}
		catch (final Exception e) {
			final LogRecord record= new LogRecord(this.isPublished ? Level.SEVERE : Level.INFO,
					"{0} cleaning up server resources failed.");
			record.setParameters(new Object[] { this.logPrefix });
			record.setThrown(e);
			LOGGER.log(record);
		}
		try {
			UnicastRemoteObject.unexportObject(this.mainServer, true);
		}
		catch (final NoSuchObjectException e) {
			// ok
		}
		this.mainServer= null;
		System.gc();
	}
	
	public ServerAuthMethod createServerAuth(final String config) throws RjException {
		// auth
		final String authType;
		final String authConfig;
		try {
			final ArgKeyValue auth= ServerUtils.getArgSubValue(config);
			switch (auth.getKey()) {
			case "": //$NON-NLS-1$
				throw new RjInvalidConfigurationException("Missing 'auth' configuration");
			case "none": //$NON-NLS-1$
				authType= "org.eclipse.statet.rj.server.srvext.auth.NoAuthMethod";
				break;
			case "name-pass": //$NON-NLS-1$
				authType= "org.eclipse.statet.rj.server.srvext.auth.SimpleNamePassAuthMethod";
				break;
			case "fx": //$NON-NLS-1$
				authType= "org.eclipse.statet.rj.server.srvext.auth.FxAuthMethod";
				break;
			case "local-shaj": //$NON-NLS-1$
				authType= "org.eclipse.statet.rj.server.srvext.auth.LocalShajAuthMethod";
				break;
			default:
				authType= auth.getKey();
				break;
			}
			authConfig= auth.getValue();
		}
		catch (final Exception e) {
			final LogRecord record= new LogRecord(Level.SEVERE,
					"{0} init authentication method failed.");
			record.setParameters(new Object[] { this.logPrefix });
			record.setThrown(e);
			LOGGER.log(record);
			throw new RjInvalidConfigurationException("Init authentication method failed.", e);
		}
		try {
			final Class<ServerAuthMethod> authClazz= (Class<ServerAuthMethod>) Class.forName(authType);
			final ServerAuthMethod authMethod= authClazz.newInstance();
			authMethod.init(authConfig);
			return authMethod;
		}
		catch (final Exception e) {
			final LogRecord record= new LogRecord(Level.SEVERE,
					"{0} init authentication method ''{1}'' failed.");
			record.setParameters(new Object[] { this.logPrefix, authType });
			record.setThrown(e);
			LOGGER.log(record);
			throw new RjException(String.format("Init authentication method failed '%1$s'.", authType),
					e );
		}
	}
	
	
	public void start(final SrvEngineServer server) {
		try {
			server.start(new ServerRuntimePlugin() {
				
				@Override
				public String getSymbolicName() {
					return "rmi";
				}
				
				@Override
				public void rjIdle() throws Exception {
				}
				
				@Override
				public void rjStop(final int state) throws Exception {
					if (state == 0) {
						try {
							Thread.sleep(1000);
						}
						catch (final InterruptedException e) {
						}
					}
					checkCleanup();
				}
				
			});
		}
		catch (final Exception e) {
			final LogRecord record= new LogRecord(Level.SEVERE,
					"{0} starting R engine server failed.");
			record.setParameters(new Object[] { this.logPrefix });
			record.setThrown(e);
			LOGGER.log(record);
			
			exit(EXIT_INIT_RENGINE_ERROR | 8);
		}
		
		publishServer(server);
	}
	
	public void clean() {
		final int dead= unbindDead();
		if (dead == 0) {
			exit(0);
			return;
		}
		if (dead == EXIT_REGISTRY_SERVER_STILL_ACTIVE && !getOptions().containsKey("force")) {
			exit(EXIT_REGISTRY_SERVER_STILL_ACTIVE);
		}
		try {
			final RMIRegistry rmiRegistry= getRmiRegistry();
			rmiRegistry.getRegistry().unbind(getName());
			LOGGER.log(Level.INFO,
					"{0} server removed from registry.",
					this.logPrefix);
		}
		catch (final NotBoundException e) {
			exit(0);
		}
		catch (final RemoteException e) {
			final LogRecord record= new LogRecord(Level.SEVERE,
					"{0} removing server from registry failed.");
			record.setParameters(new Object[] { this.logPrefix });
			record.setThrown(e);
			LOGGER.log(record);
			
			exit(EXIT_REGISTRY_CONNECTING_ERROR);
		}
	}
	
}
