import { SshClient, SshShell } from './@f2/ssh-client';
import { ClientErrorExtensions } from 'ssh2';
import { PmacUnsolicitedBaseClient } from './unsolicited-base-client';


interface GetSendShells {
    buffer: number;
    shell: SshShell;
}

export interface PmacUnsolicitedAutoClient extends PmacUnsolicitedBaseClient {

    on(event: 'connect', cb: () => void): this;
    on(event: 'disconnect', cb: () => void): this;
    on(event: 'message', cb: (msg: string, buffer: number) => void): this;
    on(event: 'error', cb: (err: Error) => void): this;

    emit(event: 'connect'): boolean;
    emit(event: 'disconnect'): boolean;
    emit(event: 'message', msg: string, buffer: number): boolean;
    emit(event: 'error', err: Error): boolean;
}

export class PmacUnsolicitedAutoClient extends PmacUnsolicitedBaseClient{

    private _running = false;
    private _connected = false;

    get connected(): boolean {

        return this._connected;
    }

    constructor(sshClient: SshClient, buffers: number[]) {

        super(sshClient, buffers);

        sshClient.on('disconnect', () => {

            this._connected = false;
            this.emit('disconnect');

            setTimeout(() => this._tryConnect());
        });

        sshClient.on('error', (err) => {

            this.emit('error', err);
        })
    }

    private async _tryConnect(): Promise<void> {

        if(!this._running) {
            return;
        }

        try {

            await this._connect();

            this._connected = true;

            this.emit('connect');

            return;
        } catch (err) {

            if(!(err as ClientErrorExtensions).level) {
                this.emit('error', err as Error);
            }
        }

        setTimeout(() => this._tryConnect(), 1000);
    }
    
    public start(): void {

        this._running = true;

        this._tryConnect();
    }

    public stop(): void {
        this._running = false;

        this._sshClient.close();
    }
}

