import express from 'express';
import morgan from "morgan";
import debug from "debug";
import expressWs from "express-ws";
import http from "http";
import {handleWebSocket} from "./routes/ws/websocketRoute";

export class WebsocketApp {
    static port = 3005;
    private readonly _app: express.Application;
    private readonly _server;
    private log = debug("itender:websocket-app");

    constructor() {
        const expressApp = express();
        expressApp.set('trust proxy', 1);
        expressApp.disable("x-powered-by");
        this._server = http.createServer(expressApp);
        const wsApp= expressWs(expressApp, this._server).app;
        this._app = wsApp;
        this._app.use(morgan('dev'));
        this._app.use(express.json());
        this._app.use(express.urlencoded({extended: false}));

        this._app.set('trust proxy', 0);

        this._app.use((err, req, res, next) => {
            res.status(err.status || 500);
            res.render('error');
            this.log("Error " + err);
        });


        wsApp.ws("/", (ws, req, res) => handleWebSocket(ws, req, res));

    }

    get app() {
        return this._app;
    }

    public listen(): Promise<void> {
        return new Promise((resolve, reject) => {
            this._server.on('error', (error) => {
                if (error.syscall != 'listen') {
                    reject();
                    return;
                }

                let bind = 'Port ' + WebsocketApp.port;

                // handle specific listen errors with friendly messages
                switch (error.code) {
                    case 'EACCES':
                        reject(bind + ' requires elevated privileges');
                        break;
                    case 'EADDRINUSE':
                        reject(bind + ' is already in use');
                        break;
                    default:
                        reject();
                }

            });
            this._server.on('listening', () => {
                let addr = this._server.address();
                this.log("Listening on " + addr.port);
                resolve();
            })
            this._server.listen(WebsocketApp.port);
        });
    }
}

