/*
 * Application Insights JavaScript SDK - Core, 2.8.15
 * Copyright (c) Microsoft and contributors. All rights reserved.
 */


"use strict";
import dynamicProto from "@microsoft/dynamicproto-js";
import { _DYN_DIAG_LOG, _DYN_ENABLE_DEBUG_EXCEPTI4, _DYN_LOGGER, _DYN_LOG_INTERNAL_MESSAGE, _DYN_MESSAGE, _DYN_MESSAGE_ID, _DYN_PUSH, _DYN_REPLACE } from "../__DynamicConstants";
import { getDebugExt } from "./DbgExtensionUtils";
import { dumpObj, getConsole, getJSON, hasJSON } from "./EnvUtils";
import { getCfgValue, isFunction, isUndefined } from "./HelperFuncs";
import { STR_EMPTY, STR_ERROR_TO_CONSOLE, STR_WARN_TO_CONSOLE } from "./InternalConstants";
/**
 * For user non actionable traces use AI Internal prefix.
 */
var AiNonUserActionablePrefix = "AI (Internal): ";
/**
 * Prefix of the traces in portal.
 */
var AiUserActionablePrefix = "AI: ";
/**
 *  Session storage key for the prefix for the key indicating message type already logged
 */
var AIInternalMessagePrefix = "AITR_";
function _sanitizeDiagnosticText(text) {
    if (text) {
        return "\"" + text[_DYN_REPLACE /* @min:%2ereplace */](/\"/g, STR_EMPTY) + "\"";
    }
    return STR_EMPTY;
}
function _logToConsole(func, message) {
    var theConsole = getConsole();
    if (!!theConsole) {
        var logFunc = "log";
        if (theConsole[func]) {
            logFunc = func;
        }
        if (isFunction(theConsole[logFunc])) {
            theConsole[logFunc](message);
        }
    }
}
var _InternalLogMessage = /** @class */ (function () {
    function _InternalLogMessage(msgId, msg, isUserAct, properties) {
        if (isUserAct === void 0) { isUserAct = false; }
        var _self = this;
        _self[_DYN_MESSAGE_ID /* @min:%2emessageId */] = msgId;
        _self[_DYN_MESSAGE /* @min:%2emessage */] =
            (isUserAct ? AiUserActionablePrefix : AiNonUserActionablePrefix) +
                msgId;
        var strProps = STR_EMPTY;
        if (hasJSON()) {
            strProps = getJSON().stringify(properties);
        }
        var diagnosticText = (msg ? " message:" + _sanitizeDiagnosticText(msg) : STR_EMPTY) +
            (properties ? " props:" + _sanitizeDiagnosticText(strProps) : STR_EMPTY);
        _self[_DYN_MESSAGE /* @min:%2emessage */] += diagnosticText;
    }
    _InternalLogMessage.dataType = "MessageData";
    return _InternalLogMessage;
}());
export { _InternalLogMessage };
export function safeGetLogger(core, config) {
    return (core || {})[_DYN_LOGGER /* @min:%2elogger */] || new DiagnosticLogger(config);
}
var DiagnosticLogger = /** @class */ (function () {
    function DiagnosticLogger(config) {
        this.identifier = "DiagnosticLogger";
        /**
         * The internal logging queue
         */
        this.queue = [];
        /**
         * Count of internal messages sent
         */
        var _messageCount = 0;
        /**
         * Holds information about what message types were already logged to console or sent to server.
         */
        var _messageLogged = {};
        var _loggingLevelConsole;
        var _loggingLevelTelemetry;
        var _maxInternalMessageLimit;
        var _enableDebug;
        dynamicProto(DiagnosticLogger, this, function (_self) {
            _setDefaultsFromConfig(config || {});
            _self.consoleLoggingLevel = function () { return _loggingLevelConsole; };
            _self.telemetryLoggingLevel = function () { return _loggingLevelTelemetry; };
            _self.maxInternalMessageLimit = function () { return _maxInternalMessageLimit; };
            _self[_DYN_ENABLE_DEBUG_EXCEPTI4 /* @min:%2eenableDebugExceptions */] = function () { return _enableDebug; };
            /**
             * This method will throw exceptions in debug mode or attempt to log the error as a console warning.
             * @param severity {LoggingSeverity} - The severity of the log message
             * @param message {_InternalLogMessage} - The log message.
             */
            _self.throwInternal = function (severity, msgId, msg, properties, isUserAct) {
                if (isUserAct === void 0) { isUserAct = false; }
                var message = new _InternalLogMessage(msgId, msg, isUserAct, properties);
                if (_enableDebug) {
                    throw dumpObj(message);
                }
                else {
                    // Get the logging function and fallback to warnToConsole of for some reason errorToConsole doesn't exist
                    var logFunc = severity === 1 /* eLoggingSeverity.CRITICAL */ ? STR_ERROR_TO_CONSOLE : STR_WARN_TO_CONSOLE;
                    if (!isUndefined(message[_DYN_MESSAGE /* @min:%2emessage */])) {
                        if (isUserAct) {
                            // check if this message type was already logged to console for this page view and if so, don't log it again
                            var messageKey = +message[_DYN_MESSAGE_ID /* @min:%2emessageId */];
                            if (!_messageLogged[messageKey] && _loggingLevelConsole >= severity) {
                                _self[logFunc](message[_DYN_MESSAGE /* @min:%2emessage */]);
                                _messageLogged[messageKey] = true;
                            }
                        }
                        else {
                            // Only log traces if the console Logging Level is >= the throwInternal severity level
                            if (_loggingLevelConsole >= severity) {
                                _self[logFunc](message[_DYN_MESSAGE /* @min:%2emessage */]);
                            }
                        }
                        _logInternalMessage(severity, message);
                    }
                    else {
                        _debugExtMsg("throw" + (severity === 1 /* eLoggingSeverity.CRITICAL */ ? "Critical" : "Warning"), message);
                    }
                }
            };
            /**
             * This will write a warning to the console if possible
             * @param message {string} - The warning message
             */
            _self[STR_WARN_TO_CONSOLE /* @min:%2ewarnToConsole */] = function (message) {
                _logToConsole("warn", message);
                _debugExtMsg("warning", message);
            };
            /**
             * This will write an error to the console if possible
             * @param message {string} - The error message
             */
            _self[STR_ERROR_TO_CONSOLE /* @min:%2eerrorToConsole */] = function (message) {
                _logToConsole("error", message);
                _debugExtMsg("error", message);
            };
            /**
             * Resets the internal message count
             */
            _self.resetInternalMessageCount = function () {
                _messageCount = 0;
                _messageLogged = {};
            };
            /**
             * Logs a message to the internal queue.
             * @param severity {LoggingSeverity} - The severity of the log message
             * @param message {_InternalLogMessage} - The message to log.
             */
            _self[_DYN_LOG_INTERNAL_MESSAGE /* @min:%2elogInternalMessage */] = _logInternalMessage;
            function _logInternalMessage(severity, message) {
                if (_areInternalMessagesThrottled()) {
                    return;
                }
                // check if this message type was already logged for this session and if so, don't log it again
                var logMessage = true;
                var messageKey = AIInternalMessagePrefix + message[_DYN_MESSAGE_ID /* @min:%2emessageId */];
                // if the session storage is not available, limit to only one message type per page view
                if (_messageLogged[messageKey]) {
                    logMessage = false;
                }
                else {
                    _messageLogged[messageKey] = true;
                }
                if (logMessage) {
                    // Push the event in the internal queue
                    if (severity <= _loggingLevelTelemetry) {
                        _self.queue[_DYN_PUSH /* @min:%2epush */](message);
                        _messageCount++;
                        _debugExtMsg((severity === 1 /* eLoggingSeverity.CRITICAL */ ? "error" : "warn"), message);
                    }
                    // When throttle limit reached, send a special event
                    if (_messageCount === _maxInternalMessageLimit) {
                        var throttleLimitMessage = "Internal events throttle limit per PageView reached for this app.";
                        var throttleMessage = new _InternalLogMessage(23 /* _eInternalMessageId.MessageLimitPerPVExceeded */, throttleLimitMessage, false);
                        _self.queue[_DYN_PUSH /* @min:%2epush */](throttleMessage);
                        if (severity === 1 /* eLoggingSeverity.CRITICAL */) {
                            _self[STR_ERROR_TO_CONSOLE /* @min:%2eerrorToConsole */](throttleLimitMessage);
                        }
                        else {
                            _self[STR_WARN_TO_CONSOLE /* @min:%2ewarnToConsole */](throttleLimitMessage);
                        }
                    }
                }
            }
            function _setDefaultsFromConfig(config) {
                _loggingLevelConsole = getCfgValue(config.loggingLevelConsole, 0);
                _loggingLevelTelemetry = getCfgValue(config.loggingLevelTelemetry, 1);
                _maxInternalMessageLimit = getCfgValue(config.maxMessageLimit, 25);
                _enableDebug = getCfgValue(config.enableDebug, getCfgValue(config[_DYN_ENABLE_DEBUG_EXCEPTI4 /* @min:%2eenableDebugExceptions */], false));
            }
            function _areInternalMessagesThrottled() {
                return _messageCount >= _maxInternalMessageLimit;
            }
            function _debugExtMsg(name, data) {
                var dbgExt = getDebugExt(config || {});
                if (dbgExt && dbgExt[_DYN_DIAG_LOG /* @min:%2ediagLog */]) {
                    dbgExt[_DYN_DIAG_LOG /* @min:%2ediagLog */](name, data);
                }
            }
        });
    }
// Removed Stub for DiagnosticLogger.prototype.enableDebugExceptions.
// Removed Stub for DiagnosticLogger.prototype.consoleLoggingLevel.
// Removed Stub for DiagnosticLogger.prototype.telemetryLoggingLevel.
// Removed Stub for DiagnosticLogger.prototype.maxInternalMessageLimit.
// Removed Stub for DiagnosticLogger.prototype.throwInternal.
// Removed Stub for DiagnosticLogger.prototype.warnToConsole.
// Removed Stub for DiagnosticLogger.prototype.errorToConsole.
// Removed Stub for DiagnosticLogger.prototype.resetInternalMessageCount.
// Removed Stub for DiagnosticLogger.prototype.logInternalMessage.
    // This is a workaround for an IE8 bug when using dynamicProto() with classes that don't have any
    // non-dynamic functions or static properties/functions when using uglify-js to minify the resulting code.
    // this will be removed when ES3 support is dropped.
    DiagnosticLogger.__ieDyn=1;

    return DiagnosticLogger;
}());
export { DiagnosticLogger };
function _getLogger(logger) {
    return (logger || new DiagnosticLogger());
}
/**
 * This is a helper method which will call throwInternal on the passed logger, will throw exceptions in
 * debug mode or attempt to log the error as a console warning. This helper is provided mostly to better
 * support minification as logger.throwInternal() will not compress the publish "throwInternal" used throughout
 * the code.
 * @param logger - The Diagnostic Logger instance to use.
 * @param severity {LoggingSeverity} - The severity of the log message
 * @param message {_InternalLogMessage} - The log message.
 */
export function _throwInternal(logger, severity, msgId, msg, properties, isUserAct) {
    if (isUserAct === void 0) { isUserAct = false; }
    _getLogger(logger).throwInternal(severity, msgId, msg, properties, isUserAct);
}
/**
 * This is a helper method which will call warnToConsole on the passed logger with the provided message.
 * @param logger - The Diagnostic Logger instance to use.
 * @param message {_InternalLogMessage} - The log message.
 */
export function _warnToConsole(logger, message) {
    _getLogger(logger)[STR_WARN_TO_CONSOLE /* @min:%2ewarnToConsole */](message);
}
/**
 * Logs a message to the internal queue.
 * @param logger - The Diagnostic Logger instance to use.
 * @param severity {LoggingSeverity} - The severity of the log message
 * @param message {_InternalLogMessage} - The message to log.
 */
export function _logInternalMessage(logger, severity, message) {
    _getLogger(logger)[_DYN_LOG_INTERNAL_MESSAGE /* @min:%2elogInternalMessage */](severity, message);
}
