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


"use strict";
var _a;
import { __spreadArrayFn as __spreadArray } from "@microsoft/applicationinsights-shims";
import dynamicProto from "@microsoft/dynamicproto-js";
import { createPromise } from "@nevware21/ts-async";
import { arrAppend, arrForEach, arrIndexOf, createTimeout, deepExtend, hasDocument, isFunction, isNullOrUndefined, isPlainObject, objDeepFreeze, objDefine, objForEachKey, objFreeze, objHasOwn, scheduleTimeout, throwError } from "@nevware21/ts-utils";
import { createDynamicConfig, onConfigChange } from "../Config/DynamicConfig";
import { _DYN_ADD_NOTIFICATION_LIS1, _DYN_CANCEL, _DYN_CREATE_NEW, _DYN_ENABLED, _DYN_GET_NOTIFY_MGR, _DYN_GET_PLUGIN, _DYN_GET_PROCESS_TEL_CONT2, _DYN_IDENTIFIER, _DYN_INITIALIZE, _DYN_IS_ASYNC, _DYN_IS_INITIALIZED, _DYN_LENGTH, _DYN_LOGGER, _DYN_LOGGING_LEVEL_CONSOL4, _DYN_MESSAGE, _DYN_MESSAGE_ID, _DYN_NAME, _DYN_NOTIFY, _DYN_ON_COMPLETE, _DYN_POLL_INTERNAL_LOGS, _DYN_PROCESS_NEXT, _DYN_PUSH, _DYN_REMOVE_NOTIFICATION_0, _DYN_SET_DF, _DYN_SPLICE, _DYN_STOP_POLLING_INTERNA3, _DYN_TEARDOWN, _DYN_TIME, _DYN_UNLOAD, _DYN_VERSION, _DYN_WATCH } from "../__DynamicConstants";
import { doUnloadAll, runTargetUnload } from "./AsyncUtils";
import { ChannelControllerPriority } from "./Constants";
import { createCookieMgr } from "./CookieMgr";
import { createUniqueNamespace } from "./DataCacheHelper";
import { getDebugListener } from "./DbgExtensionUtils";
import { DiagnosticLogger, _InternalLogMessage, _throwInternal, _warnToConsole } from "./DiagnosticLogger";
import { getSetValue, proxyFunctionAs, proxyFunctions, toISOString } from "./HelperFuncs";
import { STR_CHANNELS, STR_CORE, STR_CREATE_PERF_MGR, STR_DISABLED, STR_EMPTY, STR_EVENTS_DISCARDED, STR_EXTENSIONS, STR_EXTENSION_CONFIG, STR_GET_PERF_MGR, STR_PRIORITY, UNDEFINED_VALUE } from "./InternalConstants";
import { NotificationManager } from "./NotificationManager";
import { PerfManager, doPerf, getGblPerfMgr } from "./PerfManager";
import { createProcessTelemetryContext, createProcessTelemetryUnloadContext, createProcessTelemetryUpdateContext, createTelemetryProxyChain } from "./ProcessTelemetryContext";
import { _getPluginState, createDistributedTraceContext, initializePlugins, sortPlugins } from "./TelemetryHelpers";
import { TelemetryInitializerPlugin } from "./TelemetryInitializerPlugin";
import { createUnloadHandlerContainer } from "./UnloadHandlerContainer";
import { createUnloadHookContainer } from "./UnloadHookContainer";
var strValidationError = "Plugins must provide initialize method";
var strNotificationManager = "_notificationManager";
var strSdkUnloadingError = "SDK is still unloading...";
var strSdkNotInitialized = "SDK is not initialized";
// const strPluginUnloadFailed = "Failed to unload plugin";
/**
 * The default settings for the config.
 * WE MUST include all defaults here to ensure that the config is created with all of the properties
 * defined as dynamic.
 */
var defaultConfig = objDeepFreeze((_a = {
        cookieCfg: {}
    },
    _a[STR_EXTENSIONS] = { rdOnly: true, ref: true, v: [] },
    _a[STR_CHANNELS] = { rdOnly: true, ref: true, v: [] },
    _a[STR_EXTENSION_CONFIG] = { ref: true, v: {} },
    _a[STR_CREATE_PERF_MGR] = UNDEFINED_VALUE,
    _a.loggingLevelConsole = 0 /* eLoggingSeverity.DISABLED */,
    _a.diagnosticLogInterval = UNDEFINED_VALUE,
    _a));
/**
 * Helper to create the default performance manager
 * @param core
 * @param notificationMgr
 */
function _createPerfManager(core, notificationMgr) {
    return new PerfManager(notificationMgr);
}
function _validateExtensions(logger, channelPriority, allExtensions) {
    var _a;
    // Concat all available extensions
    var coreExtensions = [];
    var channels = [];
    // Check if any two extensions have the same priority, then warn to console
    // And extract the local extensions from the
    var extPriorities = {};
    // Extension validation
    arrForEach(allExtensions, function (ext) {
        // Check for ext.initialize
        if (isNullOrUndefined(ext) || isNullOrUndefined(ext[_DYN_INITIALIZE /* @min:%2einitialize */])) {
            throwError(strValidationError);
        }
        var extPriority = ext[STR_PRIORITY /* @min:%2epriority */];
        var identifier = ext[_DYN_IDENTIFIER /* @min:%2eidentifier */];
        if (ext && extPriority) {
            if (!isNullOrUndefined(extPriorities[extPriority])) {
                _warnToConsole(logger, "Two extensions have same priority #" + extPriority + " - " + extPriorities[extPriority] + ", " + identifier);
            }
            else {
                // set a value
                extPriorities[extPriority] = identifier;
            }
        }
        // Split extensions to core and channels
        if (!extPriority || extPriority < channelPriority) {
            // Add to core extension that will be managed by AppInsightsCore
            coreExtensions[_DYN_PUSH /* @min:%2epush */](ext);
        }
        else {
            channels[_DYN_PUSH /* @min:%2epush */](ext);
        }
    });
    return _a = {},
        _a[STR_CORE /* @min:core */] = coreExtensions,
        _a[STR_CHANNELS /* @min:channels */] = channels,
        _a;
}
function _isPluginPresent(thePlugin, plugins) {
    var exists = false;
    arrForEach(plugins, function (plugin) {
        if (plugin === thePlugin) {
            exists = true;
            return -1;
        }
    });
    return exists;
}
function _deepMergeConfig(details, target, newValues, merge) {
    // Lets assign the new values to the existing config
    if (newValues) {
        objForEachKey(newValues, function (key, value) {
            if (merge) {
                if (isPlainObject(value) && isPlainObject(target[key])) {
                    // The target is an object and it has a value
                    _deepMergeConfig(details, target[key], value, merge);
                }
            }
            if (merge && isPlainObject(value) && isPlainObject(target[key])) {
                // The target is an object and it has a value
                _deepMergeConfig(details, target[key], value, merge);
            }
            else {
                // Just Assign (replace) and/or make the property dynamic
                details.set(target, key, value);
            }
        });
    }
}
function _findWatcher(listeners, newWatcher) {
    var theListener = null;
    var idx = -1;
    arrForEach(listeners, function (listener, lp) {
        if (listener.w === newWatcher) {
            theListener = listener;
            idx = lp;
            return -1;
        }
    });
    return { i: idx, l: theListener };
}
function _addDelayedCfgListener(listeners, newWatcher) {
    var theListener = _findWatcher(listeners, newWatcher).l;
    if (!theListener) {
        theListener = {
            w: newWatcher,
            rm: function () {
                var fnd = _findWatcher(listeners, newWatcher);
                if (fnd.i !== -1) {
                    listeners[_DYN_SPLICE /* @min:%2esplice */](fnd.i, 1);
                }
            }
        };
        listeners[_DYN_PUSH /* @min:%2epush */](theListener);
    }
    return theListener;
}
function _registerDelayedCfgListener(config, listeners, logger) {
    arrForEach(listeners, function (listener) {
        var unloadHdl = onConfigChange(config, listener.w, logger);
        delete listener.w; // Clear the listener reference so it will get garbage collected.
        // replace the remove function
        listener.rm = function () {
            unloadHdl.rm();
        };
    });
}
// Moved this outside of the closure to reduce the retained memory footprint
function _initDebugListener(configHandler, unloadContainer, notificationManager, debugListener) {
    // Will get recalled if any referenced config values are changed
    unloadContainer.add(configHandler[_DYN_WATCH /* @min:%2ewatch */](function (details) {
        var disableDbgExt = details.cfg.disableDbgExt;
        if (disableDbgExt === true && debugListener) {
            // Remove any previously loaded debug listener
            notificationManager[_DYN_REMOVE_NOTIFICATION_0 /* @min:%2eremoveNotificationListener */](debugListener);
            debugListener = null;
        }
        if (notificationManager && !debugListener && disableDbgExt !== true) {
            debugListener = getDebugListener(details.cfg);
            notificationManager[_DYN_ADD_NOTIFICATION_LIS1 /* @min:%2eaddNotificationListener */](debugListener);
        }
    }));
    return debugListener;
}
// Moved this outside of the closure to reduce the retained memory footprint
function _createUnloadHook(unloadHook) {
    return objDefine({
        rm: function () {
            unloadHook.rm();
        }
    }, "toJSON", { v: function () { return "aicore::onCfgChange<" + JSON.stringify(unloadHook) + ">"; } });
}
/**
 * @group Classes
 * @group Entrypoint
 */
var AppInsightsCore = /** @class */ (function () {
    function AppInsightsCore() {
        // NOTE!: DON'T set default values here, instead set them in the _initDefaults() function as it is also called during teardown()
        var _configHandler;
        var _isInitialized;
        var _logger;
        var _eventQueue;
        var _notificationManager;
        var _perfManager;
        var _cfgPerfManager;
        var _cookieManager;
        var _pluginChain;
        var _configExtensions;
        var _channelConfig;
        var _channels;
        var _isUnloading;
        var _telemetryInitializerPlugin;
        var _internalLogsEventName;
        var _evtNamespace;
        var _unloadHandlers;
        var _hookContainer;
        var _debugListener;
        var _traceCtx;
        var _instrumentationKey;
        var _cfgListeners;
        var _extensions;
        var _pluginVersionStringArr;
        var _pluginVersionString;
        /**
         * Internal log poller
         */
        var _internalLogPoller;
        var _internalLogPollerListening;
        var _forceStopInternalLogPoller;
        dynamicProto(AppInsightsCore, this, function (_self) {
            // Set the default values (also called during teardown)
            _initDefaults();
            // Special internal method to allow the unit tests and DebugPlugin to hook embedded objects
            _self["_getDbgPlgTargets"] = function () {
                return [_extensions];
            };
            _self[_DYN_IS_INITIALIZED /* @min:%2eisInitialized */] = function () { return _isInitialized; };
            // Creating the self.initialize = ()
            _self[_DYN_INITIALIZE /* @min:%2einitialize */] = function (config, extensions, logger, notificationManager) {
                if (_isUnloading) {
                    throwError(strSdkUnloadingError);
                }
                // Make sure core is only initialized once
                if (_self[_DYN_IS_INITIALIZED /* @min:%2eisInitialized */]()) {
                    throwError("Core cannot be initialized more than once");
                }
                _configHandler = createDynamicConfig(config, defaultConfig, logger || _self[_DYN_LOGGER /* @min:%2elogger */], false);
                // Re-assigning the local config property so we don't have any references to the passed value and it can be garbage collected
                config = _configHandler.cfg;
                // This will be "re-run" if the referenced config properties are changed
                _addUnloadHook(_configHandler[_DYN_WATCH /* @min:%2ewatch */](function (details) {
                    _instrumentationKey = details.cfg.instrumentationKey;
                    // Mark the extensionConfig and all first level keys as referenced
                    // This is so that calls to getExtCfg() will always return the same object
                    // Even when a user may "re-assign" the plugin properties (or it's unloaded/reloaded)
                    var extCfg = details.ref(details.cfg, STR_EXTENSION_CONFIG);
                    objForEachKey(extCfg, function (key) {
                        details.ref(extCfg, key);
                    });
                    if (isNullOrUndefined(_instrumentationKey)) {
                        throwError("Please provide instrumentation key");
                    }
                }));
                _notificationManager = notificationManager;
                // Initialize the debug listener outside of the closure to reduce the retained memory footprint
                _debugListener = _initDebugListener(_configHandler, _hookContainer, _notificationManager && _self[_DYN_GET_NOTIFY_MGR /* @min:%2egetNotifyMgr */](), _debugListener);
                _initPerfManager();
                _self[_DYN_LOGGER /* @min:%2elogger */] = logger;
                var cfgExtensions = config[STR_EXTENSIONS /* @min:%2eextensions */];
                // Extension validation
                _configExtensions = [];
                _configExtensions[_DYN_PUSH /* @min:%2epush */].apply(_configExtensions, __spreadArray(__spreadArray([], extensions, false), cfgExtensions, false));
                _channelConfig = config[STR_CHANNELS /* @min:%2echannels */];
                _initPluginChain(null);
                if (!_channels || _channels[_DYN_LENGTH /* @min:%2elength */] === 0) {
                    throwError("No " + STR_CHANNELS + " available");
                }
                if (_channelConfig && _channelConfig[_DYN_LENGTH /* @min:%2elength */] > 1) {
                    var teeController = _self[_DYN_GET_PLUGIN /* @min:%2egetPlugin */]("TeeChannelController");
                    if (!teeController || !teeController.plugin) {
                        _throwInternal(_logger, 1 /* eLoggingSeverity.CRITICAL */, 28 /* _eInternalMessageId.SenderNotInitialized */, "TeeChannel required");
                    }
                }
                _registerDelayedCfgListener(config, _cfgListeners, _logger);
                _cfgListeners = null;
                _isInitialized = true;
                _self.releaseQueue();
                _self[_DYN_POLL_INTERNAL_LOGS /* @min:%2epollInternalLogs */]();
            };
            _self.getChannels = function () {
                var controls = [];
                if (_channels) {
                    arrForEach(_channels, function (channel) {
                        controls[_DYN_PUSH /* @min:%2epush */](channel);
                    });
                }
                return objFreeze(controls);
            };
            _self.track = function (telemetryItem) {
                doPerf(_self[STR_GET_PERF_MGR /* @min:%2egetPerfMgr */](), function () { return "AppInsightsCore:track"; }, function () {
                    if (telemetryItem === null) {
                        _notifyInvalidEvent(telemetryItem);
                        // throw error
                        throwError("Invalid telemetry item");
                    }
                    // do basic validation before sending it through the pipeline
                    if (!telemetryItem[_DYN_NAME /* @min:%2ename */] && isNullOrUndefined(telemetryItem[_DYN_NAME /* @min:%2ename */])) {
                        _notifyInvalidEvent(telemetryItem);
                        throwError("telemetry name required");
                    }
                    // setup default iKey if not passed in
                    telemetryItem.iKey = telemetryItem.iKey || _instrumentationKey;
                    // add default timestamp if not passed in
                    telemetryItem[_DYN_TIME /* @min:%2etime */] = telemetryItem[_DYN_TIME /* @min:%2etime */] || toISOString(new Date());
                    // Common Schema 4.0
                    telemetryItem.ver = telemetryItem.ver || "4.0";
                    if (!_isUnloading && _self[_DYN_IS_INITIALIZED /* @min:%2eisInitialized */]()) {
                        // Process the telemetry plugin chain
                        _createTelCtx()[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](telemetryItem);
                    }
                    else {
                        // Queue events until all extensions are initialized
                        _eventQueue[_DYN_PUSH /* @min:%2epush */](telemetryItem);
                    }
                }, function () { return ({ item: telemetryItem }); }, !(telemetryItem.sync));
            };
            _self[_DYN_GET_PROCESS_TEL_CONT2 /* @min:%2egetProcessTelContext */] = _createTelCtx;
            _self[_DYN_GET_NOTIFY_MGR /* @min:%2egetNotifyMgr */] = function () {
                if (!_notificationManager) {
                    _notificationManager = new NotificationManager(_configHandler.cfg);
                    // For backward compatibility only
                    _self[strNotificationManager] = _notificationManager;
                }
                return _notificationManager;
            };
            /**
             * Adds a notification listener. The SDK calls methods on the listener when an appropriate notification is raised.
             * The added plugins must raise notifications. If the plugins do not implement the notifications, then no methods will be
             * called.
             * @param listener - An INotificationListener object.
             */
            _self[_DYN_ADD_NOTIFICATION_LIS1 /* @min:%2eaddNotificationListener */] = function (listener) {
                _self.getNotifyMgr()[_DYN_ADD_NOTIFICATION_LIS1 /* @min:%2eaddNotificationListener */](listener);
            };
            /**
             * Removes all instances of the listener.
             * @param listener - INotificationListener to remove.
             */
            _self[_DYN_REMOVE_NOTIFICATION_0 /* @min:%2eremoveNotificationListener */] = function (listener) {
                if (_notificationManager) {
                    _notificationManager[_DYN_REMOVE_NOTIFICATION_0 /* @min:%2eremoveNotificationListener */](listener);
                }
            };
            _self.getCookieMgr = function () {
                if (!_cookieManager) {
                    _cookieManager = createCookieMgr(_configHandler.cfg, _self[_DYN_LOGGER /* @min:%2elogger */]);
                }
                return _cookieManager;
            };
            _self.setCookieMgr = function (cookieMgr) {
                if (_cookieManager !== cookieMgr) {
                    runTargetUnload(_cookieManager, false);
                    _cookieManager = cookieMgr;
                }
            };
            _self[STR_GET_PERF_MGR /* @min:%2egetPerfMgr */] = function () {
                return _perfManager || _cfgPerfManager || getGblPerfMgr();
            };
            _self.setPerfMgr = function (perfMgr) {
                _perfManager = perfMgr;
            };
            _self.eventCnt = function () {
                return _eventQueue[_DYN_LENGTH /* @min:%2elength */];
            };
            _self.releaseQueue = function () {
                if (_isInitialized && _eventQueue[_DYN_LENGTH /* @min:%2elength */] > 0) {
                    var eventQueue = _eventQueue;
                    _eventQueue = [];
                    arrForEach(eventQueue, function (event) {
                        _createTelCtx()[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](event);
                    });
                }
            };
            _self[_DYN_POLL_INTERNAL_LOGS /* @min:%2epollInternalLogs */] = function (eventName) {
                _internalLogsEventName = eventName || null;
                _forceStopInternalLogPoller = false;
                _internalLogPoller && _internalLogPoller[_DYN_CANCEL /* @min:%2ecancel */]();
                return _startLogPoller(true);
            };
            function _startLogPoller(alwaysStart) {
                if ((!_internalLogPoller || !_internalLogPoller[_DYN_ENABLED /* @min:%2eenabled */]) && !_forceStopInternalLogPoller) {
                    var shouldStart = alwaysStart || (_logger && _logger.queue[_DYN_LENGTH /* @min:%2elength */] > 0);
                    if (shouldStart) {
                        if (!_internalLogPollerListening) {
                            _internalLogPollerListening = true;
                            // listen for any configuration changes so that changes to the
                            // interval will cause the timer to be re-initialized
                            _addUnloadHook(_configHandler[_DYN_WATCH /* @min:%2ewatch */](function (details) {
                                var interval = details.cfg.diagnosticLogInterval;
                                if (!interval || !(interval > 0)) {
                                    interval = 10000;
                                }
                                var isRunning = false;
                                if (_internalLogPoller) {
                                    // It was already created so remember it's running and cancel
                                    isRunning = _internalLogPoller[_DYN_ENABLED /* @min:%2eenabled */];
                                    _internalLogPoller[_DYN_CANCEL /* @min:%2ecancel */]();
                                }
                                // Create / reconfigure
                                _internalLogPoller = createTimeout(_flushInternalLogs, interval);
                                _internalLogPoller.unref();
                                // Restart if previously running
                                _internalLogPoller[_DYN_ENABLED /* @min:%2eenabled */] = isRunning;
                            }));
                        }
                        _internalLogPoller[_DYN_ENABLED /* @min:%2eenabled */] = true;
                    }
                }
                return _internalLogPoller;
            }
            _self[_DYN_STOP_POLLING_INTERNA3 /* @min:%2estopPollingInternalLogs */] = function () {
                _forceStopInternalLogPoller = true;
                _internalLogPoller && _internalLogPoller[_DYN_CANCEL /* @min:%2ecancel */]();
                _flushInternalLogs();
            };
            // Add addTelemetryInitializer
            proxyFunctions(_self, function () { return _telemetryInitializerPlugin; }, ["addTelemetryInitializer"]);
            _self[_DYN_UNLOAD /* @min:%2eunload */] = function (isAsync, unloadComplete, cbTimeout) {
                var _a;
                if (isAsync === void 0) { isAsync = true; }
                if (!_isInitialized) {
                    // The SDK is not initialized
                    throwError(strSdkNotInitialized);
                }
                // Check if the SDK still unloading so throw
                if (_isUnloading) {
                    // The SDK is already unloading
                    throwError(strSdkUnloadingError);
                }
                var unloadState = (_a = {
                        reason: 50 /* TelemetryUnloadReason.SdkUnload */
                    },
                    _a[_DYN_IS_ASYNC /* @min:isAsync */] = isAsync,
                    _a.flushComplete = false,
                    _a);
                var result;
                if (isAsync && !unloadComplete) {
                    result = createPromise(function (resolve) {
                        // Set the callback to the promise resolve callback
                        unloadComplete = resolve;
                    });
                }
                var processUnloadCtx = createProcessTelemetryUnloadContext(_getPluginChain(), _self);
                processUnloadCtx[_DYN_ON_COMPLETE /* @min:%2eonComplete */](function () {
                    _hookContainer.run(_self[_DYN_LOGGER /* @min:%2elogger */]);
                    // Run any "unload" functions for the _cookieManager, _notificationManager and _logger
                    doUnloadAll([_cookieManager, _notificationManager, _logger], isAsync, function () {
                        _initDefaults();
                        unloadComplete && unloadComplete(unloadState);
                    });
                }, _self);
                function _doUnload(flushComplete) {
                    unloadState.flushComplete = flushComplete;
                    _isUnloading = true;
                    // Run all of the unload handlers first (before unloading the plugins)
                    _unloadHandlers.run(processUnloadCtx, unloadState);
                    // Stop polling the internal logs
                    _self[_DYN_STOP_POLLING_INTERNA3 /* @min:%2estopPollingInternalLogs */]();
                    // Start unloading the components, from this point onwards the SDK should be considered to be in an unstable state
                    processUnloadCtx[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](unloadState);
                }
                _flushInternalLogs();
                if (!_flushChannels(isAsync, _doUnload, 6 /* SendRequestReason.SdkUnload */, cbTimeout)) {
                    _doUnload(false);
                }
                return result;
            };
            _self[_DYN_GET_PLUGIN /* @min:%2egetPlugin */] = _getPlugin;
            _self.addPlugin = function (plugin, replaceExisting, isAsync, addCb) {
                if (!plugin) {
                    addCb && addCb(false);
                    _logOrThrowError(strValidationError);
                    return;
                }
                var existingPlugin = _getPlugin(plugin[_DYN_IDENTIFIER /* @min:%2eidentifier */]);
                if (existingPlugin && !replaceExisting) {
                    addCb && addCb(false);
                    _logOrThrowError("Plugin [" + plugin[_DYN_IDENTIFIER /* @min:%2eidentifier */] + "] is already loaded!");
                    return;
                }
                var updateState = {
                    reason: 16 /* TelemetryUpdateReason.PluginAdded */
                };
                function _addPlugin(removed) {
                    _configExtensions[_DYN_PUSH /* @min:%2epush */](plugin);
                    updateState.added = [plugin];
                    // Re-Initialize the plugin chain
                    _initPluginChain(updateState);
                    addCb && addCb(true);
                }
                if (existingPlugin) {
                    var removedPlugins_1 = [existingPlugin.plugin];
                    var unloadState = {
                        reason: 2 /* TelemetryUnloadReason.PluginReplace */,
                        isAsync: !!isAsync
                    };
                    _removePlugins(removedPlugins_1, unloadState, function (removed) {
                        if (!removed) {
                            // Previous plugin was successfully removed or was not installed
                            addCb && addCb(false);
                        }
                        else {
                            updateState.removed = removedPlugins_1;
                            updateState.reason |= 32 /* TelemetryUpdateReason.PluginRemoved */;
                            _addPlugin(true);
                        }
                    });
                }
                else {
                    _addPlugin(false);
                }
            };
            _self.updateCfg = function (newConfig, mergeExisting) {
                if (mergeExisting === void 0) { mergeExisting = true; }
                var updateState;
                if (_self[_DYN_IS_INITIALIZED /* @min:%2eisInitialized */]()) {
                    updateState = {
                        reason: 1 /* TelemetryUpdateReason.ConfigurationChanged */,
                        cfg: _configHandler.cfg,
                        oldCfg: deepExtend({}, _configHandler.cfg),
                        newConfig: deepExtend({}, newConfig),
                        merge: mergeExisting
                    };
                    newConfig = updateState.newConfig;
                    var cfg = _configHandler.cfg;
                    // replace the immutable (if initialized) values
                    // We don't currently allow updating the extensions and channels via the update config
                    // So overwriting any user provided values to reuse the existing values
                    newConfig[STR_EXTENSIONS /* @min:%2eextensions */] = cfg[STR_EXTENSIONS /* @min:%2eextensions */];
                    newConfig[STR_CHANNELS /* @min:%2echannels */] = cfg[STR_CHANNELS /* @min:%2echannels */];
                }
                // Explicitly blocking any previous config watchers so that they don't get called because
                // of this bulk update (Probably not necessary)
                _configHandler._block(function (details) {
                    // Lets assign the new values to the existing config either overwriting or re-assigning
                    var theConfig = details.cfg;
                    _deepMergeConfig(details, theConfig, newConfig, mergeExisting);
                    if (!mergeExisting) {
                        // Remove (unassign) the values "missing" from the newConfig and also not in the default config
                        objForEachKey(theConfig, function (key) {
                            if (!objHasOwn(newConfig, key)) {
                                // Set the value to undefined
                                details.set(theConfig, key, UNDEFINED_VALUE);
                            }
                        });
                    }
                    // Apply defaults to the new config
                    details[_DYN_SET_DF /* @min:%2esetDf */](theConfig, defaultConfig);
                }, true);
                // Now execute all of the listeners (synchronously) so they update their values immediately
                _configHandler[_DYN_NOTIFY /* @min:%2enotify */]();
                if (updateState) {
                    _doUpdate(updateState);
                }
            };
            _self.evtNamespace = function () {
                return _evtNamespace;
            };
            _self.flush = _flushChannels;
            _self.getTraceCtx = function (createNew) {
                if (!_traceCtx) {
                    _traceCtx = createDistributedTraceContext();
                }
                return _traceCtx;
            };
            _self.setTraceCtx = function (traceCtx) {
                _traceCtx = traceCtx || null;
            };
            _self.addUnloadHook = _addUnloadHook;
            // Create the addUnloadCb
            proxyFunctionAs(_self, "addUnloadCb", function () { return _unloadHandlers; }, "add");
            _self.onCfgChange = function (handler) {
                var unloadHook;
                if (!_isInitialized) {
                    unloadHook = _addDelayedCfgListener(_cfgListeners, handler);
                }
                else {
                    unloadHook = onConfigChange(_configHandler.cfg, handler, _self[_DYN_LOGGER /* @min:%2elogger */]);
                }
                return _createUnloadHook(unloadHook);
            };
            _self.getWParam = function () {
                return (hasDocument() || !!_configHandler.cfg.enableWParam) ? 0 : -1;
            };
            function _setPluginVersions() {
                var thePlugins = {};
                _pluginVersionStringArr = [];
                var _addPluginVersions = function (plugins) {
                    if (plugins) {
                        arrForEach(plugins, function (plugin) {
                            if (plugin[_DYN_IDENTIFIER /* @min:%2eidentifier */] && plugin[_DYN_VERSION /* @min:%2eversion */] && !thePlugins[plugin.identifier]) {
                                var ver = plugin[_DYN_IDENTIFIER /* @min:%2eidentifier */] + "=" + plugin[_DYN_VERSION /* @min:%2eversion */];
                                _pluginVersionStringArr[_DYN_PUSH /* @min:%2epush */](ver);
                                thePlugins[plugin.identifier] = plugin;
                            }
                        });
                    }
                };
                _addPluginVersions(_channels);
                if (_channelConfig) {
                    arrForEach(_channelConfig, function (channels) {
                        _addPluginVersions(channels);
                    });
                }
                _addPluginVersions(_configExtensions);
            }
            function _initDefaults() {
                _isInitialized = false;
                // Use a default logger so initialization errors are not dropped on the floor with full logging
                _configHandler = createDynamicConfig({}, defaultConfig, _self[_DYN_LOGGER /* @min:%2elogger */]);
                // Set the logging level to critical so that any critical initialization failures are displayed on the console
                _configHandler.cfg[_DYN_LOGGING_LEVEL_CONSOL4 /* @min:%2eloggingLevelConsole */] = 1 /* eLoggingSeverity.CRITICAL */;
                // Define _self.config
                objDefine(_self, "config", {
                    g: function () { return _configHandler.cfg; },
                    s: function (newValue) {
                        _self.updateCfg(newValue, false);
                    }
                });
                objDefine(_self, "pluginVersionStringArr", {
                    g: function () {
                        if (!_pluginVersionStringArr) {
                            _setPluginVersions();
                        }
                        return _pluginVersionStringArr;
                    }
                });
                objDefine(_self, "pluginVersionString", {
                    g: function () {
                        if (!_pluginVersionString) {
                            if (!_pluginVersionStringArr) {
                                _setPluginVersions();
                            }
                            _pluginVersionString = _pluginVersionStringArr.join(";");
                        }
                        return _pluginVersionString || STR_EMPTY;
                    }
                });
                objDefine(_self, "logger", {
                    g: function () {
                        if (!_logger) {
                            _logger = new DiagnosticLogger(_configHandler.cfg);
                            _configHandler[_DYN_LOGGER /* @min:%2elogger */] = _logger;
                        }
                        return _logger;
                    },
                    s: function (newLogger) {
                        _configHandler[_DYN_LOGGER /* @min:%2elogger */] = newLogger;
                        if (_logger !== newLogger) {
                            runTargetUnload(_logger, false);
                            _logger = newLogger;
                        }
                    }
                });
                _self[_DYN_LOGGER /* @min:%2elogger */] = new DiagnosticLogger(_configHandler.cfg);
                _extensions = [];
                var cfgExtensions = _self.config[STR_EXTENSIONS /* @min:%2eextensions */] || [];
                cfgExtensions.splice(0, cfgExtensions[_DYN_LENGTH /* @min:%2elength */]);
                arrAppend(cfgExtensions, _extensions);
                _telemetryInitializerPlugin = new TelemetryInitializerPlugin();
                _eventQueue = [];
                runTargetUnload(_notificationManager, false);
                _notificationManager = null;
                _perfManager = null;
                _cfgPerfManager = null;
                runTargetUnload(_cookieManager, false);
                _cookieManager = null;
                _pluginChain = null;
                _configExtensions = [];
                _channelConfig = null;
                _channels = null;
                _isUnloading = false;
                _internalLogsEventName = null;
                _evtNamespace = createUniqueNamespace("AIBaseCore", true);
                _unloadHandlers = createUnloadHandlerContainer();
                _traceCtx = null;
                _instrumentationKey = null;
                _hookContainer = createUnloadHookContainer();
                _cfgListeners = [];
                _pluginVersionString = null;
                _pluginVersionStringArr = null;
                _forceStopInternalLogPoller = false;
                _internalLogPoller = null;
                _internalLogPollerListening = false;
            }
            function _createTelCtx() {
                var theCtx = createProcessTelemetryContext(_getPluginChain(), _configHandler.cfg, _self);
                theCtx[_DYN_ON_COMPLETE /* @min:%2eonComplete */](_startLogPoller);
                return theCtx;
            }
            // Initialize or Re-initialize the plugins
            function _initPluginChain(updateState) {
                // Extension validation
                var theExtensions = _validateExtensions(_self[_DYN_LOGGER /* @min:%2elogger */], ChannelControllerPriority, _configExtensions);
                _pluginChain = null;
                _pluginVersionString = null;
                _pluginVersionStringArr = null;
                // Get the primary channel queue and include as part of the normal extensions
                _channels = (_channelConfig || [])[0] || [];
                // Add any channels provided in the extensions and sort them
                _channels = sortPlugins(arrAppend(_channels, theExtensions[STR_CHANNELS /* @min:%2echannels */]));
                // Create an array of all extensions, including the _channels
                var allExtensions = arrAppend(sortPlugins(theExtensions[STR_CORE /* @min:%2ecore */]), _channels);
                // Required to allow plugins to call core.getPlugin() during their own initialization
                _extensions = objFreeze(allExtensions);
                // This has a side effect of adding the extensions passed during initialization
                // into the config.extensions, so you can see all of the extensions loaded.
                // This will also get updated by the addPlugin() and remove plugin code.
                var cfgExtensions = _self.config[STR_EXTENSIONS /* @min:%2eextensions */] || [];
                cfgExtensions.splice(0, cfgExtensions[_DYN_LENGTH /* @min:%2elength */]);
                arrAppend(cfgExtensions, _extensions);
                var rootCtx = _createTelCtx();
                // Initializing the channels first
                if (_channels && _channels[_DYN_LENGTH /* @min:%2elength */] > 0) {
                    initializePlugins(rootCtx[_DYN_CREATE_NEW /* @min:%2ecreateNew */](_channels), allExtensions);
                }
                // Now initialize the normal extensions (explicitly not including the _channels as this can cause duplicate initialization)
                initializePlugins(rootCtx, allExtensions);
                if (updateState) {
                    _doUpdate(updateState);
                }
            }
            function _getPlugin(pluginIdentifier) {
                var theExt = null;
                var thePlugin = null;
                var channelHosts = [];
                arrForEach(_extensions, function (ext) {
                    if (ext[_DYN_IDENTIFIER /* @min:%2eidentifier */] === pluginIdentifier && ext !== _telemetryInitializerPlugin) {
                        thePlugin = ext;
                        return -1;
                    }
                    if (ext.getChannel) {
                        channelHosts[_DYN_PUSH /* @min:%2epush */](ext);
                    }
                });
                if (!thePlugin && channelHosts[_DYN_LENGTH /* @min:%2elength */] > 0) {
                    arrForEach(channelHosts, function (host) {
                        thePlugin = host.getChannel(pluginIdentifier);
                        if (!thePlugin) {
                            return -1;
                        }
                    });
                }
                if (thePlugin) {
                    theExt = {
                        plugin: thePlugin,
                        setEnabled: function (enabled) {
                            _getPluginState(thePlugin)[STR_DISABLED] = !enabled;
                        },
                        isEnabled: function () {
                            var pluginState = _getPluginState(thePlugin);
                            return !pluginState[_DYN_TEARDOWN /* @min:%2eteardown */] && !pluginState[STR_DISABLED];
                        },
                        remove: function (isAsync, removeCb) {
                            var _a;
                            if (isAsync === void 0) { isAsync = true; }
                            var pluginsToRemove = [thePlugin];
                            var unloadState = (_a = {
                                    reason: 1 /* TelemetryUnloadReason.PluginUnload */
                                },
                                _a[_DYN_IS_ASYNC /* @min:isAsync */] = isAsync,
                                _a);
                            _removePlugins(pluginsToRemove, unloadState, function (removed) {
                                if (removed) {
                                    // Re-Initialize the plugin chain
                                    _initPluginChain({
                                        reason: 32 /* TelemetryUpdateReason.PluginRemoved */,
                                        removed: pluginsToRemove
                                    });
                                }
                                removeCb && removeCb(removed);
                            });
                        }
                    };
                }
                return theExt;
            }
            function _getPluginChain() {
                if (!_pluginChain) {
                    // copy the collection of extensions
                    var extensions = (_extensions || []).slice();
                    // During add / remove this may get called again, so don't read if already present
                    if (arrIndexOf(extensions, _telemetryInitializerPlugin) === -1) {
                        extensions[_DYN_PUSH /* @min:%2epush */](_telemetryInitializerPlugin);
                    }
                    _pluginChain = createTelemetryProxyChain(sortPlugins(extensions), _configHandler.cfg, _self);
                }
                return _pluginChain;
            }
            function _removePlugins(thePlugins, unloadState, removeComplete) {
                if (thePlugins && thePlugins[_DYN_LENGTH /* @min:%2elength */] > 0) {
                    var unloadChain = createTelemetryProxyChain(thePlugins, _configHandler.cfg, _self);
                    var unloadCtx = createProcessTelemetryUnloadContext(unloadChain, _self);
                    unloadCtx[_DYN_ON_COMPLETE /* @min:%2eonComplete */](function () {
                        var removed = false;
                        // Remove the listed config extensions
                        var newConfigExtensions = [];
                        arrForEach(_configExtensions, function (plugin, idx) {
                            if (!_isPluginPresent(plugin, thePlugins)) {
                                newConfigExtensions[_DYN_PUSH /* @min:%2epush */](plugin);
                            }
                            else {
                                removed = true;
                            }
                        });
                        _configExtensions = newConfigExtensions;
                        _pluginVersionString = null;
                        _pluginVersionStringArr = null;
                        // Re-Create the channel config
                        var newChannelConfig = [];
                        if (_channelConfig) {
                            arrForEach(_channelConfig, function (queue, idx) {
                                var newQueue = [];
                                arrForEach(queue, function (channel) {
                                    if (!_isPluginPresent(channel, thePlugins)) {
                                        newQueue[_DYN_PUSH /* @min:%2epush */](channel);
                                    }
                                    else {
                                        removed = true;
                                    }
                                });
                                newChannelConfig[_DYN_PUSH /* @min:%2epush */](newQueue);
                            });
                            _channelConfig = newChannelConfig;
                        }
                        removeComplete && removeComplete(removed);
                        _startLogPoller();
                    });
                    unloadCtx[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](unloadState);
                }
                else {
                    removeComplete(false);
                }
            }
            function _flushInternalLogs() {
                if (_logger && _logger.queue) {
                    var queue = _logger.queue.slice(0);
                    _logger.queue[_DYN_LENGTH /* @min:%2elength */] = 0;
                    arrForEach(queue, function (logMessage) {
                        var _a;
                        var item = (_a = {},
                            _a[_DYN_NAME /* @min:name */] = _internalLogsEventName ? _internalLogsEventName : "InternalMessageId: " + logMessage[_DYN_MESSAGE_ID /* @min:%2emessageId */],
                            _a.iKey = _instrumentationKey,
                            _a[_DYN_TIME /* @min:time */] = toISOString(new Date()),
                            _a.baseType = _InternalLogMessage.dataType,
                            _a.baseData = { message: logMessage[_DYN_MESSAGE /* @min:%2emessage */] },
                            _a);
                        _self.track(item);
                    });
                }
            }
            function _flushChannels(isAsync, callBack, sendReason, cbTimeout) {
                // Setting waiting to one so that we don't call the callBack until we finish iterating
                var waiting = 1;
                var doneIterating = false;
                var cbTimer = null;
                cbTimeout = cbTimeout || 5000;
                function doCallback() {
                    waiting--;
                    if (doneIterating && waiting === 0) {
                        cbTimer && cbTimer[_DYN_CANCEL /* @min:%2ecancel */]();
                        cbTimer = null;
                        callBack && callBack(doneIterating);
                        callBack = null;
                    }
                }
                if (_channels && _channels[_DYN_LENGTH /* @min:%2elength */] > 0) {
                    var flushCtx = _createTelCtx()[_DYN_CREATE_NEW /* @min:%2ecreateNew */](_channels);
                    flushCtx.iterate(function (plugin) {
                        if (plugin.flush) {
                            waiting++;
                            var handled_1 = false;
                            // Not all channels will call this callback for every scenario
                            if (!plugin.flush(isAsync, function () {
                                handled_1 = true;
                                doCallback();
                            }, sendReason)) {
                                if (!handled_1) {
                                    // If any channel doesn't return true and it didn't call the callback, then we should assume that the callback
                                    // will never be called, so use a timeout to allow the channel(s) some time to "finish" before triggering any
                                    // followup function (such as unloading)
                                    if (isAsync && cbTimer == null) {
                                        cbTimer = scheduleTimeout(function () {
                                            cbTimer = null;
                                            doCallback();
                                        }, cbTimeout);
                                    }
                                    else {
                                        doCallback();
                                    }
                                }
                            }
                        }
                    });
                }
                doneIterating = true;
                doCallback();
                return true;
            }
            function _initPerfManager() {
                // Save the previous config based performance manager creator to avoid creating new perf manager instances if unchanged
                var prevCfgPerfMgr;
                // Will get recalled if any referenced config values are changed
                _addUnloadHook(_configHandler[_DYN_WATCH /* @min:%2ewatch */](function (details) {
                    var enablePerfMgr = details.cfg.enablePerfMgr;
                    if (enablePerfMgr) {
                        var createPerfMgr = details.cfg[STR_CREATE_PERF_MGR /* @min:%2ecreatePerfMgr */];
                        if (prevCfgPerfMgr !== createPerfMgr) {
                            if (!createPerfMgr) {
                                createPerfMgr = _createPerfManager;
                            }
                            // Set the performance manager creation function if not defined
                            getSetValue(details.cfg, STR_CREATE_PERF_MGR, createPerfMgr);
                            prevCfgPerfMgr = createPerfMgr;
                            // Remove any existing config based performance manager
                            _cfgPerfManager = null;
                        }
                        // Only create the performance manager if it's not already created or manually set
                        if (!_perfManager && !_cfgPerfManager && isFunction(createPerfMgr)) {
                            // Create a new config based performance manager
                            _cfgPerfManager = createPerfMgr(_self, _self[_DYN_GET_NOTIFY_MGR /* @min:%2egetNotifyMgr */]());
                        }
                    }
                    else {
                        // Remove any existing config based performance manager
                        _cfgPerfManager = null;
                        // Clear the previous cached value so it can be GC'd
                        prevCfgPerfMgr = null;
                    }
                }));
            }
            function _doUpdate(updateState) {
                var updateCtx = createProcessTelemetryUpdateContext(_getPluginChain(), _self);
                updateCtx[_DYN_ON_COMPLETE /* @min:%2eonComplete */](_startLogPoller);
                if (!_self._updateHook || _self._updateHook(updateCtx, updateState) !== true) {
                    updateCtx[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](updateState);
                }
            }
            function _logOrThrowError(message) {
                var logger = _self[_DYN_LOGGER /* @min:%2elogger */];
                if (logger) {
                    // there should always be a logger
                    _throwInternal(logger, 2 /* eLoggingSeverity.WARNING */, 73 /* _eInternalMessageId.PluginException */, message);
                    _startLogPoller();
                }
                else {
                    throwError(message);
                }
            }
            function _notifyInvalidEvent(telemetryItem) {
                var manager = _self[_DYN_GET_NOTIFY_MGR /* @min:%2egetNotifyMgr */]();
                if (manager) {
                    manager[STR_EVENTS_DISCARDED /* @min:%2eeventsDiscarded */]([telemetryItem], 2 /* eEventsDiscardedReason.InvalidEvent */);
                }
            }
            function _addUnloadHook(hooks) {
                _hookContainer.add(hooks);
            }
        });
    }
// Removed Stub for AppInsightsCore.prototype.initialize.
// Removed Stub for AppInsightsCore.prototype.getChannels.
// Removed Stub for AppInsightsCore.prototype.track.
// Removed Stub for AppInsightsCore.prototype.getProcessTelContext.
// Removed Stub for AppInsightsCore.prototype.getNotifyMgr.
// Removed Stub for AppInsightsCore.prototype.addNotificationListener.
// Removed Stub for AppInsightsCore.prototype.removeNotificationListener.
// Removed Stub for AppInsightsCore.prototype.getCookieMgr.
// Removed Stub for AppInsightsCore.prototype.setCookieMgr.
// Removed Stub for AppInsightsCore.prototype.getPerfMgr.
// Removed Stub for AppInsightsCore.prototype.setPerfMgr.
// Removed Stub for AppInsightsCore.prototype.eventCnt.
// Removed Stub for AppInsightsCore.prototype.pollInternalLogs.
// Removed Stub for AppInsightsCore.prototype.stopPollingInternalLogs.
// Removed Stub for AppInsightsCore.prototype.addTelemetryInitializer.
// Removed Stub for AppInsightsCore.prototype.unload.
// Removed Stub for AppInsightsCore.prototype.getPlugin.
// Removed Stub for AppInsightsCore.prototype.addPlugin.
// Removed Stub for AppInsightsCore.prototype.updateCfg.
// Removed Stub for AppInsightsCore.prototype.evtNamespace.
// Removed Stub for AppInsightsCore.prototype.addUnloadCb.
// Removed Stub for AppInsightsCore.prototype.flush.
// Removed Stub for AppInsightsCore.prototype.getTraceCtx.
// Removed Stub for AppInsightsCore.prototype.setTraceCtx.
// Removed Stub for AppInsightsCore.prototype.addUnloadHook.
// Removed Stub for AppInsightsCore.prototype.onCfgChange.
// Removed Stub for AppInsightsCore.prototype.releaseQueue.
// Removed Stub for AppInsightsCore.prototype._updateHook.
    // This is a workaround for an IE 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.
    AppInsightsCore.__ieDyn=1;

    return AppInsightsCore;
}());
export { AppInsightsCore };
//# sourceMappingURL=AppInsightsCore.js.map