package click.runtime.remote;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import jist.runtime.JistAPI;

import click.runtime.remote.WrapSshConnector2.AsynchRunner;

import de.mud.jta.Wrapper;
import de.mud.ssh.SshWrapper;

public class WrapSshConnector implements RemoteConnector {
  
  public static int nextRequestId = 1;

  protected Wrapper ssh;

  private String user;
  private String password;
  private int port;
  private Map<Integer, AsynchRunner> mapRequests;

  public WrapSshConnector() {
    ssh = new SshWrapper();
    mapRequests = new HashMap<Integer, AsynchRunner>();
  }

  /*
   * (non-Javadoc)
   * @see click.runtime.remote.RemoteConnector#init(java.util.Properties)
   */
  public void init(Properties prop) {
    user = prop.getProperty("user", null);
    password = prop.getProperty("password", null);
    port = Integer.parseInt(prop.getProperty("port", "22"));
  }

  /*
   * (non-Javadoc)
   * @see click.runtime.remote.RemoteConnector#connect(java.lang.String, int, java.lang.String, java.lang.String)
   */
  public void connect(String host, int port, String user, String password)
      throws IOException {
    ssh.connect(host, port);
    if (user != null && user.length() > 0)
      ssh.login(user, password);
    ssh.setPrompt("root@OpenWrt");
  }

  /*
   * (non-Javadoc)
   * @see click.runtime.remote.RemoteConnector#connect(java.lang.String, int)
   */
  public void connect(String host) throws IOException {
    this.connect(host, port, user, password);
  }

  /*
   * (non-Javadoc)
   * @see click.runtime.remote.RemoteConnector#disconnect()
   */
  public void disconnect() throws IOException {
    ssh.disconnect();
  }

  /*
   * (non-Javadoc)
   * @see click.runtime.remote.RemoteConnector#execute(java.lang.String)
   */
  public String execute(String command) throws IOException {
    return ssh.send(command);
  }

  public class AsynchRunner extends Thread implements JistAPI.DoNotRewrite {
    private int requestId;
    private String[] script;
    private String output = "";
    private IOException e;
    public AsynchRunner(int requestId, String[] script) {
      this.requestId = requestId;
      this.script = script;
    }
    public void run() {
      try {
        for (int i = 0; i < script.length; i++) {
          output += execute(script[i]);
        }
      } catch (IOException e) {
        this.e = e;
      }
    }
  }
  
  public int beginExecute(String[] script) {
    AsynchRunner thread = new AsynchRunner(nextRequestId++, script);
    mapRequests.put(thread.requestId, thread);
    thread.start();
    return thread.requestId;
  }

  public String finishExecute(int requestId) throws IOException {
    AsynchRunner runner = mapRequests.remove(requestId);
    try {
      runner.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    if (null != runner.e)
      throw runner.e;
    return runner.output;
  }


}
