#!/usr/bin/env node

process.on('unhandledRejection', error => {
    // this makes sure that stacktrace of failed promise is printed out
    console.log(error);

    // but also try to log it into file
    require('./services/log').info(error);
});

const { app, sessionParser } = require('./app');
const debug = require('debug')('node:server');
const fs = require('fs');
const http = require('http');
const https = require('https');
const config = require('./services/config');
const log = require('./services/log');
const appInfo = require('./services/app_info');
const messagingService = require('./services/messaging');
const utils = require('./services/utils');
const sqlInit = require('./services/sql_init');
const port = require('./services/port');

let httpServer;

async function startTrilium() {
    const usedPort = await port;

    app.set('port', usedPort);

    if (config['Network']['https']) {
        const options = {
            key: fs.readFileSync(config['Network']['keyPath']),
            cert: fs.readFileSync(config['Network']['certPath'])
        };

        httpServer = https.createServer(options, app);

        log.info("App HTTPS server starting up at port " + usedPort);
    }
    else {
        httpServer = http.createServer(app);

        log.info("App HTTP server starting up at port " + usedPort);
    }

    log.info(JSON.stringify(appInfo, null, 2));

    /**
     * Listen on provided port, on all network interfaces.
     */

    httpServer.keepAliveTimeout = 120000 * 5;
    httpServer.listen(usedPort);
    httpServer.on('error', onError);
    httpServer.on('listening', () => debug('Listening on port' + httpServer.address().port));

    sqlInit.dbReady.then(() => messagingService.init(httpServer, sessionParser));

    if (utils.isElectron()) {
        const electronRouting = require('./routes/electron');
        electronRouting(app);
    }
}

startTrilium();

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
    if (error.syscall !== 'listen') {
        throw error;
    }

    // handle specific listen errors with friendly messages
    switch (error.code) {
        case 'EACCES':
            console.error('Port requires elevated privileges');
            process.exit(1);
        break;

        case 'EADDRINUSE':
            console.error('Port is already in use');
            process.exit(1);
        break;

        default:
            throw error;
    }
}