'use strict';

const Hapi = require('@hapi/hapi');
const Joi = require('joi');
const Path = require('path');
const Rfr = require('rfr');

const ComSrv = Rfr('/server/comsrv');
const Db = Rfr('/server/db');
const PTable = Rfr('/server/ptable');
const Originate = Rfr('/server/originate');
const AMI = Rfr('/server/ami');

let server;

const initServer = async() => {
    server = Hapi.server({
        port: process.env.PORT,
        host: '0.0.0.0',
        routes: {
            files: {
                relativeTo: global.appRoot
            },
            json: {
                space: 4
            }
        },
        router: {
            isCaseSensitive: false,
            stripTrailingSlash: true
        },

        ...ComSrv.isDebugMode() && {
            debug: {
                log: ['error'],
                request: ['error']
            }
        },
        ...process.env.ADDRESS && {address: process.env.ADDRESS}
    });

    await server.register({
        plugin: require('hapi-favicon'),
        options: {
            path: './client/favicon.ico'
        }
    });

    await server.register([require('@hapi/vision'), require('@hapi/inert')]);
    server.route(Rfr('/server/route'));
    server.views({
        engines: { pug: require('pug') },
        path: './templates',
        relativeTo: Path.join(global.appRoot, 'server'),
        isCached: !ComSrv.isDebugMode(),
        compileOptions: {
            pretty: ComSrv.isDebugMode()
        }
    });
};



module.exports = {
    init: async () => {
        // Initialize all known configs
        Rfr('/server/config')([
            Rfr('/server/recording').config,
            Db.config,
            PTable.config,
            AMI.config,
            Originate.config,

            Joi.object({
                PORT: Joi.number().port().optional().default(80)
            })
        ]);

        const results = await Promise.allSettled([initServer(), Db.initDB(), AMI.initAMI()]);
        const errors = results.filter(p => p.status === 'rejected')
            .map(p => p.reason)
            .forEach( r => { throw new Error(r); } );

        await PTable.initPTable();
        await server.start();

        if (process.connected && process.send) {
            process.send('ready');
        }

        console.log(`Server running on ${server.info.uri} in ${ComSrv.isDebugMode() ? 'debug' : 'production'} mode`);
    }
};

['unhandledRejection', 'uncaughtException'].forEach( (eventName) => {
    process.on(eventName, e => {
        console.log(e);
        process.exit(1);
    });
});

process.on('SIGINT', () => {
    process.exit(0);
});
