/*=============================================================================#
 # Copyright (c) 2009, 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.r.nico.impl;

import static org.eclipse.statet.nico.core.runtime.IToolEventHandler.LOGIN_SSH_HOST_DATA_KEY;
import static org.eclipse.statet.nico.core.runtime.IToolEventHandler.LOGIN_SSH_PORT_DATA_KEY;
import static org.eclipse.statet.nico.core.runtime.IToolEventHandler.LOGIN_USERNAME_DATA_KEY;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketImpl;
import java.net.SocketOptions;
import java.rmi.RemoteException;
import java.rmi.server.RMIClientSocketFactory;
import java.security.SecureRandom;
import java.util.Hashtable;
import java.util.Map;

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 com.jcraft.jsch.ChannelDirectTCPIP;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

import org.eclipse.statet.jcommons.status.ErrorStatus;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.jcommons.status.Statuses;

import org.eclipse.statet.ecommons.net.ssh.core.ISshSessionService;
import org.eclipse.statet.ecommons.runtime.core.util.StatusUtils;

import org.eclipse.statet.base.core.StatetCore;
import org.eclipse.statet.internal.r.console.core.RConsoleCorePlugin;
import org.eclipse.statet.rj.server.FxCallback;


public class RjsUtil {
	
	
	public static Session getSession(final Map<String, Object> loginData, final IProgressMonitor monitor) throws CoreException {
		final String username = (String) loginData.get(LOGIN_USERNAME_DATA_KEY);
		final String sshHost = (String) loginData.get(LOGIN_SSH_HOST_DATA_KEY);
		final Integer sshPort = (Integer) loginData.get(LOGIN_SSH_PORT_DATA_KEY);
		
		return StatetCore.getSshSessionManager().getSshSession(
				username, sshHost, (sshPort != null) ? sshPort.intValue() : ISshSessionService.SSH_DEFAULT_PORT,
				monitor );
	}
	
	public static Session getSession(final Map<String, Object> loginData, final ProgressMonitor m) throws StatusException {
		final String username = (String) loginData.get(LOGIN_USERNAME_DATA_KEY);
		final String sshHost = (String) loginData.get(LOGIN_SSH_HOST_DATA_KEY);
		final Integer sshPort = (Integer) loginData.get(LOGIN_SSH_PORT_DATA_KEY);
		
		try {
			return StatetCore.getSshSessionManager().getSshSession(
					username, sshHost, (sshPort != null) ? sshPort.intValue() : ISshSessionService.SSH_DEFAULT_PORT,
					StatusUtils.convert(m) );
		}
		catch (final CoreException e) {
			throw StatusUtils.convert(e);
		}
	}
	
	
	private static class RMIOverSshClientSocket extends Socket {
		
		public RMIOverSshClientSocket(final ChannelDirectTCPIP channel) throws SocketException, IOException {
			super(new RMIOverSshClientSocketImpl(channel));
		}
		
	}
	
	private static class RMIOverSshClientSocketImpl extends SocketImpl {
		
		private static class ChannelInputStream extends PipedInputStream {
			
			public ChannelInputStream() {
				super();
				this.buffer = new byte[32*1024];
			}
			
			public int getBufferSize() {
				return this.buffer.length;
			}
			
		}
		
		
		private final ChannelDirectTCPIP fChannel;
		
		private final ChannelInputStream fInputStream;
		private final OutputStream fOutputStream;
		
		
		public RMIOverSshClientSocketImpl(final ChannelDirectTCPIP channel) throws IOException {
			fChannel = channel;
			fInputStream = new ChannelInputStream();
			channel.setOutputStream(new PipedOutputStream(fInputStream));
			fOutputStream = channel.getOutputStream();
			
			localport = 0;
		}
		
		
		@Override
		protected void create(final boolean stream) throws IOException {
			if (!stream) {
				throw new IOException("Not supported");
			}
		}
		
		@Override
		protected void connect(final String host, final int port) throws IOException {
			connect(InetSocketAddress.createUnresolved(host, port), 0);
		}
		@Override
		protected void connect(final InetAddress address, final int port) throws IOException {
			connect(new InetSocketAddress(address, port), 0);
		}
		@Override
		protected void connect(final SocketAddress address, final int timeout) throws IOException {
			final InetSocketAddress inetAddress = ((InetSocketAddress) address);
			if (this.localport != 0) {
				throw new IOException("Not supported: reconnect to " + address.toString());
			}
			this.address = inetAddress.getAddress();
			this.port = inetAddress.getPort();
			this.localport = -1;
		}
		
		@Override
		protected void bind(final InetAddress host, final int port) throws IOException {
			throw new IOException("Not supported");
		}
		
		@Override
		protected void listen(final int backlog) throws IOException {
			throw new IOException("Not supported");
		}
		
		@Override
		protected void accept(final SocketImpl s) throws IOException {
			throw new IOException("Not supported");
		}
		
		@Override
		public InputStream getInputStream() throws IOException {
			return fInputStream;
		}
		
		@Override
		public OutputStream getOutputStream() throws IOException {
			return fOutputStream;
		}
		
		@Override
		protected int available() throws IOException {
			return fInputStream.available();
		}
		
		@Override
		protected void close() throws IOException {
			localport = -1;
			fChannel.disconnect();
		}
		
		@Override
		protected void shutdownInput() throws IOException {
			fInputStream.close();
		}
		
		@Override
		protected void shutdownOutput() throws IOException {
			fOutputStream.close();
		}
		
		@Override
		protected void sendUrgentData(final int data) throws IOException {
			throw new IOException("Not supported");
		}
		
		@Override
		public void setOption(final int optID, final Object value) throws SocketException {
			switch (optID) {
			case SocketOptions.TCP_NODELAY:
				if (((Boolean) value).booleanValue() == true) {
					return;
				}
				break;
			case SocketOptions.SO_KEEPALIVE:
				if (((Boolean) value).booleanValue() == false) {
					return;
				}
				break;
			case SocketOptions.SO_TIMEOUT:
				return;
			case SocketOptions.SO_SNDBUF:
			case SocketOptions.SO_RCVBUF:
				return;
			default:
//				System.out.println("SshSocket setOption " + optID + "= " + value);
				break;
			}
			throw new SocketException("Not supported: option= " + optID + " with value= " + value);
		}
		
		@Override
		public Object getOption(final int optID) throws SocketException {
			switch (optID) {
			case SocketOptions.TCP_NODELAY:
				return Boolean.TRUE;
			case SocketOptions.SO_KEEPALIVE:
				return Boolean.FALSE;
			case SocketOptions.SO_TIMEOUT:
				return Integer.valueOf(0);
			case SocketOptions.SO_SNDBUF:
				return 1024;
			case SocketOptions.SO_RCVBUF:
				return fInputStream.getBufferSize();
			default:
//				System.out.println("SshSocket getOption " + optID);
				break;
			}
			throw new SocketException("Not supported: option= " + optID);
		}
		
	}
	
	public static RMIClientSocketFactory createRMIOverSshClientSocketFactory(final Session session) {
		return new RMIClientSocketFactory() {
			@Override
			public Socket createSocket(final String host, final int port) throws IOException {
//				System.out.println("SshSocket new: to= " + host + ":" + port);
				try {
					final ChannelDirectTCPIP tcpipChannel = (ChannelDirectTCPIP) session.openChannel("direct-tcpip");
					tcpipChannel.setHost(host);
					tcpipChannel.setPort(port);
					final Socket socket = new RMIOverSshClientSocket(tcpipChannel);
					socket.connect(InetSocketAddress.createUnresolved(host, port));
					tcpipChannel.connect();
					return socket;
				}
				catch (final JSchException e) {
					final IOException ioException = new IOException();
					ioException.initCause(e);
					throw ioException;
				}
			}
		};
	}
	
	public static void startRemoteServerOverSsh(final Session session, final String command, final Hashtable<String, String> envp,
			final IProgressMonitor monitor) throws CoreException {
		
		ChannelExec execChannel = null;
		int status = -11111111;
		Exception error = null;
		final ByteArrayOutputStream output = new ByteArrayOutputStream();
		try {
			execChannel = (ChannelExec) session.openChannel("exec"); //$NON-NLS-1$
			execChannel.setCommand(command);
			if (envp != null) {
				execChannel.setEnv(envp);
			}
			
			execChannel.setInputStream(null);
			execChannel.setOutputStream(output, false);
			execChannel.setErrStream(output, false);
			
			execChannel.connect();
			
			while (!execChannel.isClosed()) {
				if (monitor.isCanceled()) {
					execChannel.disconnect();
					throw new CoreException(Status.CANCEL_STATUS);
				}
				try {
					Thread.sleep(200);
				}
				catch (final InterruptedException e) {
					// continue directly, monitor is checked
				}
			}
			status = execChannel.getExitStatus();
		}
		catch (final JSchException e) {
			error = e;
			status = -11111114;
		}
		finally {
			if (execChannel != null) {
				execChannel.disconnect();
			}
		}
		if (status != 0 && error == null) {
			try {
				error = new RemoteException("Exit status: " + status + //$NON-NLS-1$
						"\nMessage:\n" + output.toString("UTF-8"));
			} catch (final UnsupportedEncodingException e) {}
		}
		if (error != null) {
			throw new CoreException(new Status(IStatus.ERROR, RConsoleCorePlugin.BUNDLE_ID,
					"Failed to start remote R server over SSH.", error ));
		}
	}
	
	public static void handleFxCallback(final Session session, final FxCallback callback,
			final ProgressMonitor m) throws StatusException {
		final byte[] clientKey = new byte[1024];
		new SecureRandom().nextBytes(clientKey);
		final String filename = callback.getFilename();
		final byte[] content = callback.createContent(clientKey);
		
		ChannelExec execChannel = null;
		int status = -11111111;
		Exception error = null;
		try {
			execChannel = (ChannelExec) session.openChannel("exec"); //$NON-NLS-1$
			execChannel.setCommand("cat >> " + filename); //$NON-NLS-1$
			
			final ByteArrayInputStream inputStream = new ByteArrayInputStream(content);
			execChannel.setInputStream(inputStream, false);
			execChannel.setOutputStream(null);
			execChannel.setErrStream(null);
			
			execChannel.connect();
			
			while (!execChannel.isClosed()) {
				if (m.isCanceled()) {
					execChannel.disconnect();
					throw new StatusException(Statuses.CANCEL_STATUS);
				}
				try {
					Thread.sleep(200);
				}
				catch (final InterruptedException e) {
					// continue directly, monitor is checked
				}
			}
			status = execChannel.getExitStatus();
		}
		catch (final JSchException e) {
			error = e;
			status = -11111114;
		}
		finally {
			if (execChannel != null) {
				execChannel.disconnect();
			}
		}
		if (status != 0 && error == null) {
			error = new RemoteException("Exit code: " + status); //$NON-NLS-1$
		}
		if (error != null) {
			throw new StatusException(new ErrorStatus(RConsoleCorePlugin.BUNDLE_ID,
					"Failed to authenticate over SSH connection.",
					error ));
		}
	}
	
	public static String getVersionString(final int[] version) {
		if (version == null) {
			return "no version information";
		}
		if (version.length >= 3) {
			final StringBuilder sb = new StringBuilder();
			sb.append(version[0]);
			sb.append('.');
			sb.append((version[1] >= 0) ? Integer.toString(version[1]) : "x");
			sb.append('.');
			sb.append((version[2] >= 0) ? Integer.toString(version[2]) : "x");
			return sb.toString();
		}
		return "invalid version information";
	}
	
}
