const base = require('node-base-module');
const Utils = base.Utils;

/**
 * More functional examples can be found in:
 *      src/demo/simpleWebServer.ts or 
 *      src/test/test-express.ts
 */

 /**
  * If you want to link this module to your project run:
  * "npm link" - in module folder, after this
  * "npm link node-base-module" - in jour project (order is important)
  */

export default class WebServer {
    public app;
    public server;

    constructor() {
        /**
         * Step 1. Initialization
         * 
         * Default initialization can be found in node-base-module/options.json
         * To set your custom setting use base.setDefaultOptions or base.resetDefaultOptions
         * Both functions will replace global the default settings
         * If some settings is missing from new setting module will keep the old one
         * Express use from setting just next groups:
         *      "swagger" - to configurate the swagger if swagger/isActive are true else swagger will not be integrated
         *      "morgan" - to specify if morgan is integrated or not
         *      "logStream" - to configurate the acces log
         */

        base.setOptions({
            "swagger": {
                "swaggerDefinition": {
                    "info": {
                        "title": "RC base module",
                        "version": "1.0.0",
                        "description": "Base module for all node.js projects"
                    },
                    "basePath": "/"
                },
                "apis": ["./lib/web-server.js"],
                "isActive": true
            },
            "morgan": {
                "isActive": true
            },
            "logStream": {
                "interval": "1d",
                "maxFiles": 7,
                "compress": "gzip",
                "path": "../logs",
                "logFile": "access.log"
            }
        });

        /**
         * For exemple:
         * If you are ok with default setting but you want to change swagger title, swagger apis and logStream logfile
         * Can use base.setDefaultOptions or base.resetDefaultOptions like this:
         * Specifying just what you want to change
         */
        base.setDefaultOptions({
            "swagger": {
                "swaggerDefinition": {
                    "info": {
                        "title": "node-base-module"
                    }
                },
                "apis": ["./templates/express.ts"]
            },
            "logStream": {
                "logFile": "accessFile.log"
            }
        });

        /**
         * Diference between base.setDefaultOptions and base.resetDefaultOptions are:
         * base.setDefaultOptions will overwride last setting
         * base.resetDefaultOptions will overide alwais the default setting
         * 
         * So, base.setDefaultOptions cand be use multiple time and base.resetDefaultOptions
         * each time will delete your previous setting
         */

         /**
          * For exemple:
          * If you now want to change and swagger version but cheep old setting can just use again base.setDefaultOptions:
          * But if you use base.resetDefaultOptions will reset your all setting to default an then overide
          */
          base.setDefaultOptions({
            "swagger": {
                "swaggerDefinition": {
                    "info": {
                        "version": "1.0.1",
                    }
                }
            }
          })

          
        /**
         * Step 2. Get your own express web server
         * You can use base.express()
         * Here you can alse specifay custom setting without affecting global setting
         * Any setting specifay to this function will afect just that express instance
         */
        var express = base.express();

        /**
         * Step 3(Optional). If you have your own acces log stream and you want to use it 
         * an do not let base module to handle this can use: express.setLogStream
         * Our log stream is powerfull enough and well tested
         * !!! If you dont have a good reason to dont use our log stream, dont use this function !!!
         */
        var rfs = require('rotating-file-stream');
        var logStream = rfs();
        express.setLogStream(logStream);

        /**
         * Step 4(Optional). If you want unique mode to name your rotating acces file can use express.setLogFileGenerator(logFileGenerator);
         * The default function is:
         */
        function customGenerator(time, index) {
            if (!time)
                return this.options.logStream.logFile;
    
            var month = time.getFullYear() + "" + Utils.pad(time.getMonth() + 1);
            var day = Utils.pad(time.getDate());
            var hour = Utils.pad(time.getHours());
            var minute = Utils.pad(time.getMinutes());
    
            return month + day + "-" + hour + minute + "-" + index + "-" + this.options.logStream.logFile + ".gz";
        }
        /**
         * If you dont like our name generator, you can define your own use express.setLogFileGenerator(logFileGenerator)
         */
        express.setLogFileGenerator(function(time, index){
            return "your_file_name";
        });

        /**
         * Step 5. generate an express client
         * To get access to express client use express.initialize()
         * At this point if you skip "Step 3." will be generated a default "log stream"
         * else will be youse your own "log stream"
         * Same for setting, if you set options.morgan.isActive to false, will not be integrate morgane
         * to your express client. Same for this.options.swagger.isActive.
         */
        this.app = express.initialize();

        /**
         * !!! Atention !!! in any case will be generated a route to "/health"
         * At this route you can check status for all used inner resources like: redis, cassandra and elastic.
         * Also an generar status over all to know if is safe to use or not your project.
         * 
         * For exemple: Your project use redis and elastic but not cassandra, checking "/health" from exterior
         * you can see if both connection is disponible to make any operation and will ignore cassandra until you decide
         * to actually use it.
         * 
         * If you want see if all used resources ar functional and ready to be used, inside of your project, can check:
         * base.isFunctional(), which will return an boolean to tell if all is functional or not
         */
        base.isFunctional();

        /**
         * Step 6(Optional). If you have your own resorces like: mysql or differents workers, anything is crucial for well functionality
         * of your project can use base.setProjectFunctionality() to tell if your integrated resources are fully functional or not.
         * After this base.isFunctional() will keep in mind ale your custom resources an will tell you if all resources used by you(inner module and your own project)
         * are fully functional or not
         */
        base.setProjectFunctionality(function(){
            return true; //If all is functional
        });

        
        /**
         * Step 7(Optional). Aditional information
         * If you have custom resources whitch are neccesary for well functionality of your project specificated in "Step 6",
         * we recomand you to also add aditional information for each custom resource you include, outsede of this module,
         * useing base.setProjectStatus().
         * This metod will be use for "/healt" route to display not just if project is functional or not but alse and status for each resource used.
         * 
         * !!! Attention !!!
         * If you include any resource otside of this module
         * You need to specify they functionality in setProjectFunctionality()
         * And status for each of one in setProjectStatus()
         * If you use just resource from this module you dont need any of this function.
         */
        base.setProjectStatus(function(){
            return {
                "mySql": "status_of_mysql",
                "casper": "status_of_casper"
            };
        });


        /**
         * Step 8(Optional). Include routes
         * To include your own route use express client generated at "Step 5" with function express.initialize()
         */

         /**
          * Note:
          * You can find in req.body a parser object
          * Module by default parse anyting he find in req.body
          */
        this.app.get('/test', function (req, res, next) {
            res.status(200);                    
            res.send(JSON.stringify("Ower test response")); 
        });

        /**
         * Also you can use auto generated routes:
         *      "/health" for functionality
         *      "/swagger.json" for swagger documentation
         */

        /**
         * Step 9. Public your webserver
         */
        let port = 9876;
        this.server = this.app.listen(port);
    }
}
