"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("./utils");
class Settings {
    constructor() {
        this.default = require("../options.json");
        this.envMap = require("../envMap");
        this.swagger = {};
        this.morgan = {};
        this.zipkin = {};
        this.crashReporter = {};
        this.mailer = {};
        this.logger = {};
        this.redis = {};
        this.cassandra = {};
        this.elastic = {};
        this.mysql = {};
        this.metrics = {};
        this.routeMetrics = {};
        this.consul = {};
        this.custom = {};
        this.enviroments = this.extractEnviroments();
    }
    ;
    static get Instance() {
        if (this.instance === null || this.instance === undefined) {
            this.instance = new this();
        }
        return this.instance;
    }
    set(settings) {
        this.default = utils_1.default.deepExtend({}, this.default, settings);
        this.enviroments = this.extractEnviroments();
    }
    setFile(filename) {
        let path = utils_1.default.getFullRouteFrom(filename);
        let env = utils_1.default.readFromFile(path);
        if (env == null)
            return false;
        this.set(env);
        return true;
    }
    setEnvMap(envMap) {
        this.envMap = utils_1.default.deepExtend({}, this.envMap, envMap);
        this.enviroments = this.extractEnviroments();
    }
    setEnvMapFile(filename) {
        let envMap = utils_1.default.readFromFile(filename);
        if (envMap == null)
            return false;
        this.setEnvMap(envMap);
        return true;
    }
    /**
     * Setters
     */
    setRouteMetrics(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.routeMetrics != null ? this.enviroments.routeMetrics : null;
        this.routeMetrics[token] = this.applySetting(settings, this.routeMetrics[token], this.default.routeMetrics, env);
    }
    setSwagger(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.swagger != null ? this.enviroments.swagger : null;
        this.swagger[token] = this.applySetting(settings, this.swagger[token], this.default.swagger, env);
    }
    setMorgan(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.morgan != null ? this.enviroments.morgan : null;
        this.morgan[token] = this.applySetting(settings, this.morgan[token], this.default.morgan, env);
    }
    setZipkin(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.zipkin != null ? this.enviroments.zipkin : null;
        this.zipkin[token] = this.applySetting(settings, this.zipkin[token], this.default.zipkin, env);
    }
    setCrashReporter(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.crashReporter != null ? this.enviroments.crashReporter : null;
        this.crashReporter[token] = this.applySetting(settings, this.crashReporter[token], this.default.crashReporter, env);
    }
    setMailer(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.mailer != null ? this.enviroments.mailer : null;
        this.mailer[token] = this.applySetting(settings, this.mailer[token], this.default.mailer, env);
    }
    setLogger(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.logger != null ? this.enviroments.logger : null;
        this.logger[token] = this.applySetting(settings, this.logger[token], this.default.logger, env);
    }
    setRedis(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.redis != null ? this.enviroments.redis : null;
        this.redis[token] = this.applySetting(settings, this.redis[token], this.default.redis, env);
    }
    setCassandra(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.cassandra != null ? this.enviroments.cassandra : null;
        this.cassandra[token] = this.applySetting(settings, this.cassandra[token], this.default.cassandra, env);
    }
    setElastic(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.elastic != null ? this.enviroments.elastic : null;
        this.elastic[token] = this.applySetting(settings, this.elastic[token], this.default.elastic, env);
    }
    setMysql(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.mysql != null ? this.enviroments.mysql : null;
        this.mysql[token] = this.applySetting(settings, this.mysql[token], this.default.mysql, env);
    }
    setMetrics(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.metrics != null ? this.enviroments.metrics : null;
        this.metrics[token] = this.applySetting(settings, this.metrics[token], this.default.metrics, env);
    }
    setConsul(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.consul != null ? this.enviroments.consul : null;
        this.consul[token] = this.applySetting(settings, this.consul[token], this.default.consul, env);
    }
    /**
     * For custom usage like tests
     * @param token
     * @param settings
     */
    setCustom(token, settings) {
        let env = token == "global" && this.enviroments != null && this.enviroments.custom != null ? this.enviroments.custom : null;
        this.custom[token] = this.applySetting(settings, this.custom[token], this.default.custom, env);
    }
    /**
     * Geters
     */
    getRouteMetrics(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.routeMetrics != null ? this.enviroments.routeMetrics : null;
        return this.selectSetting(this.routeMetrics[token], this.default.routeMetrics, env);
    }
    getSwagger(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.swagger != null ? this.enviroments.swagger : null;
        return this.selectSetting(this.swagger[token], this.default.swagger, env);
    }
    getMorgan(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.morgan != null ? this.enviroments.morgan : null;
        return this.selectSetting(this.morgan[token], this.default.morgan, env);
    }
    getZipkin(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.zipkin != null ? this.enviroments.zipkin : null;
        return this.selectSetting(this.zipkin[token], this.default.zipkin, env);
    }
    getCrashReporter(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.crashReporter != null ? this.enviroments.crashReporter : null;
        return this.selectSetting(this.crashReporter[token], this.default.crashReporter, env);
    }
    getMailer(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.mailer != null ? this.enviroments.mailer : null;
        return this.selectSetting(this.mailer[token], this.default.mailer, env);
    }
    getLogger(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.logger != null ? this.enviroments.logger : null;
        return this.selectSetting(this.logger[token], this.default.logger, env);
    }
    getRedis(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.redis != null ? this.enviroments.redis : null;
        return this.selectSetting(this.redis[token], this.default.redis, env);
    }
    getCassandra(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.cassandra != null ? this.enviroments.cassandra : null;
        return this.selectSetting(this.cassandra[token], this.default.cassandra, env);
    }
    getElastic(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.elastic != null ? this.enviroments.elastic : null;
        return this.selectSetting(this.elastic[token], this.default.elastic, env);
    }
    getMysql(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.mysql != null ? this.enviroments.mysql : null;
        return this.selectSetting(this.mysql[token], this.default.mysql, env);
    }
    getMetrics(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.metrics != null ? this.enviroments.metrics : null;
        return this.selectSetting(this.metrics[token], this.default.metrics, env);
    }
    getConsul(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.consul != null ? this.enviroments.consul : null;
        return this.selectSetting(this.consul[token], this.default.consul, env);
    }
    /**
     * For custom usage like tests
     * @param token
     */
    getCustom(token) {
        let env = token == "global" && this.enviroments != null && this.enviroments.custom != null ? this.enviroments.custom : null;
        return this.selectSetting(this.custom[token], this.default.custom, env);
    }
    resetSwagger(token) {
        this.swagger[token] = {};
    }
    resetMorgan(token) {
        this.morgan[token] = {};
    }
    resetZipkin(token) {
        this.zipkin[token] = {};
    }
    resetCrashReporter(token) {
        this.crashReporter[token] = {};
    }
    resetMailer(token) {
        this.mailer[token] = {};
    }
    resetLogger(token) {
        this.logger[token] = {};
    }
    resetRedis(token) {
        this.redis[token] = {};
    }
    resetMysql(token) {
        this.mysql[token] = {};
    }
    resetCassandra(token) {
        this.cassandra[token] = {};
    }
    resetElastic(token) {
        this.elastic[token] = {};
    }
    resetMetrics(token) {
        this.metrics[token] = {};
    }
    /**
     * For custom usage like tests
     * @param token
     */
    resetCustom(token) {
        this.custom[token] = {};
    }
    /**
     * Utils
     */
    applySetting(newSettings, oldSettings, defaultSettings, envSettings) {
        if (newSettings == null)
            newSettings = {};
        if (oldSettings == null)
            oldSettings = {};
        if (defaultSettings == null)
            defaultSettings = {};
        if (envSettings == null)
            envSettings = {};
        return utils_1.default.deepExtend({}, defaultSettings, oldSettings, newSettings, envSettings);
    }
    selectSetting(setting, defaultSettings, envSettings) {
        //If we have setting reture it
        if (setting != null)
            return setting;
        //Else return default settings with enviroments injected
        if (envSettings == null)
            envSettings = {};
        return utils_1.default.deepExtend({}, defaultSettings, envSettings);
    }
    extractEnviroments() {
        let response = {};
        let envNames = Object.keys(this.envMap);
        let self = this;
        envNames.forEach(function (name) {
            let path = self.envMap[name].route;
            let type = self.envMap[name].type;
            if (path == null || type == null)
                return;
            path = JSON.parse(JSON.stringify(path)); //Need a copy of object
            let value;
            switch (type) {
                case "boolean":
                    value = self.envBoolean(name);
                    break;
                case "number":
                    value = self.envNumber(name);
                    break;
                case "string":
                    value = self.envString(name);
                    break;
                case "array":
                    value = self.envArray(name);
                    break;
                default:
                    return;
            }
            let deepSize = path.length;
            if (deepSize < 2 || value == null)
                return;
            let tempParam = null;
            let param = value;
            path.reverse(); //Reverse elements in array
            path.forEach(function (deep) {
                tempParam = param;
                param = {};
                param[deep] = tempParam;
            });
            tempParam = null;
            response = utils_1.default.deepExtend({}, response, param);
        });
        return response;
    }
    envArray(name) {
        let response = process.env[name];
        if (response == null)
            return null;
        response = response.trim();
        let array = response.match(/\S+/g);
        return array;
    }
    envBoolean(name) {
        let response = process.env[name];
        if (response == null)
            return null;
        response = response.trim().toLowerCase();
        if (response == "true")
            return true;
        if (response == "false")
            return false;
        return null;
    }
    envString(name) {
        let response = process.env[name];
        if (response == null)
            return null;
        response = response.trim();
        if (response == "")
            return null;
        return response;
    }
    envNumber(name) {
        let response = process.env[name];
        if (response == null)
            return null;
        response = response.trim().toLowerCase();
        //check if string contains only digits with posible one dot in middle 
        if (!/^\d+(\.\d+)?$/.test(response))
            return null;
        let number = parseFloat(response);
        if (isNaN(number))
            return null;
        return number;
    }
    /**
     * Only for tests
     */
    reset() {
        Settings.instance = null;
    }
}
Settings.ZIPKIN_CONTEXT_NAME = 'express-context';
exports.default = Settings;
//# sourceMappingURL=settings.js.map