"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.LogItem = exports.LogItemLevel = void 0;
const CartoApp_1 = require("../app/CartoApp");
const AppServiceProxy_1 = require("./AppServiceProxy");
const Utilities_1 = require("./Utilities");
const ste_events_1 = require("ste-events");
var LogItemLevel;
(function (LogItemLevel) {
    LogItemLevel[LogItemLevel["debug"] = 0] = "debug";
    LogItemLevel[LogItemLevel["verbose"] = 1] = "verbose";
    LogItemLevel[LogItemLevel["message"] = 2] = "message";
    LogItemLevel[LogItemLevel["error"] = 3] = "error";
    LogItemLevel[LogItemLevel["important"] = 4] = "important";
    LogItemLevel[LogItemLevel["operationStarted"] = 10] = "operationStarted";
    LogItemLevel[LogItemLevel["operationEnded"] = 11] = "operationEnded";
})(LogItemLevel = exports.LogItemLevel || (exports.LogItemLevel = {}));
class LogItem {
    level;
    message;
    created;
    operId;
    category;
    context;
    static alertFunction;
    constructor(message, level, context, category) {
        this.level = level;
        this.message = message;
        this.created = new Date();
        this.context = context;
        this.category = category;
        if (this.level === LogItemLevel.operationStarted) {
            this.operId = Log.items.length;
        }
    }
}
exports.LogItem = LogItem;
class Log {
    static _suppressedLogs = {};
    static _log = [];
    static _onItemAdded = new ste_events_1.EventDispatcher();
    static get items() {
        return Log._log;
    }
    static get onItemAdded() {
        return this._onItemAdded.asEvent();
    }
    static message(message, context, category) {
        this.log(message, LogItemLevel.message, context, category);
    }
    static important(message, context, category) {
        this.log(message, LogItemLevel.important, context, category);
    }
    static verbose(message, context, category) {
        this.log(message, LogItemLevel.verbose, context, category);
    }
    static error(message, context, category) {
        this.log(message, LogItemLevel.error, context, category);
    }
    static unexpectedUndefined(token) {
        Log.fail("Unexpected undefined condition found." + (token ? " (" + token + ")" : ""));
    }
    static unexpectedIsDisposed(token) {
        Log.fail("Unexpected usage of a disposed object." + (token ? " (" + token + ")" : ""));
    }
    static throwIsDisposed(token) {
        this.unexpectedIsDisposed(token);
        throw new Error("Unexpected usage of a disposed object." + (token ? " (" + token + ")" : ""));
    }
    static throwUnexpectedUndefined(token) {
        this.unexpectedUndefined(token);
        throw new Error("Unexpected undefined condition found." + (token ? " (" + token + ")" : ""));
    }
    static unexpectedNull(token) {
        Log.fail("Unexpected null condition found." + (token ? " (" + token + ")" : ""));
    }
    static unexpectedContentState(token) {
        Log.fail("Unexpected state of content." + (token ? " (" + token + ")" : ""));
    }
    static unexpectedState(token) {
        Log.fail("Unexpected state of internal variables." + (token ? " (" + token + ")" : ""));
    }
    static unexpectedArguments(token) {
        Log.fail("Unexpected arguments found." + (token ? " (" + token + ")" : ""));
    }
    static log(message, level, context, category) {
        const logItem = new LogItem(message, level, context, category);
        this._log.push(logItem);
        Log._onItemAdded.dispatch(this, logItem);
        return logItem.operId;
    }
    static debug(message, context) {
        this.log(message, LogItemLevel.debug, context);
    }
    static assertIsInt(number, message) {
        if (number !== Math.round(number)) {
            Log.debugAlert("Unexpectedly found number " + number + " is not an integer. " + (message ? message : ""));
        }
    }
    static assert(condition, message, context) {
        if (!condition) {
            if (!message) {
                Log.debugAlert("Assertion failed.", context);
            }
            else {
                Log.debugAlert("Assertion failed: " + message, context);
            }
        }
    }
    static assertDefined(obj, message) {
        if (!obj) {
            Log.unexpectedUndefined("LAD." + (message ? message : ""));
            debugger;
        }
        return obj !== undefined && obj !== null;
    }
    static fail(message, context) {
        Log.debugAlert("Failure case: " + message, context);
    }
    static unsupportedToken(token, context) {
        if (Utilities_1.default.isDebug) {
            Log.debugAlert("Unsupported token: " + token, context);
        }
    }
    static unexpectedError(errorMessage, context) {
        if (Utilities_1.default.isDebug) {
            Log.debugAlert(errorMessage, context);
        }
        throw new Error(errorMessage);
    }
    static debugAlert(message, context) {
        if (Log._suppressedLogs["all"] === true) {
            return;
        }
        Log.debug(message, context);
        if (!Utilities_1.default.isDebug) {
            return;
        }
        let stack = "";
        let header = "";
        const err = new Error();
        if (err.stack !== undefined) {
            stack = err.stack;
        }
        let i = stack.lastIndexOf("at Function.");
        if (i >= 0) {
            i = stack.indexOf("at ", i + 1);
            if (i >= 4) {
                // i -= 4;
                stack = stack.substring(i, stack.length);
                const nextSpace = stack.indexOf(" ", 8);
                if (nextSpace >= 0) {
                    header = "=== " + stack.substring(7, nextSpace) + " ===\r\n\r\n";
                }
            }
        }
        const wholeMessage = header + message + "\r\n" + stack;
        if (LogItem.alertFunction) {
            let stackTrim = stack;
            if (stackTrim.length > 80) {
                stackTrim = stackTrim.substring(0, 80);
            }
            LogItem.alertFunction(message + "\r\n\r\n" + stackTrim);
            // debugger;
            return;
        }
        else if (AppServiceProxy_1.default.hasAppService && CartoApp_1.default.isWeb) {
            // @ts-ignore
            alert(header + message + "\r\n\r\n" + stack);
            debugger;
            return;
            // @ts-ignore
        }
        else if (typeof window === "undefined") {
            console.log(header + message + "\r\n\r\n" + stack);
            return;
        }
        // @ts-ignore
        const val = prompt(wholeMessage, "b to break, s to suppress, a to suppress all");
        if (val === "s") {
            Log._suppressedLogs[message] = true;
            return;
        }
        else if (val === "b") {
            debugger;
        }
        else if (val === "a") {
            Log._suppressedLogs["all"] = true;
        }
    }
}
exports.default = Log;

//# sourceMappingURL=../maps/core/Log.js.map
