import * as net from "net";
import * as shortid from "shortid";
import { Log } from "./log";
import { TcpSessionManager } from "./tcpSessionManager";

export class TcpServer {
    // Singleton ==================================
    private static _instance: TcpServer = null;

    static getInstance() {
        if (TcpServer._instance === null) {
            TcpServer._instance = new TcpServer();
        }

        return TcpServer._instance;
    }

    constructor() {
        this.tag = 'TcpServer';
        this._server = null;
        this._port = 0;
        this._host = '';
        this._sessionManager = new TcpSessionManager();
    }
    // ============================================

    tag;
    private _sessionManager;
    private _server;
    private _port;
    private _host;

    init(port, host) {
        let server = net.createServer((socket) => {
            /// on socket connection:
            this._sessionManager.createSession(socket);
        });

        this._server = server;
        this._port = port;
        this._host = host;
        this._bindServerEvents(server);
    }

    _bindServerEvents(server) {
        server.on('error', (err) => {
            if (err.code == 'EADDRINUSE') {
                Log.error(this.tag, 'Address in use, retrying...');
                this._retry();
            } else {
                Log.error(this.tag, err.toString());
            }
        });

        server.listen(this._port, this._host, () => {
            Log.info(this.tag, 'bind to', this._host, ':', this._port);
        });
    }

    _retry() {
        if (this._server && this._port && this._host) {
            setTimeout(() => {
                let server = this._server;
                server.close();
                server.listen(this._port, this._host, () => {
                    Log.info(this.tag, 'bind to', this._host, ':', this._port);
                });
            }, 1000);
        }
    }

    periodSendingTest(ms) {
        const commands = ["!VENEER@W01\r", "!VENEER@L01\r", "!VENEER@Q01\r", "!VENEER@X01\r", "!VENEER@T01\r"];
        setInterval(() => {
            const session = this._sessionManager.getSessions()[this._sessionManager.getSessions().length - 1];
            if (session) session.getSocket().write(commands[Math.round(Math.random() * (commands.length - 1))]);
        }, ms);
    }
}
