import express from 'express';
import morgan from "morgan";
import debug from "debug";
import expressWs from "express-ws";
import http from "http";

export class WebsocketApp {
    get app(): express.Application {
        return this._app;
    }

    private readonly _app: express.Application;
    private readonly _server;

    static port = 3005;

    private log = debug("itender:websocket-app");

    constructor() {
        this._app = express();
        this._server = http.createServer(this._app);
        expressWs(this._app, this._server);

        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);
        });

        this.loadRoutes();
    }

    public loadRoutes( ) : void
    {
        this._app.use( "/", require("./routes/ws/websocketRoute") );
    }

    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);
        });
    }
}