"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Console = exports.Logger = exports.level = exports.promiseRetry = void 0;
const openflow_api_1 = require("@openiap/openflow-api");
const Config_1 = require("./Config");
const dockerdriver_1 = require("./dockerdriver");
const DBHelper_1 = require("./DBHelper");
const path = require('path');
const MAX_RETRIES_DEFAULT = 5;
async function promiseRetry(fn, retries = MAX_RETRIES_DEFAULT, retryIntervalMillis, previousError) {
    return !retries
        ? Promise.reject(previousError)
        : fn().catch(async (error) => {
            await new Promise((resolve) => setTimeout(resolve, retryIntervalMillis));
            return promiseRetry(fn, retries - 1, retryIntervalMillis, error);
        });
}
exports.promiseRetry = promiseRetry;
var level;
(function (level) {
    level[level["Error"] = 1] = "Error";
    level[level["Warning"] = 2] = "Warning";
    level[level["Information"] = 3] = "Information";
    level[level["Debug"] = 4] = "Debug";
    level[level["Verbose"] = 5] = "Verbose";
    level[level["Silly"] = 6] = "Silly";
})(level = exports.level || (exports.level = {}));
class Logger {
    prefix(lvl, cls, func, message) {
        let White = Console.Reset + Console.Bright + Console.FgWhite;
        let Grey = Console.Reset + Console.Dim + Console.FgWhite;
        let Red = Console.Reset + Console.Bright + Console.FgRed;
        let Yellow = Console.Reset + Console.Bright + Console.FgYellow;
        let darkYellow = Console.Reset + Console.Dim + Console.FgYellow;
        let Blue = Console.Reset + Console.Bright + Console.FgBlue;
        let Cyan = Console.Reset + Console.Bright + Console.FgCyan;
        let Green = Console.Reset + Console.Bright + Console.FgGreen;
        let dt = new Date();
        if (cls == "cli" || cls == "cli-lic" || cls == "cliutil")
            cls = "";
        let prefix = "";
        let color = Cyan;
        if (lvl == level.Debug)
            color = Blue;
        if (lvl == level.Verbose || lvl == level.Silly)
            color = Grey;
        if (lvl == level.Error)
            color = Red;
        if (lvl == level.Warning)
            color = darkYellow;
        if (cls != "") {
            // DatabaseConnection
            // WebSocketServerClient
            let dts = dt.getHours() + ":" + dt.getMinutes() + ":" + dt.getSeconds() + "." + dt.getMilliseconds();
            if (Logger.usecolors) {
                prefix = (dts.padEnd(13, " ") + "[" + cls.padEnd(21) + "][" + func + "] ");
                let spaces = 0;
                if (prefix.length < 60)
                    spaces = 60 - prefix.length;
                prefix = Green +
                    dts.padEnd(13, " ") + White + "[" + darkYellow + cls.padEnd(21) + White + "][" + darkYellow + func + White + "] ";
                if (spaces > 0)
                    prefix += "".padEnd(spaces, " ");
            }
            else {
                prefix = (dts.padEnd(13, " ") + "[" + cls.padEnd(21) + "][" + func + "] ").padEnd(60, " ");
            }
        }
        if (Logger.usecolors) {
            return prefix + color + message + Console.Reset;
        }
        return prefix + message;
    }
    error(cls, func, message) {
        if (Config_1.Config.unittesting)
            return;
        if (Logger.enabled[cls]) {
            if (Logger.enabled[cls] < level.Error)
                return;
        }
        if (message instanceof Error) {
            console.error(message);
            return;
        }
        if (Logger.log_with_trace)
            return console.trace(this.prefix(level.Error, cls, func, message));
        console.error(this.prefix(level.Error, cls, func, message));
    }
    info(cls, func, message) {
        if (Config_1.Config.unittesting)
            return;
        if (!Config_1.Config.log_information) {
            if (!Logger.enabled[cls])
                return;
            if (Logger.enabled[cls] < level.Information)
                return;
        }
        if (Logger.log_with_trace)
            return console.trace(this.prefix(level.Information, cls, func, message));
        console.info(this.prefix(level.Information, cls, func, message));
    }
    warn(cls, func, message) {
        if (Config_1.Config.unittesting)
            return;
        // if (!Logger.enabled[cls]) return;
        // if (Logger.enabled[cls] < level.Warning) return;
        // if (Logger.log_with_trace) return console.trace(this.prefix(cls, func, message));
        console.warn(this.prefix(level.Warning, cls, func, message));
    }
    debug(cls, func, message) {
        if (Config_1.Config.unittesting)
            return;
        if (!Config_1.Config.log_debug) {
            if (!Logger.enabled[cls])
                return;
            if (Logger.enabled[cls] < level.Debug)
                return;
        }
        if (Logger.log_with_trace)
            return console.trace(this.prefix(level.Debug, cls, func, message));
        console.debug(this.prefix(level.Debug, cls, func, message));
    }
    verbose(cls, func, message) {
        if (Config_1.Config.unittesting)
            return;
        if (!Config_1.Config.log_verbose) {
            if (!Logger.enabled[cls])
                return;
            if (Logger.enabled[cls] < level.Verbose)
                return;
        }
        if (Logger.log_with_trace)
            return console.trace(this.prefix(level.Verbose, cls, func, message));
        console.debug(this.prefix(level.Verbose, cls, func, message));
    }
    silly(cls, func, message) {
        if (Config_1.Config.unittesting)
            return;
        if (!Config_1.Config.log_silly) {
            if (!Logger.enabled[cls])
                return;
            if (Logger.enabled[cls] < level.Silly)
                return;
        }
        if (Logger.log_with_trace)
            return console.trace(this.prefix(level.Silly, cls, func, message));
        console.debug(this.prefix(level.Silly, cls, func, message));
    }
    static async shutdown() {
        Logger.License.shutdown();
        if (Config_1.Config.db != null)
            await Config_1.Config.db.shutdown();
        await Logger.otel.shutdown();
    }
    static configure(skipotel, skiplic) {
        Logger.DBHelper = new DBHelper_1.DBHelper();
        Logger.log_with_trace = Config_1.Config.log_with_trace;
        Logger.usecolors = Config_1.Config.log_with_colors;
        // if (Config.NODE_ENV == "development") Logger.log_with_trace = true;
        if (Config_1.Config.log_cache)
            Logger.enabled["DBHelper"] = level.Verbose;
        if (Config_1.Config.log_amqp)
            Logger.enabled["amqpwrapper"] = level.Verbose;
        if (Config_1.Config.log_login_provider)
            Logger.enabled["LoginProvider"] = level.Verbose;
        if (Config_1.Config.log_websocket)
            Logger.enabled["WebSocketServer"] = level.Verbose;
        if (Config_1.Config.log_websocket)
            Logger.enabled["WebSocketServerClient"] = level.Verbose;
        if (Config_1.Config.log_oauth)
            Logger.enabled["OAuthProvider"] = level.Verbose;
        if (Config_1.Config.log_webserver)
            Logger.enabled["WebServer"] = level.Verbose;
        if (Config_1.Config.log_database)
            Logger.enabled["DatabaseConnection"] = level.Verbose;
        if (Config_1.Config.log_grafana)
            Logger.enabled["grafana-proxy"] = level.Verbose;
        if (Config_1.Config.log_housekeeping)
            Logger.enabled["Housekeeping"] = level.Verbose;
        if (Config_1.Config.log_otel)
            Logger.enabled["otel"] = level.Verbose;
        if (Config_1.Config.otel_debug_log)
            Logger.enabled["WebSocketServerClient"] = level.Verbose;
        if (Config_1.Config.otel_warn_log)
            Logger.enabled["WebSocketServerClient"] = level.Warning;
        if (Config_1.Config.otel_err_log)
            Logger.enabled["WebSocketServerClient"] = level.Error;
        const filename = path.join(Config_1.Config.logpath, "openflow.log");
        const options = {
            file: {
                level: "debug",
                filename: filename,
                handleExceptions: false,
                json: true,
                maxsize: 5242880,
                maxFiles: 5,
                colorize: false,
            },
            console: {
                level: "debug",
                handleExceptions: false,
                json: false,
                colorize: true
            },
        };
        Logger.instanse = new Logger();
        let _lic_require = null;
        try {
            if (!skiplic)
                _lic_require = require("./ee/license-file");
        }
        catch (error) {
        }
        if (_lic_require != null) {
            Logger.License = new _lic_require.LicenseFile();
        }
        else {
            Logger.License = {};
            Logger.License.ofid = Logger.ofid;
            Logger.License.shutdown = () => undefined;
        }
        this.nodereddriver = null;
        if (!openflow_api_1.NoderedUtil.isKubernetes() && openflow_api_1.NoderedUtil.isDocker()) {
            if (openflow_api_1.NoderedUtil.IsNullEmpty(process.env["KUBERNETES_SERVICE_HOST"])) {
                try {
                    this.nodereddriver = new dockerdriver_1.dockerdriver();
                    if (!this.nodereddriver.detect()) {
                        this.nodereddriver = null;
                    }
                }
                catch (error) {
                    this.nodereddriver = null;
                    Logger.instanse.error("Logger", "configure", error);
                }
            }
        }
        if (this.nodereddriver == null) {
            let _driver = null;
            try {
                _driver = require("./ee/kubedriver");
            }
            catch (error) {
            }
            try {
                if (_driver != null) {
                    this.nodereddriver = new _driver.kubedriver();
                }
                else {
                    this.nodereddriver = new dockerdriver_1.dockerdriver();
                }
                if (!this.nodereddriver.detect()) {
                    this.nodereddriver = null;
                }
            }
            catch (error) {
                this.nodereddriver = null;
                Logger.instanse.error("Logger", "configure", error);
            }
        }
        let _otel_require = null;
        try {
            if (!skipotel)
                _otel_require = require("./ee/otel");
        }
        catch (error) {
        }
        if (_otel_require != null) {
            Logger.otel = _otel_require.otel.configure();
        }
        else {
            const fakespan = {
                context: () => undefined,
                setAttribute: () => undefined,
                setAttributes: () => undefined,
                addEvent: () => undefined,
                setStatus: () => undefined,
                updateName: () => undefined,
                end: () => undefined,
                isRecording: () => undefined,
                recordException: () => undefined,
            };
            Logger.otel =
                {
                    startSpan: () => fakespan,
                    startSubSpan: () => fakespan,
                    endSpan: () => undefined,
                    startTimer: () => undefined,
                    endTimer: () => undefined,
                    setdefaultlabels: () => undefined,
                    shutdown: () => undefined,
                    meter: {
                        createHistogram: () => undefined,
                        createCounter: () => undefined,
                        createObservableUpDownCounter: () => undefined,
                        createValueObserver: () => undefined,
                        createObservableGauge: () => undefined,
                    }
                };
        }
    }
    static ofid() {
        if (!openflow_api_1.NoderedUtil.IsNullEmpty(Logger._ofid))
            return Logger._ofid;
        var crypto = require('crypto');
        const openflow_uniqueid = Config_1.Config.openflow_uniqueid || crypto.createHash('md5').update(Config_1.Config.domain).digest("hex");
        Config_1.Config.openflow_uniqueid = openflow_uniqueid;
        Logger._ofid = openflow_uniqueid;
        return openflow_uniqueid;
    }
    static getStackInfo(stackIndex) {
        // get call stack, and analyze it
        // get all file, method, and line numbers
        var stacklist = (new Error()).stack.split('\n').slice(3);
        // stack trace format:
        // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
        // do not remove the regex expresses to outside of this method (due to a BUG in node.js)
        var stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/gi;
        var stackReg2 = /at\s+()(.*):(\d*):(\d*)/gi;
        var s = stacklist[stackIndex] || stacklist[0];
        var sp = stackReg.exec(s) || stackReg2.exec(s);
        if (sp && sp.length === 5) {
            return {
                method: sp[1],
                relativePath: path.relative(__dirname, sp[2]),
                line: sp[3],
                pos: sp[4],
                file: path.basename(sp[2]),
                stack: stacklist.join('\n')
            };
        }
    }
}
exports.Logger = Logger;
Logger.log_with_trace = false;
Logger.enabled = {};
Logger.usecolors = true;
Logger.instanse = null;
Logger._ofid = null;
var Console;
(function (Console) {
    Console["Reset"] = "\u001B[0m";
    Console["Bright"] = "\u001B[1m";
    Console["Dim"] = "\u001B[2m";
    Console["Underscore"] = "\u001B[4m";
    Console["Blink"] = "\u001B[5m";
    Console["Reverse"] = "\u001B[7m";
    Console["Hidden"] = "\u001B[8m";
    Console["FgBlack"] = "\u001B[30m";
    Console["FgRed"] = "\u001B[31m";
    Console["FgGreen"] = "\u001B[32m";
    Console["FgYellow"] = "\u001B[33m";
    Console["FgBlue"] = "\u001B[34m";
    Console["FgMagenta"] = "\u001B[35m";
    Console["FgCyan"] = "\u001B[36m";
    Console["FgWhite"] = "\u001B[37m";
    Console["BgBlack"] = "\u001B[40m";
    Console["BgRed"] = "\u001B[41m";
    Console["BgGreen"] = "\u001B[42m";
    Console["BgYellow"] = "\u001B[43m";
    Console["BgBlue"] = "\u001B[44m";
    Console["BgMagenta"] = "\u001B[45m";
    Console["BgCyan"] = "\u001B[46m";
    Console["BgWhite"] = "\u001B[47m";
})(Console = exports.Console || (exports.Console = {}));
//# sourceMappingURL=Logger.js.map