import { SshClient, SshShell } from './@f2/ssh-client';
import { beginEventEmitter } from '@f2/event';


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

export interface PmacUnsolicitedBaseClient {

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

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

export class PmacUnsolicitedBaseClient {

    private _shells: GetSendShells[] = [];
    private _maxMessages = 500;

    constructor(protected _sshClient: SshClient, protected _buffers: number[]) {

        beginEventEmitter(this);
    }

    protected async _connect(): Promise<void> {

        await this._sshClient.connect();

        const isEnd = (data: Buffer) => {

            return data.toString().indexOf('\n') !== -1 || data.toString().indexOf('\r') !== -1;
        };

        this._buffers.forEach((buffer) => {

            const shell = this._sshClient.shell();

            const task = shell.runTaskCmd(`/opt/ppmac/getsends/getsends -${buffer}`);
            let ready = false;

            task.onProgress((step) => {

                let str: string;

                step.is('data', (data) => {

                    str = data.toString();

                    if(ready) {

                        let messages = str.substring(0, str.length - 1).split('\n');
                        const length = messages.length;

                        if(length > this._maxMessages) {
                            messages = messages.slice(length - this._maxMessages - 1, length - 1)
                        }

                        messages.forEach((msg) => {

                            if(msg.charCodeAt(0) === 6) {
                                return;
                            }
                            this.emit('message', msg.match(/^-[0-9]\:/) ? msg.substring(4) : msg, buffer);
                        });
                        
                    } else {

                        ready = isEnd(data);
                    }
                })
            });

            shell.on('error', (err) => {
                this.emit('error', err);
            });

            this._shells.push({
                shell,
                buffer
            });
        });
    }

    protected _close(): void {
        this._sshClient.close();
    }
}

