import express from 'express';
import path from "path";
import morgan from "morgan";
import cookieParser from "cookie-parser";
import debug from "debug";
import * as http from "http";

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

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

    static port = 3000;

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

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

        this._app.set('views', path.join(__dirname, '../views'));
        this._app.set('view engine', 'pug');

        this._app.use(morgan('dev'));
        this._app.use(express.json());
        this._app.use(express.urlencoded({extended: false}));
        this._app.use(cookieParser());
        this._app.use(express.static(path.join(__dirname, "../public")));
        this._app.use('/web.js', express.static(path.join(__dirname, "../dist/web.bundle.js")));



        this._app.use( (req, res, next) => {
            next();
        } )
        this._app.use((err, req, res, next) => {

            res.locals.message = err.message;
            res.locals.error = err;

            res.status(err.status || 500);
            res.render('error');
            this.log("Error " + err);
        });
        this.loadRoutes();
    }

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

    }

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

                let bind = 'Port ' + App.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(App.port);
        });
    }
}

