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


"use strict";
var _a;
import dynamicProto from "@microsoft/dynamicproto-js";
import { isFunction, objDefine } from "@nevware21/ts-utils";
import { createDynamicConfig } from "../Config/DynamicConfig";
import { _DYN_CREATE_NEW, _DYN_DIAG_LOG, _DYN_GET_NEXT, _DYN_GET_PROCESS_TEL_CONT2, _DYN_INITIALIZE, _DYN_IS_ASYNC, _DYN_IS_INITIALIZED, _DYN_PROCESS_NEXT, _DYN_SET_NEXT_PLUGIN, _DYN_TEARDOWN, _DYN_UPDATE, _DYN__DO_TEARDOWN } from "../__DynamicConstants";
import { safeGetLogger } from "./DiagnosticLogger";
import { isNotNullOrUndefined, proxyFunctionAs } from "./HelperFuncs";
import { STR_CORE, STR_EXTENSION_CONFIG, STR_PROCESS_TELEMETRY } from "./InternalConstants";
import { createProcessTelemetryContext, createProcessTelemetryUnloadContext, createProcessTelemetryUpdateContext } from "./ProcessTelemetryContext";
import { createUnloadHandlerContainer } from "./UnloadHandlerContainer";
import { createUnloadHookContainer } from "./UnloadHookContainer";
var strGetPlugin = "getPlugin";
var defaultValues = (_a = {},
    _a[STR_EXTENSION_CONFIG] = { isVal: isNotNullOrUndefined, v: {} },
    _a);
/**
 * BaseTelemetryPlugin provides a basic implementation of the ITelemetryPlugin interface so that plugins
 * can avoid implementation the same set of boiler plate code as well as provide a base
 * implementation so that new default implementations can be added without breaking all plugins.
 */
var BaseTelemetryPlugin = /** @class */ (function () {
    function BaseTelemetryPlugin() {
        var _self = this; // Setting _self here as it's used outside of the dynamicProto as well
        // NOTE!: DON'T set default values here, instead set them in the _initDefaults() function as it is also called during teardown()
        var _isinitialized;
        var _rootCtx; // Used as the root context, holding the current config and initialized core
        var _nextPlugin; // Used for backward compatibility where plugins don't call the main pipeline
        var _unloadHandlerContainer;
        var _hookContainer;
        _initDefaults();
        dynamicProto(BaseTelemetryPlugin, _self, function (_self) {
            _self[_DYN_INITIALIZE /* @min:%2einitialize */] = function (config, core, extensions, pluginChain) {
                _setDefaults(config, core, pluginChain);
                _isinitialized = true;
            };
            _self[_DYN_TEARDOWN /* @min:%2eteardown */] = function (unloadCtx, unloadState) {
                var _a;
                // If this plugin has already been torn down (not operational) or is not initialized (core is not set)
                // or the core being used for unload was not the same core used for initialization.
                var core = _self[STR_CORE /* @min:%2ecore */];
                if (!core || (unloadCtx && core !== unloadCtx[STR_CORE /* @min:%2ecore */]())) {
                    // Do Nothing as either the plugin is not initialized or was not initialized by the current core
                    return;
                }
                var result;
                var unloadDone = false;
                var theUnloadCtx = unloadCtx || createProcessTelemetryUnloadContext(null, core, _nextPlugin && _nextPlugin[strGetPlugin] ? _nextPlugin[strGetPlugin]() : _nextPlugin);
                var theUnloadState = unloadState || (_a = {
                        reason: 0 /* TelemetryUnloadReason.ManualTeardown */
                    },
                    _a[_DYN_IS_ASYNC /* @min:isAsync */] = false,
                    _a);
                function _unloadCallback() {
                    if (!unloadDone) {
                        unloadDone = true;
                        _unloadHandlerContainer.run(theUnloadCtx, unloadState);
                        _hookContainer.run(theUnloadCtx[_DYN_DIAG_LOG /* @min:%2ediagLog */]());
                        if (result === true) {
                            theUnloadCtx[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](theUnloadState);
                        }
                        _initDefaults();
                    }
                }
                if (!_self[_DYN__DO_TEARDOWN /* @min:%2e_doTeardown */] || _self[_DYN__DO_TEARDOWN /* @min:%2e_doTeardown */](theUnloadCtx, theUnloadState, _unloadCallback) !== true) {
                    _unloadCallback();
                }
                else {
                    // Tell the caller that we will be calling processNext()
                    result = true;
                }
                return result;
            };
            _self[_DYN_UPDATE /* @min:%2eupdate */] = function (updateCtx, updateState) {
                // If this plugin has already been torn down (not operational) or is not initialized (core is not set)
                // or the core being used for unload was not the same core used for initialization.
                var core = _self[STR_CORE /* @min:%2ecore */];
                if (!core || (updateCtx && core !== updateCtx[STR_CORE /* @min:%2ecore */]())) {
                    // Do Nothing
                    return;
                }
                var result;
                var updateDone = false;
                var theUpdateCtx = updateCtx || createProcessTelemetryUpdateContext(null, core, _nextPlugin && _nextPlugin[strGetPlugin] ? _nextPlugin[strGetPlugin]() : _nextPlugin);
                var theUpdateState = updateState || {
                    reason: 0 /* TelemetryUpdateReason.Unknown */
                };
                function _updateCallback() {
                    if (!updateDone) {
                        updateDone = true;
                        _setDefaults(theUpdateCtx.getCfg(), theUpdateCtx.core(), theUpdateCtx[_DYN_GET_NEXT /* @min:%2egetNext */]());
                    }
                }
                if (!_self._doUpdate || _self._doUpdate(theUpdateCtx, theUpdateState, _updateCallback) !== true) {
                    _updateCallback();
                }
                else {
                    result = true;
                }
                return result;
            };
            proxyFunctionAs(_self, "_addUnloadCb", function () { return _unloadHandlerContainer; }, "add");
            proxyFunctionAs(_self, "_addHook", function () { return _hookContainer; }, "add");
            objDefine(_self, "_unloadHooks", { g: function () { return _hookContainer; } });
        });
        // These are added after the dynamicProto so that are not moved to the prototype
        _self[_DYN_DIAG_LOG /* @min:%2ediagLog */] = function (itemCtx) {
            return _getTelCtx(itemCtx)[_DYN_DIAG_LOG /* @min:%2ediagLog */]();
        };
        _self[_DYN_IS_INITIALIZED /* @min:%2eisInitialized */] = function () {
            return _isinitialized;
        };
        _self.setInitialized = function (isInitialized) {
            _isinitialized = isInitialized;
        };
        // _self.getNextPlugin = () => DO NOT IMPLEMENT
        // Sub-classes of this base class *should* not be relying on this value and instead
        // should use processNext() function. If you require access to the plugin use the
        // IProcessTelemetryContext.getNext().getPlugin() while in the pipeline, Note getNext() may return null.
        _self[_DYN_SET_NEXT_PLUGIN /* @min:%2esetNextPlugin */] = function (next) {
            _nextPlugin = next;
        };
        _self[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */] = function (env, itemCtx) {
            if (itemCtx) {
                // Normal core execution sequence
                itemCtx[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](env);
            }
            else if (_nextPlugin && isFunction(_nextPlugin[STR_PROCESS_TELEMETRY /* @min:%2eprocessTelemetry */])) {
                // Looks like backward compatibility or out of band processing. And as it looks
                // like a ITelemetryPlugin or ITelemetryPluginChain, just call processTelemetry
                _nextPlugin[STR_PROCESS_TELEMETRY /* @min:%2eprocessTelemetry */](env, null);
            }
        };
        _self._getTelCtx = _getTelCtx;
        function _getTelCtx(currentCtx) {
            if (currentCtx === void 0) { currentCtx = null; }
            var itemCtx = currentCtx;
            if (!itemCtx) {
                var rootCtx = _rootCtx || createProcessTelemetryContext(null, {}, _self[STR_CORE /* @min:%2ecore */]);
                // tslint:disable-next-line: prefer-conditional-expression
                if (_nextPlugin && _nextPlugin[strGetPlugin]) {
                    // Looks like a chain object
                    itemCtx = rootCtx[_DYN_CREATE_NEW /* @min:%2ecreateNew */](null, _nextPlugin[strGetPlugin]);
                }
                else {
                    itemCtx = rootCtx[_DYN_CREATE_NEW /* @min:%2ecreateNew */](null, _nextPlugin);
                }
            }
            return itemCtx;
        }
        function _setDefaults(config, core, pluginChain) {
            // Make sure the extensionConfig exists and the config is dynamic
            createDynamicConfig(config, defaultValues, safeGetLogger(core));
            if (!pluginChain && core) {
                // Get the first plugin from the core
                pluginChain = core[_DYN_GET_PROCESS_TEL_CONT2 /* @min:%2egetProcessTelContext */]()[_DYN_GET_NEXT /* @min:%2egetNext */]();
            }
            var nextPlugin = _nextPlugin;
            if (_nextPlugin && _nextPlugin[strGetPlugin]) {
                // If it looks like a proxy/chain then get the plugin
                nextPlugin = _nextPlugin[strGetPlugin]();
            }
            // Support legacy plugins where core was defined as a property
            _self[STR_CORE /* @min:%2ecore */] = core;
            _rootCtx = createProcessTelemetryContext(pluginChain, config, core, nextPlugin);
        }
        function _initDefaults() {
            _isinitialized = false;
            _self[STR_CORE /* @min:%2ecore */] = null;
            _rootCtx = null;
            _nextPlugin = null;
            _hookContainer = createUnloadHookContainer();
            _unloadHandlerContainer = createUnloadHandlerContainer();
        }
    }
// Removed Stub for BaseTelemetryPlugin.prototype.initialize.
// Removed Stub for BaseTelemetryPlugin.prototype.teardown.
// Removed Stub for BaseTelemetryPlugin.prototype.update.
// Removed Stub for BaseTelemetryPlugin.prototype._addUnloadCb.
// Removed Stub for BaseTelemetryPlugin.prototype._addHook.
    // 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.
    BaseTelemetryPlugin.__ieDyn=1;

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