import * as baseType from "../index.d";
let assert = require('assert');
import Settings from "../settings";
let base = require('../index');

class SettingsWraper extends Settings{

    public useExtractEnviroments(): baseType.ModuleOptions {
        return this.extractEnviroments();
    }
    
    public getArray(name: string): string[] | null {
        return this.envArray(name);
    }

    public getString(name: string): string | null {
        return this.envString(name);
    }

    public getNumber(name: string): number | null {
        return this.envNumber(name);
    }

    public getBoolean(name: string): boolean | null {
        return this.envBoolean(name);
    }

    public useReset() {
        this.reset();
    }
}

let sett = new SettingsWraper();
let oldEnv = process.env;

describe('test settings', function () {
    beforeEach(function(){
        process.env = JSON.parse(JSON.stringify(oldEnv));
        sett.useReset();
    });

    it('envArray', function (done) {
        //Set enviroments
        process.env["INVALID_ARRAY"] = "        ";//Tab, space, tab
        process.env["INVALID_ARRAY2"] = "";
        process.env["SINGLE_ELEM_ARRAY"] = "test_val";
        process.env["TOW_ELEMS_ARRAY"] = "test val";
        process.env["HARD_ELEMS_ARRAY"] = "test     val comma,   tree;fore 4 3k4 kkl4 dot.  .tab";

        //Tests
        assert.equal(sett.getArray("INVALID_ARRAY"), null);
        assert.equal(sett.getArray("INVALID_ARRAY2"), null);
        assert.equal(sett.getArray("INEXISTENT_ARRAY"), null);

        //SINGLE_ELEM_ARRAY
        let single = sett.getArray("SINGLE_ELEM_ARRAY");
        if(single == null){
            assert.notEqual(single, null);
            done("Error");
            return;            
        }
        assert.equal(single.length, 1);
        assert.equal(single[0], "test_val");

        //SINGLE_ELEM_ARRAY
        let tow = sett.getArray("TOW_ELEMS_ARRAY");
        if(tow == null){
            assert.notEqual(tow, null);
            done("Error");
            return;            
        }
        assert.equal(tow.length, 2);
        assert.equal(tow[0], "test");
        assert.equal(tow[1], "val");


        //HARD_ELEMS_ARRAY
        let hard = sett.getArray("HARD_ELEMS_ARRAY");
        if(hard == null){
            assert.notEqual(hard, null);
            done("Error");
            return;            
        }
        assert.equal(hard.length, 9);
        assert.equal(hard[0], "test");
        assert.equal(hard[1], "val");
        assert.equal(hard[2], "comma,");
        assert.equal(hard[3], "tree;fore");
        assert.equal(hard[4], "4");
        assert.equal(hard[5], "3k4");
        assert.equal(hard[6], "kkl4");
        assert.equal(hard[7], "dot.");
        assert.equal(hard[8], ".tab");
        done();
    });

    it('envString', function (done) {
        //Set enviroments
        process.env["INVALID_STRING"] = "        ";//Tab, space, tab
        process.env["INVALID_STRING2"] = "";
        process.env["VALID_STRING"]  = "tESt_val";
        process.env["VALID_STRING2"] = "test val";
        process.env["VALID_STRING3"] = "43a";
        process.env["VALID_STRING4"] = "a43";
        process.env["VALID_STRING5"] = "-34";
        process.env["VALID_STRING6"] = "     0  ";//Tab, space, 0, space, tab

        //Tests
        assert.equal(sett.getString("INVALID_STRING"), null);
        assert.equal(sett.getString("INVALID_STRING2"), null);
        assert.equal(sett.getString("INEXISTENT_STRING"), null);
        assert.equal(sett.getString("VALID_STRING"), "tESt_val");
        assert.equal(sett.getString("VALID_STRING2"), "test val");
        assert.equal(sett.getString("VALID_STRING3"), "43a");
        assert.equal(sett.getString("VALID_STRING4"), "a43");
        assert.equal(sett.getString("VALID_STRING5"), "-34");
        assert.equal(sett.getString("VALID_STRING6"), "0");

        done();
    });

    it('envNumber', function (done) {
        //Set enviroments
        process.env["INVALID_NUMBER1"] = "        ";//Tab, space, tab
        process.env["INVALID_NUMBER2"] = "";
        process.env["INVALID_NUMBER3"]  = "test_val";
        process.env["INVALID_NUMBER4"] = "test val";
        process.env["INVALID_NUMBER6"] = "a43";
        process.env["INVALID_NUMBER7"] = "43a";
        process.env["INVALID_NUMBER8"] = "43a41";
        process.env["INVALID_NUMBER9"] = "43,41";
        process.env["INVALID_NUMBER10"] = ".41";
        process.env["INVALID_NUMBER11"] = "41.";
        process.env["INVALID_NUMBER12"] = "34 45 66";
        process.env["INVALID_NUMBER13"] = "0x10";//support just base 10        
        
        
        //By JavaScript parseFloat() Function "43a" is valid int represent "43";
        //https://www.w3schools.com/jsref/jsref_parsefloat.asp        
        process.env["VALID_NUMBER1"] = "10";
        process.env["VALID_NUMBER2"] = "10.00";
        process.env["VALID_NUMBER3"] = "10.33";
        process.env["VALID_NUMBER4"] = "   60   ";
        process.env["VALID_NUMBER5"] = "010";
        process.env["VALID_NUMBER6"] = "    0  ";//Tab, space, 0, space, tab

        //Tests
        assert.equal(sett.getNumber("INVALID_NUMBER1"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER2"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER3"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER4"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER5"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER6"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER7"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER8"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER9"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER10"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER11"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER12"), null);
        assert.equal(sett.getNumber("INVALID_NUMBER13"), null);
        

        assert.equal(sett.getNumber("VALID_NUMBER1"), 10);
        assert.equal(sett.getNumber("VALID_NUMBER2"), 10);
        assert.equal(sett.getNumber("VALID_NUMBER3"), 10.33);
        assert.equal(sett.getNumber("VALID_NUMBER4"), 60);
        assert.equal(sett.getNumber("VALID_NUMBER5"), 10);
        assert.equal(sett.getNumber("VALID_NUMBER6"), 0);

        done();
    });

    it('envArray', function (done) {
        process.env["INVALID_BOOLEAN1"] = "        ";//Tab, space, tab
        process.env["INVALID_BOOLEAN2"] = "";
        process.env["INVALID_BOOLEAN3"] = "test_val";
        process.env["INVALID_BOOLEAN4"] = "test val";
        process.env["INVALID_BOOLEAN5"] = "a43";
        process.env["INVALID_BOOLEAN6"] = "1";
        process.env["INVALID_BOOLEAN7"] = "0";
        process.env["INVALID_BOOLEAN8"] = "-1";
        process.env["INVALID_BOOLEAN9"] = "TRUES";
        process.env["INVALID_BOOLEAN10"] = "FALSES";
        process.env["INVALID_BOOLEAN11"] = "TRUE S";
        process.env["INVALID_BOOLEAN12"] = "FALSE S";
        process.env["INVALID_BOOLEAN13"] = "S TRUE";
        process.env["INVALID_BOOLEAN14"] = "S FALSE";

        process.env["VALID_BOOLEAN1"] = "    true   ";//Tab, space, true, space, tab
        process.env["VALID_BOOLEAN2"] = "false";
        process.env["VALID_BOOLEAN3"] = "TRUE";
        process.env["VALID_BOOLEAN4"] = "FALSE";

        assert.equal(sett.getBoolean("INVALID_BOOLEAN1"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN2"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN3"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN4"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN5"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN6"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN7"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN8"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN9"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN10"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN11"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN12"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN13"), null);
        assert.equal(sett.getBoolean("INVALID_BOOLEAN14"), null);

        assert.equal(sett.getBoolean("VALID_BOOLEAN1"), true);
        assert.equal(sett.getBoolean("VALID_BOOLEAN2"), false);
        assert.equal(sett.getBoolean("VALID_BOOLEAN3"), true);
        assert.equal(sett.getBoolean("VALID_BOOLEAN4"), false);

        done();
    }); 
    
    
    it('test full mount', function (done) {
        //swagger
        process.env["SWAGGER_ALLOWED_DOMAINS"] = "domain1.com www.dom.domain.net";

        //morgan
        process.env["MORGAN_USE_STDOUT"] = "FALSE";

        //crashReporter
        process.env["CRASH_REPORTER_ENABLE_MAIL"] = "false";

        //mailer
        process.env["MAILER_HOST"] = "23.43.233.451";
        process.env["MAILER_PORT"] = "3495";
        process.env["MAILER_USER"] = "username";
        process.env["MAILER_PASS"] = "password";

        //redis
        process.env["REDIS_USE_CLUSTER"] = "TRUE";
        process.env["REDIS_PASS"] = "PASSWORD";
        process.env["REDIS_PORT"] = "4985";
        process.env["REDIS_HOST"] = "HOST.NAME";

        //cassandra
        process.env["CASSANDRA_HOST"] = "HOST1 HOST2 host3";
        process.env["CASSANDRA_PORT"] = "4532";
        process.env["CASSANDRA_KEYSPACE"] = "KEYS";
        process.env["CASSANDRA_USER"] = "USERNAME";
        process.env["CASSANDRA_PASS"] = "PARApass";

        //elastic
        process.env["ELASTIC_HOST"] = "23.00.00.00";
        process.env["ELASTIC_LOG"] = "NULL";
        
        let response = sett.useExtractEnviroments();
        let expected = {
            swagger: {
                allowedDomains: ["domain1.com", "www.dom.domain.net"],
            },
            morgan: {
                useStdout: false,
            },
            crashReporter: {
                mailEnabled: false,
            },
            mailer: {
                mailTransportConfig: {
                    host: "23.43.233.451",
                    port: 3495,
                    auth: {
                        user: "username",
                        pass: "password",
                    }
                }
            },
            redis: {
                isCluster: true,
                password: "PASSWORD",
                port: 4985,
                host: "HOST.NAME",
            },
            cassandra: {
                hosts: ["HOST1", "HOST2", "host3"],
                port: 4532,
                keyspace: "KEYS",
                user: "USERNAME",
                password: "PARApass",
            },
            elastic: {
                host: "23.00.00.00",
                log: "NULL",
            }
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test empty mount', function (done) {
        let response = sett.useExtractEnviroments();
        assert.equal(JSON.stringify(response), JSON.stringify({}));

        done();
    });

    it('test mount partial case 1', function (done) {

        //mailer
        process.env["MAILER_HOST"] = "23.43.233.451";
        process.env["MAILER_PORT"] = "3495";

        //redis
        process.env["REDIS_USE_CLUSTER"] = "TRUE";
        process.env["REDIS_HOST"] = "HOST.NAME";

        //cassandra
        process.env["CASSANDRA_HOST"] = "HOST1";
        process.env["CASSANDRA_PORT"] = "4532";
        process.env["CASSANDRA_KEYSPACE"] = "KEYS";

        //elastic
        process.env["ELASTIC_HOST"] = "23.00.00.00";
        
        let response = sett.useExtractEnviroments();
        let expected = {
            mailer: {
                mailTransportConfig: {
                    host: "23.43.233.451",
                    port: 3495,
                }
            },
            redis: {
                isCluster: true,
                host: "HOST.NAME",
            },
            cassandra: {
                hosts: ["HOST1"],
                port: 4532,
                keyspace: "KEYS",
            },
            elastic: {
                host: "23.00.00.00",
            }
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test mount partial case 2', function (done) {
        //swagger
        process.env["SWAGGER_ALLOWED_DOMAINS"] = "domain1.com";

        //crashReporter
        process.env["CRASH_REPORTER_ENABLE_MAIL"] = "false";

        //mailer
        process.env["MAILER_USER"] = "username";

        //redis
        process.env["REDIS_PASS"] = "PASSWORD";
        process.env["REDIS_PORT"] = "4985";

        //cassandra
        process.env["CASSANDRA_KEYSPACE"] = "KEYS";
        process.env["CASSANDRA_USER"] = "USERNAME";
        process.env["CASSANDRA_PASS"] = "PARApass";

        //elastic
        process.env["ELASTIC_LOG"] = "NULL";
        
        let response = sett.useExtractEnviroments();
        let expected = {
            swagger: {
                allowedDomains: ["domain1.com"],
            },
            crashReporter: {
                mailEnabled: false,
            },
            mailer: {
                mailTransportConfig: {
                    auth: {
                        user: "username",
                    }
                }
            },
            redis: {
                password: "PASSWORD",
                port: 4985,
            },
            cassandra: {
                keyspace: "KEYS",
                user: "USERNAME",
                password: "PARApass",
            },
            elastic: {
                log: "NULL",
            }
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test swagger settings', function (done) {
        process.env["SWAGGER_ALLOWED_DOMAINS"] = "new.domain.com";

        let swagger_def = Settings.Instance.getSwagger("global").swaggerDefinition;
        
        let settings = {
            swaggerDefinition: {
                info: {
                    title: "new title",
                },
            },
            apis: ["./test/test-settings.js"],
            allowedDomains: ["domain.net"],
        }

        let settings2 = {
            swaggerDefinition: {
                info: {
                    description: "New description",
                },
            },
            allowedDomains: ["domain2.net"],
        }

        Settings.Instance.setSwagger("test", settings);
        Settings.Instance.setSwagger("test", settings2);
        
        let response = Settings.Instance.getSwagger("test");

        let expected = {
            swaggerDefinition: {
                info: {
                    title: "new title",
                    version: swagger_def != null && swagger_def.info != null && swagger_def.info.version != null ? swagger_def.info.version : "1.0.14",
                    description: "New description"
                },
                basePath: "/"
            },
            apis: ["./test/test-settings.js"],
            allowedDomains: ["domain2.net"],
            allowHeaders: "Origin, X-Requested-With, Content-Type, Accept, Authorization",
            allowMethods: "GET, POST, OPTIONS",
            isActive: true
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test swagger settings (global tag)', function (done) {
        process.env["SWAGGER_ALLOWED_DOMAINS"] = "new.domain.com";

        let swagger_def = Settings.Instance.getSwagger("global").swaggerDefinition;

        
        let settings = {
            swaggerDefinition: {
                info: {
                    title: "new title",
                },
            },
            apis: ["./test/test-settings.js"],
            allowedDomains: ["domain.net"],
        }

        let settings2 = {
            swaggerDefinition: {
                info: {
                    description: "New description",
                },
            },
            allowedDomains: ["domain2.net"],
        }

        Settings.Instance.setSwagger("global", settings);
        Settings.Instance.setSwagger("global", settings2);
        
        let response = Settings.Instance.getSwagger("global");

        let expected = {
            swaggerDefinition: {
                info: {
                    title: "new title",
                    version: swagger_def != null && swagger_def.info != null && swagger_def.info.version != null ? swagger_def.info.version : "1.0.10",
                    description: "New description"
                },
                basePath: "/"
            },
            apis: ["./test/test-settings.js"],
            allowedDomains: ["new.domain.com"],
            allowHeaders: "Origin, X-Requested-With, Content-Type, Accept, Authorization",
            allowMethods: "GET, POST, OPTIONS",
            isActive: true
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test morgan settings', function (done) {
        process.env["MORGAN_USE_STDOUT"] = "FALSE";
        
        let settings = {
            useStdout: true,
            logStream: {
                interval: "2d",
                maxFiles: 8,
                logFile: "access2.log"
            }
        }

        let settings2 = {
            logStream: {
                interval: "3d",
                path: "../logs2",                
            }
        }

        Settings.Instance.setMorgan("test", settings);
        Settings.Instance.setMorgan("test", settings2);
        
        let response = Settings.Instance.getMorgan("test");

        let expected = {
            isActive: true,
            useStdout: true,
            format: ":remote-addr - :remote-user [:date[clf]] \":method :url HTTP/:http-version\" :status :res[content-length] :response-time",
            logStream: {
                interval: "3d",
                maxFiles: 8,
                compress: "gzip",
                path: "../logs2",
                logFile: "access2.log"
            }
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test morgan settings (global tag)', function (done) {
        process.env["MORGAN_USE_STDOUT"] = "FALSE";
        
        let settings = {
            useStdout: true,
            logStream: {
                interval: "2d",
                maxFiles: 8,
                logFile: "access2.log"
            }
        }

        let settings2 = {
            logStream: {
                interval: "3d",
                path: "../logs2",                
            }
        }

        Settings.Instance.setMorgan("global", settings);
        Settings.Instance.setMorgan("global", settings2);
        
        let response = Settings.Instance.getMorgan("global");

        let expected = {
            isActive: true,
            useStdout: false,
            format: ":remote-addr - :remote-user [:date[clf]] \":method :url HTTP/:http-version\" :status :res[content-length] :response-time",            
            logStream: {
                interval: "3d",
                maxFiles: 8,
                compress: "gzip",
                path: "../logs2",
                logFile: "access2.log"
            }
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test crash reporter settings', function (done) {
        process.env["CRASH_REPORTER_ENABLE_MAIL"] = "false";
        
        let settings = {
            outDir : "../logs2",
            mailConfig: {
                subject: "Message",
                to: "target2@domain.com"
            } 
        };

        let settings2 = {
            mailEnabled: true,
            mailConfig: {
                subject: "New message",
            } 
        };

        Settings.Instance.setCrashReporter("test", settings);
        Settings.Instance.setCrashReporter("test", settings2);
        
        let response = Settings.Instance.getCrashReporter("test");

        let expected = {
            exitOnCrash: true,
            maxCrashFile: 5,
            mailEnabled: true,
            outDir : "../logs2",
            mailConfig: {
                subject: "New message",
                from: "creshreporter@node_base_module.com",
                to: "target2@domain.com"
            } 
        };

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test crash reporter settings (global tag)', function (done) {
        process.env["CRASH_REPORTER_ENABLE_MAIL"] = "false";
        
        let settings = {
            outDir : "../logs2",
            mailConfig: {
                subject: "Message",
                to: "target2@domain.com"
            } 
        };

        let settings2 = {
            mailEnabled: true,
            mailConfig: {
                subject: "New message",
            } 
        };

        Settings.Instance.setCrashReporter("global", settings);
        Settings.Instance.setCrashReporter("global", settings2);
        
        let response = Settings.Instance.getCrashReporter("global");

        let expected = {
            exitOnCrash: true,
            maxCrashFile: 5,
            mailEnabled: false,
            outDir : "../logs2",
            mailConfig: {
                subject: "New message",
                from: "creshreporter@node_base_module.com",
                to: "target2@domain.com"
            } 
        };

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test mailer settings', function (done) {
        process.env["MAILER_HOST"] = "23.43.233.451";
        process.env["MAILER_PORT"] = "3495";
        process.env["MAILER_USER"] = "username";
        process.env["MAILER_PASS"] = "password";

        let settings = {
            mailTransportConfig: {
                host: "localhost2",
                port: 253,
                auth:{
                    user: "email",
                    pass: "userpass"
                }
            },
            mailConfig: {
                subject: "Mail subject temp",
                text: "Remaining text"
            } 
        }

        let settings2 = {
            mailConfig: {
                subject: "Mail subject",
            } 
        }

        Settings.Instance.setMailer("test", settings);
        Settings.Instance.setMailer("test", settings2);
        
        let response = Settings.Instance.getMailer("test");

        let expected = {
            mailTransportConfig: {
                host: "localhost2",
                port: 253,
                auth:{
                    user: "email",
                    pass: "userpass"
                }
            },
            mailConfig: {
                subject: "Mail subject",
                from: "node_base_module@domain.com",
                to: "target@domain.com",
                text: "Remaining text"
            } 
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    }); 

    it('test mailer settings (global tag)', function (done) {
        process.env["MAILER_HOST"] = "23.43.233.451";
        process.env["MAILER_PORT"] = "3495";
        process.env["MAILER_USER"] = "username";
        process.env["MAILER_PASS"] = "password";

        let settings = {
            mailTransportConfig: {
                host: "localhost2",
                port: 253,
                auth:{
                    user: "email",
                    pass: "userpass"
                }
            },
            mailConfig: {
                subject: "Mail subject temp",
                text: "Remaining text"
            } 
        }

        let settings2 = {
            mailConfig: {
                subject: "Mail subject",
            } 
        }

        Settings.Instance.setMailer("global", settings);
        Settings.Instance.setMailer("global", settings2);
        
        let response = Settings.Instance.getMailer("global");

        let expected = {
            mailTransportConfig: {
                host: "23.43.233.451",
                port: 3495,
                auth:{
                    user: "username",
                    pass: "password"
                }
            },
            mailConfig: {
                subject: "Mail subject",
                from: "node_base_module@domain.com",
                to: "target@domain.com",
                text: "Remaining text"
            } 
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });
    
    it('test logger settings', function (done) {
        let settings = {
            "debugLogging": false,
            "rotatingSize": "11M",
        }
        let settings2 = {
            "rotatingSize": "12M",
            "errorFile": "errors2.log",
        }

        Settings.Instance.setLogger("test", settings);
        Settings.Instance.setLogger("test", settings2);
        
        let response = Settings.Instance.getLogger("test");

        let expected = {
            "logLevel": 0,
            "debugLogging": false,
            "logFolder": "../logs",
            "rotatingSize": "12M",
            "errorFile": "errors2.log",
            "outputFile": "output.log"
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test redis settings', function (done) {
        process.env["REDIS_USE_CLUSTER"] = "TRUE";
        process.env["REDIS_PASS"] = "PASSWORD";
        process.env["REDIS_PORT"] = "4985";
        process.env["REDIS_HOST"] = "HOST.NAME";

        let settings = {
            isCluster: false,
            sentinels:[
                {host:"localhost22", port:1234}
            ],
            password:"mypass22",
            statusCheckInterval: 10,
            port: 3214,
            host: "host.com",
            family: 6,
            autoConnect: true
        }

        let settings2 = {
            isCluster: false,
            sentinel_cluster_name:"cluster_name",
            statusCheckInterval: 100,
        }

        Settings.Instance.setRedis("test", settings);
        Settings.Instance.setRedis("test", settings2);
        
        let response = Settings.Instance.getRedis("test");

        let expected = {
            isCluster: false,
            sentinels:[
                {host:"localhost22", port:1234}
            ],
            sentinel_cluster_name:"cluster_name",
            password:"mypass22",
            keys:{
                rediskey_connections:"node-base-module:connections:"
            },
            statusCheckInterval: 100,
            port: 3214,
            host: "host.com",
            family: 6,
            autoConnect: true
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    }); 

    it('test redis settings (global tag)', function (done) {
        process.env["REDIS_USE_CLUSTER"] = "TRUE";
        process.env["REDIS_PASS"] = "PASSWORD";
        process.env["REDIS_PORT"] = "4985";
        process.env["REDIS_HOST"] = "HOST.NAME";

        let settings = {
            isCluster: false,
            sentinels:[
                {host:"localhost22", port:1234}
            ],
            password:"mypass22",
            statusCheckInterval: 10,
            port: 3214,
            host: "host.com",
            family: 6
        }

        let settings2 = {
            isCluster: false,
            sentinel_cluster_name:"cluster_name",
            statusCheckInterval: 100,
        }

        Settings.Instance.setRedis("global", settings);
        Settings.Instance.setRedis("global", settings2);
        
        let response = Settings.Instance.getRedis("global");

        let expected = {
            isCluster: true,
            sentinels:[
                {host:"localhost22", port:1234}
            ],
            sentinel_cluster_name:"cluster_name",
            password:"PASSWORD",
            keys:{
                rediskey_connections:"node-base-module:connections:"
            },
            statusCheckInterval: 100,
            port: 4985,
            host: "HOST.NAME",
            family: 6,
            autoConnect: true
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    }); 
    
    it('test cassandra settings', function (done) {
        process.env["CASSANDRA_HOST"] = "HOST1 host3";
        process.env["CASSANDRA_PORT"] = "4532";
        process.env["CASSANDRA_KEYSPACE"] = "KEYS";
        process.env["CASSANDRA_USER"] = "USERNAME";
        process.env["CASSANDRA_PASS"] = "PARApass";

        let settings = {
            hosts: ["localhost", "localhost2"],
            port: 1234,
            keyspace: "space",
            user: "name",
            password: "pass",
            timeout: 100,
            autoConnect: false
        }

        let settings2 = {
            timeout: 500,
        }

        Settings.Instance.setCassandra("test", settings);
        Settings.Instance.setCassandra("test", settings2);
        
        let response = Settings.Instance.getCassandra("test");

        let expected = {
            hosts: ["localhost", "localhost2"],
            port: 1234,
            keyspace: "space",
            user: "name",
            password: "pass",
            timeout: 500,
            autoConnect: false
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    }); 

    it('test cassandra settings (global tag)', function (done) {
        process.env["CASSANDRA_HOST"] = "HOST1 host3";
        process.env["CASSANDRA_PORT"] = "4532";
        process.env["CASSANDRA_KEYSPACE"] = "KEYS";
        process.env["CASSANDRA_USER"] = "USERNAME";
        process.env["CASSANDRA_PASS"] = "PARApass";

        let settings = {
            hosts: ["localhost", "localhost2"],
            port: 1234,
            keyspace: "space",
            user: "name",
            password: "pass",
            timeout: 100,
            autoConnect: false
        }

        let settings2 = {
            timeout: 500,
        }

        Settings.Instance.setCassandra("global", settings);
        Settings.Instance.setCassandra("global", settings2);
        
        let response = Settings.Instance.getCassandra("global");

        let expected = {
            hosts: ["HOST1", "host3"],
            port: 4532,
            keyspace: "KEYS",
            user: "USERNAME",
            password: "PARApass",
            timeout: 500,
            autoConnect: false
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    }); 
    
    it('test elastic settings', function (done) {
        process.env["ELASTIC_HOST"] = "23.00.00.00";
        process.env["ELASTIC_LOG"] = "NULL";

        let settings = {
            host: "host.com:9200",
            log: "log",
            statusCheckInterval: 200,
            autoConnect: false
        }

        let settings2 = {
            statusCheckInterval: 400,
        }

        Settings.Instance.setElastic("test", settings);
        Settings.Instance.setElastic("test", settings2);
        
        let response = Settings.Instance.getElastic("test");

        let expected = {
            host: "host.com:9200",
            log: "log",
            statusCheckInterval: 400,
            autoConnect: false
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test elastic settings (global tag)', function (done) {
        process.env["ELASTIC_HOST"] = "23.00.00.00";
        process.env["ELASTIC_LOG"] = "NULL";

        let settings = {
            host: "host.com:9200",
            log: "log",
            statusCheckInterval: 200,
            autoConnect: false
        }

        let settings2 = {
            statusCheckInterval: 400,
        }

        Settings.Instance.setElastic("global", settings);
        Settings.Instance.setElastic("global", settings2);
        
        let response = Settings.Instance.getElastic("global");

        let expected = {
            host: "23.00.00.00",
            log: "NULL",
            statusCheckInterval: 400,
            autoConnect: false
        }

        assert.equal(JSON.stringify(response), JSON.stringify(expected));
        done();
    });

    it('test setDefaultFileOptions full', function (done) {

        //Default value
        let response = {
            swagger: Settings.Instance.getSwagger("global"),
            routeMetrics: Settings.Instance.getRouteMetrics("global"),
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            mysql: Settings.Instance.getMysql("global"),            
            consul: Settings.Instance.getConsul("global"),
            custom: Settings.Instance.getCustom("global")
        }
        let expected = require("../../options.json");
        assert.equal(JSON.stringify(response), JSON.stringify(expected));

        //Set from file
        base.setDefaultFileOptions("../../../src/test/settings/alterate.json");
        
        //Ensure you do not reset settings
        let express = base.express();
        express.initialize();

        let response2 = {
            swagger: Settings.Instance.getSwagger("global"),
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            consul: Settings.Instance.getConsul("global")
        }
        let expected2 = require("../../src/test/settings/alterate.json");
        assert.equal(JSON.stringify(response2), JSON.stringify(expected2));
        
        done();
    });

    it('test setDefaultOptions full', function (done) {
        
        //Default value
        let response = {
            swagger: Settings.Instance.getSwagger("global"),
            routeMetrics: Settings.Instance.getRouteMetrics("global"),            
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            mysql: Settings.Instance.getMysql("global"),            
            consul: Settings.Instance.getConsul("global"),
            custom: Settings.Instance.getCustom("global")
        }
        let expected = require("../../options.json");
        assert.equal(JSON.stringify(response), JSON.stringify(expected));

        //Set from var
        let expected2 = require("../../src/test/settings/alterate.json");
        base.setDefaultOptions(expected2);

        //Ensure you do not reset settings
        let express = base.express();
        express.initialize();

        let response2 = {
            swagger: Settings.Instance.getSwagger("global"),
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            consul: Settings.Instance.getConsul("global")
        }
        assert.equal(JSON.stringify(response2), JSON.stringify(expected2));
        
        done();
    });

    it('test setDefaultFileOptions partial', function (done) {
        
        //Default value
        let response = {
            swagger: Settings.Instance.getSwagger("global"),
            routeMetrics: Settings.Instance.getRouteMetrics("global"),            
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            mysql: Settings.Instance.getMysql("global"),            
            consul: Settings.Instance.getConsul("global"),
            custom: Settings.Instance.getCustom("global")
        }
        let expected = require("../../options.json");
        assert.equal(JSON.stringify(response), JSON.stringify(expected));

        //Set from file
        base.setDefaultFileOptions("../../../src/test/settings/partial.json");
        
        //Ensure you do not reset settings
        let express = base.express();
        express.initialize();

        let response2 = {
            swagger: Settings.Instance.getSwagger("global"),
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            consul: Settings.Instance.getConsul("global")
        }
        let expected2 = require("../../src/test/settings/combine-default-partial.json");
        assert.equal(JSON.stringify(response2), JSON.stringify(expected2));
        
        done();
    });

    it('test setDefaultOptions partial', function (done) {
        
        //Default value
        let response = {
            swagger: Settings.Instance.getSwagger("global"),
            routeMetrics: Settings.Instance.getRouteMetrics("global"),            
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            mysql: Settings.Instance.getMysql("global"),            
            consul: Settings.Instance.getConsul("global"),
            custom: Settings.Instance.getCustom("global")
        }
        let expected = require("../../options.json");
        assert.equal(JSON.stringify(response), JSON.stringify(expected));

        //Set from var
        let settings = require("../../src/test/settings/partial.json");                
        base.setDefaultOptions(settings);

        //Ensure you do not reset settings
        let express = base.express();
        express.initialize();

        let response2 = {
            swagger: Settings.Instance.getSwagger("global"),
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            consul: Settings.Instance.getConsul("global")
        }
        let expected2 = require("../../src/test/settings/combine-default-partial.json");        
        assert.equal(JSON.stringify(response2), JSON.stringify(expected2));
        
        done();
    });

    it('test setDefaultFileOptions enviroment', function (done) {
        //swagger
        process.env["SWAGGER_ALLOWED_DOMAINS"] = "domain1.com www.dom.domain.net";
        
        //morgan
        process.env["MORGAN_USE_STDOUT"] = "TRUE";

        //crashReporter
        process.env["CRASH_REPORTER_ENABLE_MAIL"] = "false";

        //mailer
        process.env["MAILER_HOST"] = "23.43.233.451";
        process.env["MAILER_PORT"] = "3495";
        process.env["MAILER_USER"] = "username";
        process.env["MAILER_PASS"] = "password";

        //redis
        process.env["REDIS_USE_CLUSTER"] = "TRUE";
        process.env["REDIS_PASS"] = "PASSWORD";
        process.env["REDIS_PORT"] = "4985";
        process.env["REDIS_HOST"] = "HOST.NAME";

        //cassandra
        process.env["CASSANDRA_HOST"] = "HOST1 HOST2 host3";
        process.env["CASSANDRA_PORT"] = "4532";
        process.env["CASSANDRA_KEYSPACE"] = "KEYS";
        process.env["CASSANDRA_USER"] = "USERNAME";
        process.env["CASSANDRA_PASS"] = "PARApass";

        //elastic
        process.env["ELASTIC_HOST"] = "23.00.00.00";
        process.env["ELASTIC_LOG"] = "NULL";


        //Set from file
        base.setDefaultFileOptions("../../../src/test/settings/partial.json");
        
        //Ensure you do not reset settings
        let express = base.express();
        express.initialize();

        let response2 = {
            swagger: Settings.Instance.getSwagger("global"),
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            consul: Settings.Instance.getConsul("global")
        }
        let expected2 = require("../../src/test/settings/combine-default-partial-env.json");
        assert.equal(JSON.stringify(response2), JSON.stringify(expected2));
        
        done();
    });

    it('test setDefaultOptions enviroment', function (done) {
        //swagger
        process.env["SWAGGER_ALLOWED_DOMAINS"] = "domain1.com www.dom.domain.net";
        
        //morgan
        process.env["MORGAN_USE_STDOUT"] = "TRUE";

        //crashReporter
        process.env["CRASH_REPORTER_ENABLE_MAIL"] = "false";

        //mailer
        process.env["MAILER_HOST"] = "23.43.233.451";
        process.env["MAILER_PORT"] = "3495";
        process.env["MAILER_USER"] = "username";
        process.env["MAILER_PASS"] = "password";

        //redis
        process.env["REDIS_USE_CLUSTER"] = "TRUE";
        process.env["REDIS_PASS"] = "PASSWORD";
        process.env["REDIS_PORT"] = "4985";
        process.env["REDIS_HOST"] = "HOST.NAME";

        //cassandra
        process.env["CASSANDRA_HOST"] = "HOST1 HOST2 host3";
        process.env["CASSANDRA_PORT"] = "4532";
        process.env["CASSANDRA_KEYSPACE"] = "KEYS";
        process.env["CASSANDRA_USER"] = "USERNAME";
        process.env["CASSANDRA_PASS"] = "PARApass";

        //elastic
        process.env["ELASTIC_HOST"] = "23.00.00.00";
        process.env["ELASTIC_LOG"] = "NULL";


        //Set from var
        let settings = require("../../src/test/settings/partial.json");                
        base.setDefaultOptions(settings);

        //Ensure you do not reset settings
        let express = base.express();
        express.initialize();

        let response2 = {
            swagger: Settings.Instance.getSwagger("global"),
            morgan: Settings.Instance.getMorgan("global"),
            zipkin: Settings.Instance.getZipkin("global"),
            crashReporter: Settings.Instance.getCrashReporter("global"),
            mailer: Settings.Instance.getMailer("global"),
            logger: Settings.Instance.getLogger("global"),
            redis: Settings.Instance.getRedis("global"),
            cassandra: Settings.Instance.getCassandra("global"),
            elastic: Settings.Instance.getElastic("global"),
            consul: Settings.Instance.getConsul("global")
        }
        let expected2 = require("../../src/test/settings/combine-default-partial-env.json");        
        assert.equal(JSON.stringify(response2), JSON.stringify(expected2));
        
        done();
    });

    it('test custom usage', function (done) {
        process.env["VALUE1"] = "test1";
        process.env["VALUE2"] = "test2";

        Settings.Instance.setEnvMap({
            "VALUE1": {
                route: ["custom", "value1"],
                type: "string"
            },
            "VALUE2": {
                route: ["custom", "value2"],
                type: "string"
            }
        });

        let settings = {
            deep: {
                val: 3
            },
            value2: "string"
        }
        let expect = {
            exemple: "value",            
            deep: {
                val: 3
            },
            value2: "test2",            
            value1: "test1",
        }
        Settings.Instance.setCustom("global", settings);
        let response = Settings.Instance.getCustom("global");
        assert.equal(JSON.stringify(response), JSON.stringify(expect));
        done();
    })

    it('test setEnvMap', function (done) {
        process.env["SWAGGER_ALLOWED_DOMAINS"] = "test val";
        process.env["CUSTOM_TEST"] = "test_val";
        Settings.Instance.setEnvMap({
            "CUSTOM_TEST": {
                "route": ["custom", "test"],
                "type": "string"
            },
            "SWAGGER_ALLOWED_DOMAINS": {
                "route": ["custom", "allowedDomains"],
                "type": "array"
            }
        });
        let custom = Settings.Instance.getCustom("global");
        let expected = {
            exemple: "value",
            allowedDomains: ["test", "val"],
            test: "test_val"
        }
        assert.equal(JSON.stringify(custom), JSON.stringify(expected));
        done();
    });
})