package com.jscape.inet.ipclientssh;

import com.jscape.inet.ipclientssh.SshTunnelerConnection.SshTunnelerEvent;
import com.jscape.inet.ssh.util.SshParameters;

import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Vector;

/**
 * This class is used as SshTunneler for a local service
 *
 * @author Alvaro
 */
public class SshTunneler
        implements SshTunnelerConnection.SshServiceEndListener {

    private int portLocal;
    private SshParameters params;
    private String remoteIp;
    private int remotePort;

    private boolean running = false;

    private Vector queue = new Vector();

    private ServerSocket serverSocket = null;

    /**
     * Creates a new instance of SshTunneler local service.
     *
     * @param portLocal  The port local will be listened by the service.
     * @param params     Ssh connection parameters.
     * @param remoteIp   Remote host ip.
     * @param remotePort Remote port.
     */
    public SshTunneler(int portLocal,
                       SshParameters params, String remoteIp, int remotePort) {
        this.portLocal = portLocal;
        this.params = params;
        this.remoteIp = remoteIp;
        this.remotePort = remotePort;
    }

    /**
     * Starts the Ssh tunneler service
     *
     * @throws Exception If an error occurs
     */
    public void start()
            throws Exception {
        this.running = true;
        runService();
    }

    /**
     * Run SshTunneler service.
     *
     * @throws Exception If an error occurs.
     */
    private void runService()
            throws Exception {

        serverSocket = new ServerSocket(portLocal);
        Socket socket = null;

        while (running) {
            try {
                socket = serverSocket.accept();

                SshTunnelerConnection service = new SshTunnelerConnection(socket,
                                                                          this.params, this.remoteIp, this.remotePort);
                service.addServiceEndedListener(this);
                queue.add(service);
                service.start();
            } catch (SocketException e) {
                System.out.println(e.getMessage());
            }
        }

    }

    /**
     * Stops the ssh tunneler service.
     *
     * @throws Exception If an error occurs.
     */
    public void stop()
            throws Exception {
        this.running = false;

        for (int i = 0; queue.size() > i; i++) {
            SshTunnelerConnection service = (SshTunnelerConnection) queue.get(i);
            service.disconnect();
        }
        this.serverSocket.close();
    }

    /**
     * Service ssh tunneler ended event.
     */
    public void serviceEnded(SshTunnelerEvent event) {
        SshTunnelerConnection service = event.getSource();
        this.queue.remove(service);
    }
}
