package de.hacksaar.javatuer;

import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.UserInfo;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class TyshellClient {
	private static final String TAG = "TyshellClient";
	public static final char END_OF_COMMAND = '\n';
	private final String hostname;
	private final int port;
	private final TuerLogging log;
	private SshClient client;
	private InputStreamReader inputStream;
	private OutputStreamWriter outputStream;

	public TyshellClient(String hostname, int port) {
		this(hostname, port, new DummyLogging());
	}

	public TyshellClient(String hostname, int port, TuerLogging log) {
		this.log = log;
		this.hostname = hostname;
		this.port = port;
	}

	public void connect(String username, String password) {
		try {
			client = new SshClient(hostname, username, port, log);
			client.login(password);
			inputStream = new InputStreamReader(client.getInputStream());
			outputStream = new OutputStreamWriter(client.getOutputStream());
		} catch (JSchException | IOException e) {
			log.exception(TAG, e);
		}
	}

	public void connect(String username, String keyFile, String passphrase) {
		try {
			client = new SshClient(hostname, username, port, log);
			client.addPrivateKey(keyFile, passphrase);
			client.login();
			inputStream = new InputStreamReader(client.getInputStream());
			outputStream = new OutputStreamWriter(client.getOutputStream());
		} catch (JSchException | IOException e) {
			log.exception(TAG, e);
		}
	}

	public void connect(String username, String keyFile, UserInfo interactiveLogin) {
		try {
			client = new SshClient(hostname, username, port, log);
			client.addPrivateKey(keyFile);
			client.login(interactiveLogin);
			inputStream = new InputStreamReader(client.getInputStream());
			outputStream = new OutputStreamWriter(client.getOutputStream());
		} catch (JSchException | IOException e) {
			log.exception(TAG, e);
		}
	}

	public void disconnect() {
		try {
			inputStream.close();
			outputStream.close();
		} catch (IOException e) {
			log.exception(TAG, e);
		}
		client.disconnect();
	}

	boolean isConnected() {
		return (client.isConnected() && inputStream != null && outputStream != null);
	}

	public void sendCommand(String command) {
		if (isConnected()) {
			try {
				assert outputStream != null;
				log.debug(TAG, "Sending: " + command);
				outputStream.write((command + END_OF_COMMAND).toCharArray());
				outputStream.flush();
			} catch (IOException e) {
				log.exception(TAG, e);
			}
		}
	}
}
