/*
 * Application Insights JavaScript SDK - Properties Plugin, 3.3.11
 * Copyright (c) Microsoft and contributors. All rights reserved.
 */
/**
* CfgSyncPlugin.ts
* @copyright Microsoft 2018
*/
var _a;
import { __extendsFn as __extends } from "@microsoft/applicationinsights-shims";
import dynamicProto from "@microsoft/dynamicproto-js";
import { DisabledPropertyName } from "@microsoft/applicationinsights-common";
import { BaseTelemetryPlugin, createProcessTelemetryContext, createUniqueNamespace, eventOff, eventOn, getGlobal, getJSON, isFetchSupported, isXhrSupported, mergeEvtNamespace, onConfigChange, sendCustomEvent } from "@microsoft/applicationinsights-core-js";
import { doAwaitResponse } from "@nevware21/ts-async";
import { isFunction, isNullOrUndefined, isPlainObject, objDeepFreeze, scheduleTimeout } from "@nevware21/ts-utils";
import { applyCdnfeatureCfg, replaceByNonOverrideCfg } from "./CfgSyncHelperFuncs";
import { _DYN_SCHEDULE_FETCH_TIMEO0 } from "./__DynamicConstants";
var EVENT_NAME = "ai_cfgsync";
var STR_GET_METHOD = "GET";
var FETCH_TIMEOUT = 1800000; // 30 minutes
var udfVal = undefined;
var defaultNonOverrideCfg = { instrumentationKey: true, connectionString: true, endpointUrl: true };
var _defaultConfig = objDeepFreeze((_a = {
        syncMode: 1 /* ICfgSyncMode.Broadcast */,
        blkCdnCfg: udfVal,
        customEvtName: udfVal,
        cfgUrl: udfVal,
        overrideSyncFn: udfVal,
        overrideFetchFn: udfVal,
        onCfgChangeReceive: udfVal
    },
    _a[_DYN_SCHEDULE_FETCH_TIMEO0 /* @min:scheduleFetchTimeout */] = FETCH_TIMEOUT,
    _a.nonOverrideConfigs = defaultNonOverrideCfg,
    _a.enableAjax = false,
    _a));
var CfgSyncPlugin = /** @class */ (function (_super) {
    __extends(CfgSyncPlugin, _super);
    function CfgSyncPlugin() {
        var _this = _super.call(this) || this;
        _this.priority = 198;
        _this.identifier = "AppInsightsCfgSyncPlugin";
        var _extensionConfig;
        var _mainConfig; // throttle config should be wrapped in IConfiguration
        var _evtName;
        var _evtNamespace;
        var _cfgUrl;
        var _timeoutHandle;
        var _receiveChanges;
        var _broadcastChanges;
        var _blkCdnCfg;
        var _fetchTimeout;
        var _retryCnt;
        var _onCfgChangeReceive;
        var _nonOverrideConfigs;
        var _fetchFn;
        var _overrideFetchFn;
        var _overrideSyncFn;
        var _paused = false;
        var _enableAjax;
        dynamicProto(CfgSyncPlugin, _this, function (_self, _base) {
            _initDefaults();
            _self.initialize = function (config, core, extensions, pluginChain) {
                _base.initialize(config, core, extensions, pluginChain);
                _evtNamespace = mergeEvtNamespace(createUniqueNamespace(_self.identifier), core.evtNamespace && core.evtNamespace());
                _populateDefaults(config);
            };
            _self.getCfg = function () {
                return _mainConfig;
            };
            _self.pause = function () {
                _paused = true;
                _clearScheduledTimer();
            };
            _self.resume = function () {
                _paused = false;
                _setupTimer();
            };
            // used for V2 to manaully trigger config udpate
            _self.setCfg = function (config) {
                return _setCfg(config);
            };
            _self.sync = function (customDetails) {
                return _sendCfgsyncEvents(customDetails);
            };
            _self.updateEventListenerName = function (eventName) {
                return _updateEventListenerName(eventName);
            };
            _self._doTeardown = function (unloadCtx, unloadState) {
                _eventOff();
                _clearScheduledTimer();
                _initDefaults();
            };
            _self["_getDbgPlgTargets"] = function () {
                return [_broadcastChanges, _receiveChanges, _evtName, _blkCdnCfg, _nonOverrideConfigs];
            };
            function _initDefaults() {
                _mainConfig = null;
                _evtName = null;
                _evtNamespace = null;
                _cfgUrl = null;
                _receiveChanges = null;
                _broadcastChanges = null;
                _nonOverrideConfigs = null;
                _timeoutHandle = null;
                _fetchTimeout = null;
                _retryCnt = null;
                _blkCdnCfg = null;
                _enableAjax = false;
                _overrideFetchFn = null;
                _overrideSyncFn = null;
                _onCfgChangeReceive = null;
            }
            function _populateDefaults(config) {
                var identifier = _self.identifier;
                var core = _self.core;
                _self._addHook(onConfigChange(config, function () {
                    var ctx = createProcessTelemetryContext(null, config, core);
                    _extensionConfig = ctx.getExtCfg(identifier, _defaultConfig);
                    var preBlkCdn = _blkCdnCfg;
                    _blkCdnCfg = !!_extensionConfig.blkCdnCfg;
                    _enableAjax = !!_extensionConfig.enableAjax;
                    // avoid initial call
                    if (!isNullOrUndefined(preBlkCdn) && preBlkCdn !== _blkCdnCfg) {
                        if (!_blkCdnCfg && _cfgUrl) {
                            _fetchFn && _fetchFn(_cfgUrl, _onFetchComplete, _broadcastChanges);
                        }
                        else {
                            _clearScheduledTimer();
                        }
                    }
                    if (isNullOrUndefined(_receiveChanges)) {
                        _receiveChanges = _extensionConfig.syncMode === 2 /* ICfgSyncMode.Receive */;
                    }
                    if (isNullOrUndefined(_broadcastChanges)) {
                        _broadcastChanges = _extensionConfig.syncMode === 1 /* ICfgSyncMode.Broadcast */;
                    }
                    var newEvtName = _extensionConfig.customEvtName || EVENT_NAME;
                    if (_evtName !== newEvtName) {
                        if (_receiveChanges) {
                            _updateEventListenerName(newEvtName);
                        }
                        else {
                            _eventOff();
                            _evtName = newEvtName;
                        }
                    }
                    if (isNullOrUndefined(_cfgUrl)) {
                        _cfgUrl = _extensionConfig.cfgUrl;
                    }
                    // if cfgUrl is set, we will ignore core config change
                    if (!_cfgUrl) {
                        _mainConfig = config;
                        if (_broadcastChanges) {
                            _sendCfgsyncEvents();
                        }
                    }
                }));
                _overrideSyncFn = _extensionConfig.overrideSyncFn;
                _overrideFetchFn = _extensionConfig.overrideFetchFn;
                _onCfgChangeReceive = _extensionConfig.onCfgChangeReceive;
                _nonOverrideConfigs = _extensionConfig.nonOverrideConfigs; // override values should not be changed
                _fetchTimeout = _extensionConfig[_DYN_SCHEDULE_FETCH_TIMEO0 /* @min:%2escheduleFetchTimeout */];
                _fetchFn = _getFetchFnInterface();
                _retryCnt = 0;
                // NOT support cfgURL change to avoid mutiple fetch calls
                if (_cfgUrl && !_blkCdnCfg) {
                    _fetchFn && _fetchFn(_cfgUrl, _onFetchComplete, _broadcastChanges);
                }
            }
            function _setCfg(config, isAutoSync) {
                if (config) {
                    _mainConfig = config;
                    if (!!isAutoSync && !_paused) {
                        return _sendCfgsyncEvents();
                    }
                    if (_receiveChanges && !_paused) {
                        _self.core.updateCfg(config);
                        return true;
                    }
                }
                return false;
            }
            function _eventOff() {
                try {
                    var global_1 = getGlobal();
                    if (global_1) {
                        eventOff(global_1, null, null, _evtNamespace);
                    }
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
            }
            function _sendCfgsyncEvents(customDetails) {
                try {
                    if (!!_overrideSyncFn && isFunction(_overrideSyncFn)) {
                        return _overrideSyncFn(_mainConfig, customDetails);
                    }
                    return sendCustomEvent(_evtName, _mainConfig, customDetails);
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
                return false;
            }
            function _updateEventListenerName(name) {
                try {
                    _eventOff();
                    if (name) {
                        _evtName = name;
                        _addEventListener();
                    }
                    return true;
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
                return false;
            }
            function _getFetchFnInterface() {
                var _fetchFn = _overrideFetchFn;
                if (isNullOrUndefined(_fetchFn)) {
                    if (isFetchSupported()) {
                        _fetchFn = _fetchSender;
                    }
                    else if (isXhrSupported()) {
                        _fetchFn = _xhrSender;
                    }
                }
                return _fetchFn;
            }
            function _fetchSender(url, oncomplete, isAutoSync) {
                var global = getGlobal();
                var fetchFn = (global && global.fetch) || null;
                if (url && fetchFn && isFunction(fetchFn)) {
                    try {
                        var init = {
                            method: STR_GET_METHOD
                        };
                        if (!_enableAjax) {
                            init[DisabledPropertyName] = true;
                        }
                        var request = new Request(url, init);
                        if (!_enableAjax) {
                            try {
                                // Also try and tag the request (just in case the value in init is not copied over)
                                request[DisabledPropertyName] = true;
                            }
                            catch (e) {
                                // If the environment has locked down the XMLHttpRequest (preventExtensions and/or freeze), this would
                                // cause the request to fail and we no telemetry would be sent
                            }
                        }
                        doAwaitResponse(fetch(request), function (result) {
                            var response = result.value;
                            if (!result.rejected) {
                                if (response.ok) {
                                    doAwaitResponse(response.text(), function (res) {
                                        _doOnComplete(oncomplete, response.status, res.value, isAutoSync);
                                    });
                                }
                                else {
                                    _doOnComplete(oncomplete, response.status, null, isAutoSync);
                                }
                            }
                            else {
                                _doOnComplete(oncomplete, 400);
                            }
                        });
                    }
                    catch (e) {
                        // eslint-disable-next-line no-empty
                    }
                }
            }
            function _xhrSender(url, oncomplete, isAutoSync) {
                try {
                    var xhr_1 = new XMLHttpRequest();
                    if (!_enableAjax) {
                        xhr_1[DisabledPropertyName] = true;
                    }
                    xhr_1.open(STR_GET_METHOD, url);
                    xhr_1.onreadystatechange = function () {
                        if (xhr_1.readyState === XMLHttpRequest.DONE) {
                            _doOnComplete(oncomplete, xhr_1.status, xhr_1.responseText, isAutoSync);
                        }
                    };
                    xhr_1.onerror = function () {
                        _doOnComplete(oncomplete, 400);
                    };
                    xhr_1.ontimeout = function () {
                        _doOnComplete(oncomplete, 400);
                    };
                    xhr_1.send();
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
            }
            function _onFetchComplete(status, response, isAutoSync) {
                try {
                    if (status >= 200 && status < 400 && response) {
                        _retryCnt = 0; // any successful response will reset retry count to 0
                        var JSON_1 = getJSON();
                        if (JSON_1) {
                            var cdnCfg = JSON_1.parse(response); //comments are not allowed
                            var cfg = applyCdnfeatureCfg(cdnCfg, _self.core);
                            var newCfg = cfg && isPlainObject(cfg) && _replaceTartgetByKeys(cfg);
                            newCfg && _setCfg(newCfg, isAutoSync);
                            //cfg && _setCfg(cfg, isAutoSync);
                        }
                    }
                    else {
                        _retryCnt++;
                    }
                    if (_retryCnt < 3) {
                        _setupTimer();
                    }
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
            }
            function _doOnComplete(oncomplete, status, response, isAutoSync) {
                try {
                    oncomplete(status, response, isAutoSync);
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
            }
            function _addEventListener() {
                if (_receiveChanges) {
                    var global_2 = getGlobal();
                    if (global_2) {
                        try {
                            eventOn(global_2, _evtName, function (event) {
                                // TODO: add more validation here
                                // may include a "name" or some other features to check
                                var cfgEvent = event && event.detail;
                                if (_onCfgChangeReceive && cfgEvent) {
                                    _onCfgChangeReceive(cfgEvent);
                                }
                                else {
                                    var cfg = cfgEvent && cfgEvent.cfg;
                                    var newCfg = cfg && isPlainObject(cfg) && _replaceTartgetByKeys(cfg);
                                    newCfg && _setCfg(newCfg);
                                }
                            }, _evtNamespace, true);
                        }
                        catch (e) {
                            // eslint-disable-next-line no-empty
                        }
                    }
                }
            }
            // 4 levels
            function _replaceTartgetByKeys(cfg, level) {
                var _cfg = null;
                try {
                    if (cfg) {
                        _cfg = replaceByNonOverrideCfg(cfg, _nonOverrideConfigs, 0, 5);
                    }
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
                return _cfg;
            }
            /**
             * Sets up the timer which triggers fetching cdn every 30mins after inital call
             */
            function _setupTimer() {
                if (!_timeoutHandle && _fetchTimeout) {
                    _timeoutHandle = scheduleTimeout(function () {
                        _timeoutHandle = null;
                        _fetchFn(_cfgUrl, _onFetchComplete, _broadcastChanges);
                    }, _fetchTimeout);
                    _timeoutHandle.unref();
                }
            }
            function _clearScheduledTimer() {
                _timeoutHandle && _timeoutHandle.cancel();
                _timeoutHandle = null;
                _retryCnt = 0;
            }
            _self.processTelemetry = function (env, itemCtx) {
                _self.processNext(env, itemCtx);
            };
        });
        return _this;
    }
// Removed Stub for CfgSyncPlugin.prototype.initialize.
// Removed Stub for CfgSyncPlugin.prototype.getCfg.
// Removed Stub for CfgSyncPlugin.prototype.setCfg.
// Removed Stub for CfgSyncPlugin.prototype.sync.
// Removed Stub for CfgSyncPlugin.prototype.updateEventListenerName.
// Removed Stub for CfgSyncPlugin.prototype.pause.
// Removed Stub for CfgSyncPlugin.prototype.resume.
    //// Removed Stub for CfgSyncPlugin.prototype.processTelemetry.
    // 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.
    CfgSyncPlugin.__ieDyn=1;

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