/*
 * 1DS JS SDK POST plugin, 4.3.10-nightly3.2507-04
 * Copyright (c) Microsoft and contributors. All rights reserved.
 * (Microsoft Internal Only)
 */
var _a;
/**
* HttpManager.ts
* @author Abhilash Panwar (abpanwar); Hector Hernandez (hectorh); Nev Wylie (newylie)
* @copyright Microsoft 2018-2020
*/
import dynamicProto from "@microsoft/dynamicproto-js";
import { FullVersionString, SenderPostManager, _getAllResponseHeaders, _throwInternal, _warnToConsole, arrForEach, dateNow, doPerf, dumpObj, extend, getCommonSchemaMetaData, getNavigator, getResponseText, getTime, hasOwnProperty, isBeaconsSupported, isFeatureEnabled, isFetchSupported, isNullOrUndefined, isReactNative, isUndefined, isValueAssigned, objForEachKey, objKeys, onConfigChange, optimizeObject, prependTransports, strUndefined } from "@microsoft/1ds-core-js";
import { arrAppend, getInst, isFunction } from "@nevware21/ts-utils";
import { ClockSkewManager } from "./ClockSkewManager";
import { EventBatch } from "./EventBatch";
import { DEFAULT_CACHE_CONTROL, DEFAULT_CONTENT_TYPE, STR_API_KEY, STR_AUTH_XTOKEN, STR_CACHE_CONTROL, STR_CLIENT_ID, STR_CLIENT_VERSION, STR_CONTENT_TYPE_HEADER, STR_DROPPED, STR_EMPTY, STR_KILL_DURATION_HEADER, STR_KILL_TOKENS_HEADER, STR_MSA_DEVICE_TICKET, STR_MSFPC, STR_NO_RESPONSE_BODY, STR_OTHER, STR_REQUEUE, STR_RESPONSE_FAIL, STR_SENDING, STR_TIME_DELTA_HEADER, STR_TIME_DELTA_TO_APPLY, STR_UPLOAD_TIME } from "./InternalConstants";
import { KillSwitch } from "./KillSwitch";
import { retryPolicyGetMillisToBackoffForRetry, retryPolicyShouldRetryForStatus } from "./RetryPolicy";
import { Serializer } from "./Serializer";
import { createTimeoutWrapper } from "./TimeoutOverrideWrapper";
import { _DYN_ADD_NO_RESPONSE, _DYN_ALLOW_REQUEST_SENDIN0, _DYN_ALWAYS_USE_XHR_OVERR7, _DYN_AVOID_OPTIONS, _DYN_BATCHES, _DYN_CAN_SEND_REQUEST, _DYN_CLEAR_TIMEOUT_OVERRI3, _DYN_CONCAT, _DYN_COUNT, _DYN_CREATE_ONE_DSPAYLOAD, _DYN_CREATE_PAYLOAD, _DYN_DISABLE_EVENT_TIMING5, _DYN_DISABLE_FETCH_KEEP_A6, _DYN_DISABLE_XHR_SYNC, _DYN_ENABLE_COMPOUND_KEY, _DYN_EVENTS, _DYN_FETCH_CREDENTIALS, _DYN_GET_CLOCK_SKEW_HEADE2, _DYN_GET_OFFLINE_REQUEST_9, _DYN_GET_WPARAM, _DYN_HDRS, _DYN_HEADERS, _DYN_INITIALIZE, _DYN_IS_BEACON, _DYN_IS_TEARDOWN, _DYN_I_KEY, _DYN_LENGTH, _DYN_OVERRIDE_ENDPOINT_UR4, _DYN_PAYLOAD_BLOB, _DYN_PAYLOAD_PREPROCESSOR, _DYN_PUSH, _DYN_SEND_QUEUED_REQUESTS, _DYN_SEND_SYNCHRONOUS_BAT10, _DYN_SEND_TYPE, _DYN_SERIALIZE_OFFLINE_EV8, _DYN_SET_CLOCK_SKEW, _DYN_SET_KILL_SWITCH_TENA11, _DYN_SET_TIMEOUT_OVERRIDE, _DYN_SET_UNLOADING, _DYN_SHOULD_ADD_CLOCK_SKE1, _DYN_SPLIT, _DYN_TIMINGS, _DYN_TO_LOWER_CASE, _DYN_USE_HDRS, _DYN_USE_SEND_BEACON, _DYN__BACK_OFF_TRANSMISSI12, _DYN__SEND_REASON, _DYN__THE_PAYLOAD, _DYN__TRANSPORT } from "./__DynamicConstants";
var strSendAttempt = "sendAttempt";
var _noResponseQs = "&" + STR_NO_RESPONSE_BODY + "=true";
var UrlQueryString = "?cors=true&" + STR_CONTENT_TYPE_HEADER[_DYN_TO_LOWER_CASE /* @min:%2etoLowerCase */]() + "=" + DEFAULT_CONTENT_TYPE;
/**
 * Identifies the default notification reason to the action names
 */
var _eventActionMap = (_a = {},
    _a[1 /* EventBatchNotificationReason.Paused */] = STR_REQUEUE,
    _a[100 /* EventBatchNotificationReason.RequeueEvents */] = STR_REQUEUE,
    _a[200 /* EventBatchNotificationReason.Complete */] = "sent",
    _a[8004 /* EventBatchNotificationReason.KillSwitch */] = STR_DROPPED,
    _a[8003 /* EventBatchNotificationReason.SizeLimitExceeded */] = STR_DROPPED,
    _a);
var _collectorQsHeaders = {};
var _collectorHeaderToQs = {};
function _addCollectorHeaderQsMapping(qsName, headerName, allowQs) {
    _collectorQsHeaders[qsName] = headerName;
    if (allowQs !== false) {
        _collectorHeaderToQs[headerName] = qsName;
    }
}
_addCollectorHeaderQsMapping(STR_MSA_DEVICE_TICKET, STR_MSA_DEVICE_TICKET, false);
_addCollectorHeaderQsMapping(STR_CLIENT_VERSION, STR_CLIENT_VERSION);
_addCollectorHeaderQsMapping(STR_CLIENT_ID, "Client-Id");
_addCollectorHeaderQsMapping(STR_API_KEY, STR_API_KEY);
_addCollectorHeaderQsMapping(STR_TIME_DELTA_TO_APPLY, STR_TIME_DELTA_TO_APPLY);
_addCollectorHeaderQsMapping(STR_UPLOAD_TIME, STR_UPLOAD_TIME);
_addCollectorHeaderQsMapping(STR_AUTH_XTOKEN, STR_AUTH_XTOKEN);
function _hasHeader(headers, header) {
    var hasHeader = false;
    if (headers && header) {
        var keys = objKeys(headers);
        if (keys && keys[_DYN_LENGTH /* @min:%2elength */] > 0) {
            var lowerHeader = header[_DYN_TO_LOWER_CASE /* @min:%2etoLowerCase */]();
            for (var lp = 0; lp < keys[_DYN_LENGTH /* @min:%2elength */]; lp++) {
                var value = keys[lp];
                if (value && hasOwnProperty(header, value) &&
                    value[_DYN_TO_LOWER_CASE /* @min:%2etoLowerCase */]() === lowerHeader) {
                    hasHeader = true;
                    break;
                }
            }
        }
    }
    return hasHeader;
}
function _addRequestDetails(details, name, value, useHeaders) {
    if (name && value && value[_DYN_LENGTH /* @min:%2elength */] > 0) {
        if (useHeaders && _collectorQsHeaders[name]) {
            details[_DYN_HDRS /* @min:%2ehdrs */][_collectorQsHeaders[name]] = value;
            details[_DYN_USE_HDRS /* @min:%2euseHdrs */] = true;
        }
        else {
            details.url += "&" + name + "=" + value;
        }
    }
}
function _addQueryStringParameter(qsParams, name, value) {
    for (var i = 0; i < qsParams[_DYN_LENGTH /* @min:%2elength */]; i++) {
        if (qsParams[i].name === name) {
            qsParams[i].value = value;
            return;
        }
    }
    qsParams[_DYN_PUSH /* @min:%2epush */]({ name: name, value: value });
}
function _removeQueryStringParameter(qsParams, name) {
    for (var i = 0; i < qsParams[_DYN_LENGTH /* @min:%2elength */]; i++) {
        if (qsParams[i].name === name) {
            qsParams.splice(i, 1);
            return;
        }
    }
}
/**
 * Class managing the sending of requests.
 */
var HttpManager = /** @class */ (function () {
    /**
     * @constructor
     * @param requestQueue   - The queue that contains the requests to be sent.
     */
    function HttpManager(maxEventsPerBatch, maxConnections, maxRequestRetriesBeforeBackoff, actions) {
        // ------------------------------------------------------------------------------------------------------------------------
        // Only set "Default" values in the _initDefaults() method, unless value are not "reset" during unloading
        // ------------------------------------------------------------------------------------------------------------------------
        var _urlString;
        var _killSwitch;
        var _paused;
        var _clockSkewManager;
        var _useBeacons = false;
        var _outstandingRequests; // Holds the number of outstanding async requests that have not returned a response yet
        var _postManager;
        var _logger;
        var _sendInterfaces;
        var _core;
        var _customHttpInterface;
        var _queryStringParameters;
        var _headers;
        var _batchQueue;
        var _serializer;
        var _enableEventTimings;
        var _cookieMgr;
        var _isUnloading;
        var _useHeaders;
        var _xhrTimeout;
        var _zipPayload;
        var _disableXhrSync;
        var _disableFetchKeepAlive;
        var _canHaveReducedPayload;
        var _addNoResponse;
        var _unloadHooks;
        var _sendHook;
        var _sendListener;
        var _responseHandlers;
        var _isInitialized;
        var _timeoutWrapper;
        var _excludeCsMetaData;
        var _sendPostMgr;
        var _fetchCredentials;
        var _maxEvtPerBatch = maxEventsPerBatch; // Sets default value in case the value is null
        dynamicProto(HttpManager, this, function (_self) {
            _initDefaults();
            var _sendCredentials = true;
            _self[_DYN_INITIALIZE /* @min:%2einitialize */] = function (theConfig, core, postChannel) {
                if (!_isInitialized) {
                    _core = core;
                    _cookieMgr = core.getCookieMgr();
                    _postManager = postChannel;
                    _logger = _postManager.diagLog();
                    arrAppend(_unloadHooks, onConfigChange(theConfig, function (details) {
                        var _a;
                        var coreConfig = details.cfg;
                        var channelConfig = details.cfg.extensionConfig[postChannel.identifier];
                        _timeoutWrapper = createTimeoutWrapper(channelConfig[_DYN_SET_TIMEOUT_OVERRIDE /* @min:%2esetTimeoutOverride */], channelConfig[_DYN_CLEAR_TIMEOUT_OVERRI3 /* @min:%2eclearTimeoutOverride */]);
                        if (isValueAssigned(coreConfig.anonCookieName)) {
                            _addQueryStringParameter(_queryStringParameters, "anoncknm", coreConfig.anonCookieName);
                        }
                        else {
                            _removeQueryStringParameter(_queryStringParameters, "anoncknm");
                        }
                        _sendHook = channelConfig[_DYN_PAYLOAD_PREPROCESSOR /* @min:%2epayloadPreprocessor */];
                        _sendListener = channelConfig.payloadListener;
                        var httpInterface = channelConfig.httpXHROverride;
                        // Override endpointUrl if provided in Post config
                        var endpointUrl = channelConfig[_DYN_OVERRIDE_ENDPOINT_UR4 /* @min:%2eoverrideEndpointUrl */] ? channelConfig[_DYN_OVERRIDE_ENDPOINT_UR4 /* @min:%2eoverrideEndpointUrl */] : coreConfig.endpointUrl;
                        _urlString = endpointUrl + UrlQueryString;
                        _useHeaders = !isUndefined(channelConfig[_DYN_AVOID_OPTIONS /* @min:%2eavoidOptions */]) ? !channelConfig[_DYN_AVOID_OPTIONS /* @min:%2eavoidOptions */] : true;
                        _enableEventTimings = !channelConfig[_DYN_DISABLE_EVENT_TIMING5 /* @min:%2edisableEventTimings */];
                        var maxEvtCfg = channelConfig.maxEvtPerBatch;
                        _maxEvtPerBatch = maxEvtCfg && maxEvtCfg <= maxEventsPerBatch ? maxEvtCfg : maxEventsPerBatch;
                        var valueSanitizer = channelConfig.valueSanitizer;
                        var stringifyObjects = channelConfig.stringifyObjects;
                        var enableCompoundKey = !!coreConfig[_DYN_ENABLE_COMPOUND_KEY /* @min:%2eenableCompoundKey */];
                        if (!isUndefined(channelConfig[_DYN_ENABLE_COMPOUND_KEY /* @min:%2eenableCompoundKey */])) {
                            enableCompoundKey = !!channelConfig[_DYN_ENABLE_COMPOUND_KEY /* @min:%2eenableCompoundKey */];
                        }
                        _xhrTimeout = channelConfig.xhrTimeout;
                        var csStream = getInst("CompressionStream");
                        // Controls whether payload compression (gzip) is enabled.
                        _zipPayload = isFeatureEnabled("zipPayload", coreConfig, false);
                        // if user has payload processor (_sendHook), they may compress the payload themselves
                        // to avoid double compression, we should disable the zipPayload
                        if (!isFunction(csStream) || _sendHook) {
                            _zipPayload = false;
                        }
                        _disableXhrSync = !!channelConfig[_DYN_DISABLE_XHR_SYNC /* @min:%2edisableXhrSync */];
                        _disableFetchKeepAlive = !!channelConfig[_DYN_DISABLE_FETCH_KEEP_A6 /* @min:%2edisableFetchKeepAlive */];
                        _addNoResponse = channelConfig[_DYN_ADD_NO_RESPONSE /* @min:%2eaddNoResponse */] !== false;
                        _excludeCsMetaData = !!channelConfig.excludeCsMetaData;
                        if (!!core.getPlugin("LocalStorage")) {
                            // Always disable fetch keep alive when persisten storage is available
                            _disableFetchKeepAlive = true;
                        }
                        _useBeacons = !isReactNative(); // Only use beacons if not running in React Native
                        _serializer = new Serializer(_core, valueSanitizer, stringifyObjects, enableCompoundKey, getCommonSchemaMetaData, _excludeCsMetaData, channelConfig);
                        if (!isNullOrUndefined(channelConfig[_DYN_USE_SEND_BEACON /* @min:%2euseSendBeacon */])) {
                            _useBeacons = !!channelConfig[_DYN_USE_SEND_BEACON /* @min:%2euseSendBeacon */];
                        }
                        if (channelConfig[_DYN_FETCH_CREDENTIALS /* @min:%2efetchCredentials */]) {
                            _fetchCredentials = channelConfig[_DYN_FETCH_CREDENTIALS /* @min:%2efetchCredentials */];
                        }
                        var sendPostConfig = _getSendPostMgrConfig();
                        // only init it once
                        if (!_sendPostMgr) {
                            _sendPostMgr = new SenderPostManager();
                            _sendPostMgr[_DYN_INITIALIZE /* @min:%2einitialize */](sendPostConfig, _logger);
                        }
                        else {
                            _sendPostMgr.SetConfig(sendPostConfig);
                        }
                        var syncHttpInterface = httpInterface;
                        var beaconHttpInterface = channelConfig[_DYN_ALWAYS_USE_XHR_OVERR7 /* @min:%2ealwaysUseXhrOverride */] ? httpInterface : null;
                        var fetchSyncHttpInterface = channelConfig[_DYN_ALWAYS_USE_XHR_OVERR7 /* @min:%2ealwaysUseXhrOverride */] ? httpInterface : null;
                        var beaconUnloadTransports = [3 /* TransportType.Beacon */, 2 /* TransportType.Fetch */];
                        if (!httpInterface) {
                            _customHttpInterface = false;
                            // this is handled in SendPostManager now
                            // let location = getLocation();
                            // if (location && location.protocol && location.protocol.toLowerCase() === "file:") {
                            //     // Special case where a local html file fails with a CORS error on Chromium browsers
                            //     _sendCredentials = false;
                            // }
                            var theTransports = [];
                            if (isReactNative()) {
                                // Use Fetch or XDR/XHR
                                theTransports = [2 /* TransportType.Fetch */, 1 /* TransportType.Xhr */];
                                beaconUnloadTransports = [2 /* TransportType.Fetch */, 1 /* TransportType.Xhr */, 3 /* TransportType.Beacon */];
                            }
                            else {
                                // Use XDR/XHR, Fetch or beacons
                                theTransports = [1 /* TransportType.Xhr */, 2 /* TransportType.Fetch */, 3 /* TransportType.Beacon */];
                            }
                            // Prefix any user requested transport(s) values
                            theTransports = prependTransports(theTransports, channelConfig.transports);
                            httpInterface = _getSenderInterface(theTransports, false);
                            if (!httpInterface) {
                                _warnToConsole(_logger, "No available transport to send events");
                            }
                            syncHttpInterface = _getSenderInterface(theTransports, true);
                        }
                        if (!beaconHttpInterface) {
                            // Allow overriding the usage of sendBeacon
                            beaconUnloadTransports = prependTransports(beaconUnloadTransports, channelConfig.unloadTransports);
                            beaconHttpInterface = _getSenderInterface(beaconUnloadTransports, true);
                        }
                        _canHaveReducedPayload = !_customHttpInterface && ((_useBeacons && isBeaconsSupported()) || (!_disableFetchKeepAlive && isFetchSupported(true)));
                        _sendInterfaces = (_a = {},
                            _a[0 /* EventSendType.Batched */] = httpInterface,
                            _a[1 /* EventSendType.Synchronous */] = syncHttpInterface || _getSenderInterface([1 /* TransportType.Xhr */, 2 /* TransportType.Fetch */, 3 /* TransportType.Beacon */], true),
                            _a[2 /* EventSendType.SendBeacon */] = beaconHttpInterface || syncHttpInterface || _getSenderInterface([1 /* TransportType.Xhr */], true),
                            _a[3 /* EventSendType.SyncFetch */] = fetchSyncHttpInterface || _getSenderInterface([2 /* TransportType.Fetch */, 3 /* TransportType.Beacon */], true) || syncHttpInterface || _getSenderInterface([1 /* TransportType.Xhr */], true),
                            _a);
                    }));
                    _isInitialized = true;
                }
            };
            _self.addResponseHandler = function (responseHandler) {
                _responseHandlers[_DYN_PUSH /* @min:%2epush */](responseHandler);
                return {
                    rm: function () {
                        var index = _responseHandlers.indexOf(responseHandler);
                        if (index >= 0) {
                            _responseHandlers.splice(index, 1);
                        }
                    }
                };
            };
            _self[_DYN_SERIALIZE_OFFLINE_EV8 /* @min:%2eserializeOfflineEvt */] = function (evt) {
                try {
                    if (_serializer) {
                        return _serializer.getEventBlob(evt);
                    }
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
                return STR_EMPTY;
            };
            _self[_DYN_GET_OFFLINE_REQUEST_9 /* @min:%2egetOfflineRequestDetails */] = function () {
                try {
                    // get current url without paramter
                    var payload = _serializer && _serializer[_DYN_CREATE_PAYLOAD /* @min:%2ecreatePayload */](0, false, false, false, 1 /* SendRequestReason.NormalSchedule */, 0 /* EventSendType.Batched */);
                    return _buildRequestDetails(payload, _useHeaders);
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
                return null;
            };
            _self[_DYN_CREATE_ONE_DSPAYLOAD /* @min:%2ecreateOneDSPayload */] = function (evts, optimize) {
                try {
                    // TODO: optimize
                    var theBatches_1 = [];
                    // create a eventBatch for each event
                    arrForEach(evts, function (evt) {
                        if (optimize) {
                            evt = optimizeObject(evt);
                        }
                        var batch = EventBatch.create(evt[_DYN_I_KEY /* @min:%2eiKey */], [evt]);
                        theBatches_1[_DYN_PUSH /* @min:%2epush */](batch);
                    });
                    var thePayload = null;
                    while (theBatches_1[_DYN_LENGTH /* @min:%2elength */] > 0 && _serializer) {
                        var theBatch = theBatches_1.shift();
                        if (theBatch && theBatch[_DYN_COUNT /* @min:%2ecount */]() > 0) {
                            thePayload = thePayload || _serializer[_DYN_CREATE_PAYLOAD /* @min:%2ecreatePayload */](0, false, false, false, 1 /* SendRequestReason.NormalSchedule */, 0 /* EventSendType.Batched */);
                            _serializer.appendPayload(thePayload, theBatch, _maxEvtPerBatch);
                        }
                    }
                    var requestDetails = _buildRequestDetails(thePayload, _useHeaders);
                    var payloadData = {
                        data: thePayload[_DYN_PAYLOAD_BLOB /* @min:%2epayloadBlob */],
                        urlString: requestDetails.url,
                        headers: requestDetails[_DYN_HDRS /* @min:%2ehdrs */],
                        timeout: _xhrTimeout,
                        disableXhrSync: _disableXhrSync,
                        disableFetchKeepAlive: _disableFetchKeepAlive
                    };
                    // Only automatically add the following headers if already sending headers and we are not attempting to avoid an options call
                    if (_useHeaders) {
                        if (!_hasHeader(payloadData[_DYN_HEADERS /* @min:%2eheaders */], STR_CACHE_CONTROL)) {
                            payloadData[_DYN_HEADERS /* @min:%2eheaders */][STR_CACHE_CONTROL] = DEFAULT_CACHE_CONTROL;
                        }
                        if (!_hasHeader(payloadData[_DYN_HEADERS /* @min:%2eheaders */], STR_CONTENT_TYPE_HEADER)) {
                            payloadData[_DYN_HEADERS /* @min:%2eheaders */][STR_CONTENT_TYPE_HEADER] = DEFAULT_CONTENT_TYPE;
                        }
                    }
                    return payloadData;
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
                return null;
            };
            // Special internal method to allow the DebugPlugin to hook embedded objects
            function _getSenderInterface(transports, syncSupport) {
                try {
                    return _sendPostMgr && _sendPostMgr.getSenderInst(transports, syncSupport);
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
                return null;
            }
            _self["_getDbgPlgTargets"] = function () {
                return [_sendInterfaces[0 /* EventSendType.Batched */], _killSwitch, _serializer, _sendInterfaces, _getSendPostMgrConfig(), _urlString, _maxEvtPerBatch];
            };
            function _getSendPostMgrConfig() {
                try {
                    var onCompleteFuncs = {
                        xdrOnComplete: _xdrOncomplete,
                        fetchOnComplete: _fetchOnComplete,
                        xhrOnComplete: _xhrOnComplete,
                        beaconOnRetry: _onBeaconRetry
                    };
                    var config = {
                        enableSendPromise: false,
                        isOneDs: true,
                        disableCredentials: !_sendCredentials,
                        fetchCredentials: _fetchCredentials,
                        disableXhr: false,
                        disableBeacon: !_useBeacons,
                        disableBeaconSync: !_useBeacons,
                        disableFetchKeepAlive: _disableFetchKeepAlive,
                        timeWrapper: _timeoutWrapper,
                        addNoResponse: _addNoResponse,
                        senderOnCompleteCallBack: onCompleteFuncs
                    };
                    return config;
                }
                catch (e) {
                    // eslint-disable-next-line no-empty
                }
                return null;
            }
            function _xdrOncomplete(xdr, oncomplete, payload) {
                var response = getResponseText(xdr);
                _doOnComplete(oncomplete, 200, {}, response);
                _handleCollectorResponse(response);
            }
            function _initDefaults() {
                var undefValue;
                _urlString = null;
                _killSwitch = new KillSwitch();
                _paused = false;
                _clockSkewManager = new ClockSkewManager();
                _useBeacons = false;
                _outstandingRequests = 0; // Holds the number of outstanding async requests that have not returned a response yet
                _postManager = null;
                _logger = null;
                _sendInterfaces = null;
                _core = null;
                _customHttpInterface = true;
                _queryStringParameters = [];
                _headers = {};
                _batchQueue = [];
                _serializer = null;
                _enableEventTimings = false;
                _cookieMgr = null;
                _isUnloading = false;
                _useHeaders = false;
                _xhrTimeout = undefValue;
                _disableXhrSync = undefValue;
                _disableFetchKeepAlive = undefValue;
                _canHaveReducedPayload = undefValue;
                _addNoResponse = undefValue;
                _unloadHooks = [];
                _sendHook = undefValue;
                _sendListener = undefValue;
                _responseHandlers = [];
                _isInitialized = false;
                _timeoutWrapper = createTimeoutWrapper();
                _excludeCsMetaData = false;
                _sendPostMgr = null;
                _maxEvtPerBatch = null;
            }
            function _fetchOnComplete(response, onComplete, resValue, payload) {
                var handleResponse = function (status, headerMap, responseText) {
                    _doOnComplete(onComplete, status, headerMap, responseText);
                    _handleCollectorResponse(responseText);
                };
                var headerMap = {};
                var headers = response[_DYN_HEADERS /* @min:%2eheaders */];
                if (headers) {
                    headers["forEach"](function (value, name) {
                        headerMap[name] = value;
                    });
                }
                handleResponse(response.status, headerMap, resValue || STR_EMPTY);
            }
            function _xhrOnComplete(request, oncomplete, payload) {
                var response = getResponseText(request);
                _doOnComplete(oncomplete, request.status, _getAllResponseHeaders(request, true), response);
                _handleCollectorResponse(response);
            }
            function _doOnComplete(oncomplete, status, headers, response) {
                try {
                    oncomplete(status, headers, response);
                }
                catch (e) {
                    _throwInternal(_logger, 2 /* eLoggingSeverity.WARNING */, 518 /* _eExtendedInternalMessageId.SendPostOnCompleteFailure */, dumpObj(e));
                }
            }
            function _onBeaconRetry(payload, onComplete, canSend) {
                // Custom headers not supported in sendBeacon payload.headers would be ignored
                var internalPayloadData = payload;
                var status = 200;
                var thePayload = internalPayloadData[_DYN__THE_PAYLOAD /* @min:%2e_thePayload */];
                var theUrl = payload.urlString + (_addNoResponse ? _noResponseQs : STR_EMPTY);
                try {
                    var nav_1 = getNavigator();
                    if (thePayload) {
                        var persistStorage = !!_core.getPlugin("LocalStorage");
                        // Failed to send entire payload so try and split data and try to send as much events as possible
                        var droppedBatches_1 = [];
                        var sentBatches_1 = [];
                        arrForEach(thePayload[_DYN_BATCHES /* @min:%2ebatches */], function (theBatch) {
                            if (droppedBatches_1 && theBatch && theBatch[_DYN_COUNT /* @min:%2ecount */]() > 0) {
                                var theEvents = theBatch[_DYN_EVENTS /* @min:%2eevents */]();
                                for (var lp = 0; lp < theEvents[_DYN_LENGTH /* @min:%2elength */]; lp++) {
                                    if (!nav_1.sendBeacon(theUrl, _serializer.getEventBlob(theEvents[lp]))) {
                                        // Can't send anymore, so split the batch and drop the rest
                                        droppedBatches_1[_DYN_PUSH /* @min:%2epush */](theBatch[_DYN_SPLIT /* @min:%2esplit */](lp));
                                        break;
                                    }
                                    else {
                                        sentBatches_1[_DYN_PUSH /* @min:%2epush */](theBatch[lp]);
                                    }
                                }
                            }
                            else {
                                // Remove all of the events from the existing batch in the payload as the copy includes the original
                                droppedBatches_1[_DYN_PUSH /* @min:%2epush */](theBatch[_DYN_SPLIT /* @min:%2esplit */](0));
                            }
                        });
                        if (sentBatches_1[_DYN_LENGTH /* @min:%2elength */] > 0) {
                            // Update the payload with the sent batches
                            thePayload.sentEvts = sentBatches_1;
                        }
                        if (!persistStorage) {
                            _sendBatchesNotification(droppedBatches_1, 8003 /* EventBatchNotificationReason.SizeLimitExceeded */, thePayload[_DYN_SEND_TYPE /* @min:%2esendType */], true);
                        }
                    }
                    else {
                        status = 0;
                    }
                }
                catch (ex) {
                    _warnToConsole(_logger, "Failed to send telemetry using sendBeacon API. Ex:" + dumpObj(ex));
                    status = 0;
                }
                finally {
                    _doOnComplete(onComplete, status, {}, STR_EMPTY);
                }
            }
            function _isBeaconPayload(sendType) {
                // Sync Fetch has the same payload limitation as sendBeacon -- 64kb limit, so treat both as a beacon send
                return sendType === 2 /* EventSendType.SendBeacon */ || sendType === 3 /* EventSendType.SyncFetch */;
            }
            function _adjustSendType(sendType) {
                if (_isUnloading && _isBeaconPayload(sendType)) {
                    sendType = 2 /* EventSendType.SendBeacon */;
                }
                return sendType;
            }
            _self.addHeader = function (name, value) {
                _headers[name] = value;
            };
            _self.removeHeader = function (name) {
                delete _headers[name];
            };
            _self[_DYN_CAN_SEND_REQUEST /* @min:%2ecanSendRequest */] = function () {
                return _hasIdleConnection() && _clockSkewManager[_DYN_ALLOW_REQUEST_SENDIN0 /* @min:%2eallowRequestSending */]();
            };
            _self[_DYN_SEND_QUEUED_REQUESTS /* @min:%2esendQueuedRequests */] = function (sendType, sendReason) {
                if (isUndefined(sendType)) {
                    sendType = 0 /* EventSendType.Batched */;
                }
                if (_isUnloading) {
                    sendType = _adjustSendType(sendType);
                    sendReason = 2 /* SendRequestReason.Unload */;
                }
                if (_canSendPayload(_batchQueue, sendType, 0)) {
                    _sendBatches(_clearQueue(), 0, false, sendType, sendReason || 0 /* SendRequestReason.Undefined */);
                }
            };
            _self.isCompletelyIdle = function () {
                return !_paused && _outstandingRequests === 0 && _batchQueue[_DYN_LENGTH /* @min:%2elength */] === 0;
            };
            _self[_DYN_SET_UNLOADING /* @min:%2esetUnloading */] = function (value) {
                _isUnloading = value;
            };
            _self.addBatch = function (theBatch) {
                if (theBatch && theBatch[_DYN_COUNT /* @min:%2ecount */]() > 0) {
                    // Try and kill the event faster
                    if (_killSwitch.isTenantKilled(theBatch[_DYN_I_KEY /* @min:%2eiKey */]())) {
                        return false;
                    }
                    _batchQueue[_DYN_PUSH /* @min:%2epush */](theBatch);
                }
                return true;
            };
            /**
             * Queue all the remaining requests to be sent. The requests will be
             * sent using HTML5 Beacons if they are available.
             */
            _self.teardown = function () {
                if (_batchQueue[_DYN_LENGTH /* @min:%2elength */] > 0) {
                    _sendBatches(_clearQueue(), 0, true, 2 /* EventSendType.SendBeacon */, 2 /* SendRequestReason.Unload */);
                }
                arrForEach(_unloadHooks, function (hook) {
                    hook && hook.rm && hook.rm();
                });
                _unloadHooks = [];
            };
            /**
             * Pause the sending of requests. No new requests will be sent.
             */
            _self.pause = function () {
                _paused = true;
            };
            /**
             * Resume the sending of requests.
             */
            _self.resume = function () {
                _paused = false;
                _self[_DYN_SEND_QUEUED_REQUESTS /* @min:%2esendQueuedRequests */](0 /* EventSendType.Batched */, 4 /* SendRequestReason.Resumed */);
            };
            /**
             * Sends a request synchronously to the Aria collector. This api is used to send
             * a request containing a single immediate event.
             *
             * @param batch - The request to be sent.
             * @param sendReason   - The token used to send the request.
             */
            _self[_DYN_SEND_SYNCHRONOUS_BAT10 /* @min:%2esendSynchronousBatch */] = function (batch, sendType, sendReason) {
                // This will not take into account the max connections restriction. Since this is sync, we can
                // only send one of this request at a time and thus should not worry about multiple connections
                // being used to send synchronous events.
                // Increment active connection since we are still going to use a connection to send the request.
                if (batch && batch[_DYN_COUNT /* @min:%2ecount */]() > 0) {
                    if (isNullOrUndefined(sendType)) {
                        sendType = 1 /* EventSendType.Synchronous */;
                    }
                    if (_isUnloading) {
                        sendType = _adjustSendType(sendType);
                        sendReason = 2 /* SendRequestReason.Unload */;
                    }
                    // For sync requests we will not wait for the clock skew.
                    _sendBatches([batch], 0, false, sendType, sendReason || 0 /* SendRequestReason.Undefined */);
                }
            };
            function _hasIdleConnection() {
                return !_paused && _outstandingRequests < maxConnections;
            }
            function _clearQueue() {
                var theQueue = _batchQueue;
                _batchQueue = [];
                return theQueue;
            }
            function _canSendPayload(theBatches, sendType, retryCnt) {
                var result = false;
                if (theBatches && theBatches[_DYN_LENGTH /* @min:%2elength */] > 0 && !_paused && _sendInterfaces[sendType] && _serializer) {
                    // Always attempt to send synchronous events don't wait for idle or clockSkew
                    // and don't block retry requests if clockSkew is not yet set
                    result = (sendType !== 0 /* EventSendType.Batched */) || (_hasIdleConnection() && (retryCnt > 0 || _clockSkewManager[_DYN_ALLOW_REQUEST_SENDIN0 /* @min:%2eallowRequestSending */]()));
                }
                return result;
            }
            function _createDebugBatches(theBatches) {
                var values = {};
                if (theBatches) {
                    arrForEach(theBatches, function (theBatch, idx) {
                        values[idx] = {
                            iKey: theBatch[_DYN_I_KEY /* @min:%2eiKey */](),
                            evts: theBatch[_DYN_EVENTS /* @min:%2eevents */]()
                        };
                    });
                }
                return values;
            }
            function _sendBatches(theBatches, retryCount, isTeardown, sendType, sendReason) {
                if (!theBatches || theBatches[_DYN_LENGTH /* @min:%2elength */] === 0) {
                    // Nothing to do
                    return;
                }
                if (_paused) {
                    _sendBatchesNotification(theBatches, 1 /* EventBatchNotificationReason.Paused */, sendType);
                    return;
                }
                // Make sure that if we are unloading the sendType is a supported version
                sendType = _adjustSendType(sendType);
                try {
                    var orgBatches_1 = theBatches;
                    var isSynchronous_1 = sendType !== 0 /* EventSendType.Batched */;
                    doPerf(_core, function () { return "HttpManager:_sendBatches"; }, function (perfEvt) {
                        if (perfEvt) {
                            // Perf Monitoring is enabled, so create a "Quick" copy of the original batches so we still report
                            // the original values as part of the perfEvent. This is because theBatches uses .shift() to remove each
                            // batch as they are processed - removing from the original array, so by the time the _createDebugBatches()
                            // function is called the passed in value has changed and therefore the reported value for the perfEvent is incorrect
                            theBatches = theBatches.slice(0);
                        }
                        var droppedBatches = [];
                        var thePayload = null;
                        var serializationStart = getTime();
                        var sendInterface = _sendInterfaces[sendType] || (isSynchronous_1 ? _sendInterfaces[1 /* EventSendType.Synchronous */] : _sendInterfaces[0 /* EventSendType.Batched */]);
                        var sendTransport = sendInterface && sendInterface[_DYN__TRANSPORT /* @min:%2e_transport */];
                        // Sync Fetch has the same payload limitation as sendBeacon -- 64kb limit
                        var isReducedPayload = _canHaveReducedPayload && (_isUnloading || _isBeaconPayload(sendType) || (sendTransport === 3 /* TransportType.Beacon */ || (sendInterface._isSync && sendTransport === 2 /* TransportType.Fetch */)));
                        while (_canSendPayload(theBatches, sendType, retryCount)) {
                            var theBatch = theBatches.shift();
                            if (theBatch && theBatch[_DYN_COUNT /* @min:%2ecount */]() > 0) {
                                if (!_killSwitch.isTenantKilled(theBatch[_DYN_I_KEY /* @min:%2eiKey */]())) {
                                    // Make sure we have a payload object
                                    thePayload = thePayload || _serializer[_DYN_CREATE_PAYLOAD /* @min:%2ecreatePayload */](retryCount, isTeardown, isSynchronous_1, isReducedPayload, sendReason, sendType);
                                    // Add the batch to the current payload
                                    if (!_serializer.appendPayload(thePayload, theBatch, _maxEvtPerBatch)) {
                                        // Entire batch was not added so send the payload and retry adding this batch
                                        _doPayloadSend(thePayload, serializationStart, getTime(), sendReason);
                                        serializationStart = getTime();
                                        theBatches = [theBatch][_DYN_CONCAT /* @min:%2econcat */](theBatches);
                                        thePayload = null;
                                    }
                                    else if (thePayload.overflow !== null) {
                                        // Total Payload size was exceeded so send the payload and add the unsent as the next batch to send
                                        theBatches = [thePayload.overflow][_DYN_CONCAT /* @min:%2econcat */](theBatches);
                                        thePayload.overflow = null;
                                        _doPayloadSend(thePayload, serializationStart, getTime(), sendReason);
                                        serializationStart = getTime();
                                        thePayload = null;
                                    }
                                }
                                else {
                                    droppedBatches[_DYN_PUSH /* @min:%2epush */](theBatch);
                                }
                            }
                        }
                        // Make sure to flush any remaining payload
                        if (thePayload) {
                            _doPayloadSend(thePayload, serializationStart, getTime(), sendReason);
                        }
                        if (theBatches[_DYN_LENGTH /* @min:%2elength */] > 0) {
                            // Add any unsent batches back to the head of the queue
                            _batchQueue = theBatches[_DYN_CONCAT /* @min:%2econcat */](_batchQueue);
                        }
                        // Now send notification about any dropped events
                        _sendBatchesNotification(droppedBatches, 8004 /* EventBatchNotificationReason.KillSwitch */, sendType);
                    }, function () { return ({ batches: _createDebugBatches(orgBatches_1), retryCount: retryCount, isTeardown: isTeardown, isSynchronous: isSynchronous_1, sendReason: sendReason, useSendBeacon: _isBeaconPayload(sendType), sendType: sendType }); }, !isSynchronous_1);
                }
                catch (ex) {
                    _throwInternal(_logger, 2 /* eLoggingSeverity.WARNING */, 48 /* _eInternalMessageId.CannotSerializeObject */, "Unexpected Exception sending batch: " + dumpObj(ex));
                }
            }
            function _buildRequestDetails(thePayload, useHeaders) {
                var requestDetails = {
                    url: _urlString,
                    hdrs: {},
                    useHdrs: false // Assume no headers
                };
                if (!useHeaders) {
                    // Attempt to map headers to a query string if possible
                    objForEachKey(_headers, function (name, value) {
                        if (_collectorHeaderToQs[name]) {
                            _addRequestDetails(requestDetails, _collectorHeaderToQs[name], value, false);
                        }
                        else {
                            // No mapping, so just include in the headers anyway (may not get sent if using sendBeacon())
                            requestDetails[_DYN_HDRS /* @min:%2ehdrs */][name] = value;
                            requestDetails[_DYN_USE_HDRS /* @min:%2euseHdrs */] = true;
                        }
                    });
                }
                else {
                    // Copy the pre-defined headers into the payload headers
                    requestDetails[_DYN_HDRS /* @min:%2ehdrs */] = extend(requestDetails[_DYN_HDRS /* @min:%2ehdrs */], _headers);
                    requestDetails.useHdrs = (objKeys(requestDetails.hdrs)[_DYN_LENGTH /* @min:%2elength */] > 0);
                }
                _addRequestDetails(requestDetails, STR_CLIENT_ID, "NO_AUTH", useHeaders);
                _addRequestDetails(requestDetails, STR_CLIENT_VERSION, FullVersionString, useHeaders);
                var apiQsKeys = STR_EMPTY;
                arrForEach(thePayload.apiKeys, function (apiKey) {
                    if (apiQsKeys[_DYN_LENGTH /* @min:%2elength */] > 0) {
                        apiQsKeys += ",";
                    }
                    apiQsKeys += apiKey;
                });
                _addRequestDetails(requestDetails, STR_API_KEY, apiQsKeys, useHeaders);
                _addRequestDetails(requestDetails, STR_UPLOAD_TIME, dateNow().toString(), useHeaders);
                var msfpc = _getMsfpc(thePayload);
                if (isValueAssigned(msfpc)) {
                    requestDetails.url += "&ext.intweb.msfpc=" + msfpc;
                }
                if (_clockSkewManager[_DYN_SHOULD_ADD_CLOCK_SKE1 /* @min:%2eshouldAddClockSkewHeaders */]()) {
                    _addRequestDetails(requestDetails, STR_TIME_DELTA_TO_APPLY, _clockSkewManager[_DYN_GET_CLOCK_SKEW_HEADE2 /* @min:%2egetClockSkewHeaderValue */](), useHeaders);
                }
                if (_core[_DYN_GET_WPARAM /* @min:%2egetWParam */]) {
                    var wParam = _core[_DYN_GET_WPARAM /* @min:%2egetWParam */]();
                    if (wParam >= 0) {
                        requestDetails.url += "&w=" + wParam;
                    }
                }
                for (var i = 0; i < _queryStringParameters[_DYN_LENGTH /* @min:%2elength */]; i++) {
                    requestDetails.url += "&" + _queryStringParameters[i].name + "=" + _queryStringParameters[i].value;
                }
                return requestDetails;
            }
            function _setTimingValue(timings, name, value) {
                timings[name] = timings[name] || {};
                timings[name][_postManager.identifier] = value;
            }
            function _doPayloadSend(thePayload, serializationStart, serializationCompleted, sendReason) {
                if (thePayload && thePayload.payloadBlob && thePayload.payloadBlob[_DYN_LENGTH /* @min:%2elength */] > 0) {
                    var useSendHook_1 = !!_sendHook;
                    var sendInterface_1 = _sendInterfaces[thePayload.sendType];
                    // Send all data using a beacon style transport if closing mode is on or channel was teared down
                    if (!_isBeaconPayload(thePayload[_DYN_SEND_TYPE /* @min:%2esendType */]) && thePayload[_DYN_IS_BEACON /* @min:%2eisBeacon */] && thePayload.sendReason === 2 /* SendRequestReason.Unload */) {
                        sendInterface_1 = _sendInterfaces[2 /* EventSendType.SendBeacon */] || _sendInterfaces[3 /* EventSendType.SyncFetch */] || sendInterface_1;
                    }
                    var useHeaders_1 = _useHeaders;
                    // Disable header usage if we know we are using sendBeacon as additional headers are not supported
                    if (thePayload.isBeacon || sendInterface_1[_DYN__TRANSPORT /* @min:%2e_transport */] === 3 /* TransportType.Beacon */) {
                        useHeaders_1 = false;
                    }
                    var requestDetails_1 = _buildRequestDetails(thePayload, useHeaders_1);
                    useHeaders_1 = useHeaders_1 || requestDetails_1[_DYN_USE_HDRS /* @min:%2euseHdrs */];
                    var sendEventStart_1 = getTime();
                    doPerf(_core, function () { return "HttpManager:_doPayloadSend"; }, function () {
                        // Increment the send attempt count and add timings after packaging (So it's not serialized in the 1st attempt)
                        for (var batchLp = 0; batchLp < thePayload.batches[_DYN_LENGTH /* @min:%2elength */]; batchLp++) {
                            var theBatch = thePayload[_DYN_BATCHES /* @min:%2ebatches */][batchLp];
                            var theEvents = theBatch[_DYN_EVENTS /* @min:%2eevents */]();
                            for (var evtLp = 0; evtLp < theEvents[_DYN_LENGTH /* @min:%2elength */]; evtLp++) {
                                var telemetryItem = theEvents[evtLp];
                                if (_enableEventTimings) {
                                    var timings = telemetryItem[_DYN_TIMINGS /* @min:%2etimings */] = telemetryItem[_DYN_TIMINGS /* @min:%2etimings */] || {};
                                    _setTimingValue(timings, "sendEventStart", sendEventStart_1);
                                    _setTimingValue(timings, "serializationStart", serializationStart);
                                    _setTimingValue(timings, "serializationCompleted", serializationCompleted);
                                }
                                telemetryItem[strSendAttempt] > 0 ? telemetryItem[strSendAttempt]++ : telemetryItem[strSendAttempt] = 1;
                            }
                        }
                        // Note: always sending this notification in a synchronous manner.
                        _sendBatchesNotification(thePayload[_DYN_BATCHES /* @min:%2ebatches */], (1000 /* EventBatchNotificationReason.SendingUndefined */ + (sendReason || 0 /* SendRequestReason.Undefined */)), thePayload[_DYN_SEND_TYPE /* @min:%2esendType */], true);
                        // Disabling the use of const because of Issue:
                        // - Task 9227844: [1DS] Some environments and packagers automatically "freeze" objects which are defined as const which causes any mutations to throw
                        // eslint-disable-next-line prefer-const
                        var orgPayloadData = {
                            data: thePayload[_DYN_PAYLOAD_BLOB /* @min:%2epayloadBlob */],
                            urlString: requestDetails_1.url,
                            headers: requestDetails_1[_DYN_HDRS /* @min:%2ehdrs */],
                            _thePayload: thePayload,
                            _sendReason: sendReason,
                            timeout: _xhrTimeout,
                            disableXhrSync: _disableXhrSync,
                            disableFetchKeepAlive: _disableFetchKeepAlive
                        };
                        // Only automatically add the following headers if already sending headers and we are not attempting to avoid an options call
                        if (useHeaders_1) {
                            if (!_hasHeader(orgPayloadData[_DYN_HEADERS /* @min:%2eheaders */], STR_CACHE_CONTROL)) {
                                orgPayloadData[_DYN_HEADERS /* @min:%2eheaders */][STR_CACHE_CONTROL] = DEFAULT_CACHE_CONTROL;
                            }
                            if (!_hasHeader(orgPayloadData[_DYN_HEADERS /* @min:%2eheaders */], STR_CONTENT_TYPE_HEADER)) {
                                orgPayloadData[_DYN_HEADERS /* @min:%2eheaders */][STR_CONTENT_TYPE_HEADER] = DEFAULT_CONTENT_TYPE;
                            }
                        }
                        var sender = null;
                        if (sendInterface_1) {
                            // Send sync requests if the request is immediate or we are tearing down telemetry.
                            sender = function (payload) {
                                // Notify the clock skew manager that we are sending the first request (Potentially blocking all further requests)
                                _clockSkewManager.firstRequestSent();
                                var onComplete = function (status, headers) {
                                    _retryRequestIfNeeded(status, headers, thePayload, sendReason);
                                };
                                var isSync = thePayload[_DYN_IS_TEARDOWN /* @min:%2eisTeardown */] || thePayload.isSync;
                                _sendPostMgr.preparePayload(function (processedPayload) {
                                    try {
                                        sendInterface_1.sendPOST(processedPayload, onComplete, isSync);
                                        if (_sendListener) {
                                            // Send the original payload to the listener
                                            _sendListener(orgPayloadData, processedPayload, isSync, thePayload[_DYN_IS_BEACON /* @min:%2eisBeacon */]);
                                        }
                                    }
                                    catch (ex) {
                                        _doOnComplete(onComplete, 0, {});
                                        _warnToConsole(_logger, "Unexpected exception sending payload. Ex:" + dumpObj(ex));
                                    }
                                }, _zipPayload, payload, isSync);
                            };
                        }
                        doPerf(_core, function () { return "HttpManager:_doPayloadSend.sender"; }, function () {
                            if (sender) {
                                if (thePayload[_DYN_SEND_TYPE /* @min:%2esendType */] === 0 /* EventSendType.Batched */) {
                                    _outstandingRequests++;
                                }
                                // Only call the hook if it's defined and we are not using sendBeacon as additional headers are not supported
                                if (useSendHook_1 && !thePayload.isBeacon && sendInterface_1[_DYN__TRANSPORT /* @min:%2e_transport */] !== 3 /* TransportType.Beacon */) {
                                    // Create a new IPayloadData that is sent into the hook method, so that the hook method
                                    // can't change the object references to the orgPayloadData (it can still change the content -- mainly the headers)
                                    // Disabling the use of const because of Issue:
                                    // - Task 9227844: [1DS] Some environments and packagers automatically "freeze" objects which are defined as const which causes any mutations to throw
                                    // eslint-disable-next-line prefer-const
                                    var hookData_1 = {
                                        data: orgPayloadData.data,
                                        urlString: orgPayloadData.urlString,
                                        headers: extend({}, orgPayloadData[_DYN_HEADERS /* @min:%2eheaders */]),
                                        timeout: orgPayloadData.timeout,
                                        disableXhrSync: orgPayloadData[_DYN_DISABLE_XHR_SYNC /* @min:%2edisableXhrSync */],
                                        disableFetchKeepAlive: orgPayloadData[_DYN_DISABLE_FETCH_KEEP_A6 /* @min:%2edisableFetchKeepAlive */]
                                    };
                                    var senderCalled_1 = false;
                                    doPerf(_core, function () { return "HttpManager:_doPayloadSend.sendHook"; }, function () {
                                        try {
                                            _sendHook(hookData_1, function (payload) {
                                                senderCalled_1 = true;
                                                // Add back the internal properties
                                                if (!_customHttpInterface && !payload[_DYN__THE_PAYLOAD /* @min:%2e_thePayload */]) {
                                                    payload[_DYN__THE_PAYLOAD /* @min:%2e_thePayload */] = payload[_DYN__THE_PAYLOAD /* @min:%2e_thePayload */] || orgPayloadData[_DYN__THE_PAYLOAD /* @min:%2e_thePayload */];
                                                    payload[_DYN__SEND_REASON /* @min:%2e_sendReason */] = payload[_DYN__SEND_REASON /* @min:%2e_sendReason */] || orgPayloadData[_DYN__SEND_REASON /* @min:%2e_sendReason */];
                                                }
                                                sender(payload);
                                            }, thePayload.isSync || thePayload[_DYN_IS_TEARDOWN /* @min:%2eisTeardown */]);
                                        }
                                        catch (ex) {
                                            if (!senderCalled_1) {
                                                // The hook never called the sender -- assume that it never will
                                                sender(orgPayloadData);
                                            }
                                        }
                                    });
                                }
                                else {
                                    sender(orgPayloadData);
                                }
                            }
                        });
                    }, function () { return ({ thePayload: thePayload, serializationStart: serializationStart, serializationCompleted: serializationCompleted, sendReason: sendReason }); }, thePayload.isSync);
                }
                if (thePayload.sizeExceed && thePayload.sizeExceed[_DYN_LENGTH /* @min:%2elength */] > 0) {
                    // Ensure that we send any discard events for oversize events even when there was no payload to send
                    _sendBatchesNotification(thePayload.sizeExceed, 8003 /* EventBatchNotificationReason.SizeLimitExceeded */, thePayload[_DYN_SEND_TYPE /* @min:%2esendType */]);
                }
                if (thePayload.failedEvts && thePayload.failedEvts[_DYN_LENGTH /* @min:%2elength */] > 0) {
                    // Ensure that we send any discard events for events that could not be serialized even when there was no payload to send
                    _sendBatchesNotification(thePayload.failedEvts, 8002 /* EventBatchNotificationReason.InvalidEvent */, thePayload[_DYN_SEND_TYPE /* @min:%2esendType */]);
                }
            }
            function _addEventCompletedTimings(theEvents, sendEventCompleted) {
                if (_enableEventTimings) {
                    arrForEach(theEvents, function (theEvent) {
                        var timings = theEvent[_DYN_TIMINGS /* @min:%2etimings */] = theEvent[_DYN_TIMINGS /* @min:%2etimings */] || {};
                        _setTimingValue(timings, "sendEventCompleted", sendEventCompleted);
                    });
                }
            }
            function _retryRequestIfNeeded(status, headers, thePayload, sendReason) {
                var reason = 9000 /* EventBatchNotificationReason.ResponseFailure */;
                var droppedBatches = null;
                var isRetrying = false;
                var backOffTrans = false;
                try {
                    var shouldRetry = true;
                    if (typeof status !== strUndefined) {
                        if (headers) {
                            _clockSkewManager[_DYN_SET_CLOCK_SKEW /* @min:%2esetClockSkew */](headers[STR_TIME_DELTA_HEADER]);
                            var killDuration = headers[STR_KILL_DURATION_HEADER] || headers["kill-duration-seconds"];
                            arrForEach(_killSwitch[_DYN_SET_KILL_SWITCH_TENA11 /* @min:%2esetKillSwitchTenants */](headers[STR_KILL_TOKENS_HEADER], killDuration), function (killToken) {
                                arrForEach(thePayload[_DYN_BATCHES /* @min:%2ebatches */], function (theBatch) {
                                    if (theBatch[_DYN_I_KEY /* @min:%2eiKey */]() === killToken) {
                                        // Make sure we have initialized the array
                                        droppedBatches = droppedBatches || [];
                                        // Create a copy of the batch with all of the events (and more importantly the action functions)
                                        var removedEvents = theBatch[_DYN_SPLIT /* @min:%2esplit */](0);
                                        // And then remove the events for the payload batch and reduce the actual number of processed
                                        thePayload.numEvents -= removedEvents[_DYN_COUNT /* @min:%2ecount */]();
                                        droppedBatches[_DYN_PUSH /* @min:%2epush */](removedEvents);
                                    }
                                });
                            });
                        }
                        // Disabling triple-equals rule to avoid httpOverrides from failing because they are returning a string value
                        // tslint:disable-next-line:triple-equals
                        if (status == 200 || status == 204) {
                            // Response was successfully sent
                            reason = 200 /* EventBatchNotificationReason.Complete */;
                            return;
                        }
                        if (!retryPolicyShouldRetryForStatus(status) || thePayload.numEvents <= 0) {
                            // Only retry for specific response codes and if there is still events after kill switch processing
                            shouldRetry = false;
                        }
                        // Derive the notification response from the HttpStatus Code
                        reason = 9000 /* EventBatchNotificationReason.ResponseFailure */ + (status % 1000);
                    }
                    if (shouldRetry) {
                        // The events should be retried -- so change notification to requeue them
                        reason = 100 /* EventBatchNotificationReason.RequeueEvents */;
                        var retryCount_1 = thePayload.retryCnt;
                        if (thePayload[_DYN_SEND_TYPE /* @min:%2esendType */] === 0 /* EventSendType.Batched */) {
                            // attempt to resend the entire batch
                            if (retryCount_1 < maxRequestRetriesBeforeBackoff) {
                                isRetrying = true;
                                _doAction(function () {
                                    // try to resend the same batches
                                    if (thePayload[_DYN_SEND_TYPE /* @min:%2esendType */] === 0 /* EventSendType.Batched */) {
                                        // Reduce the outstanding request count (if this was an async request) as we didn't reduce the count
                                        // previously and we are about to reschedule our retry attempt and we want an attempt to send
                                        // to occur, it's also required to ensure that a follow up handleRequestFinished() call occurs
                                        _outstandingRequests--;
                                    }
                                    _sendBatches(thePayload[_DYN_BATCHES /* @min:%2ebatches */], retryCount_1 + 1, thePayload[_DYN_IS_TEARDOWN /* @min:%2eisTeardown */], _isUnloading ? 2 /* EventSendType.SendBeacon */ : thePayload[_DYN_SEND_TYPE /* @min:%2esendType */], 5 /* SendRequestReason.Retry */);
                                }, _isUnloading, retryPolicyGetMillisToBackoffForRetry(retryCount_1));
                            }
                            else {
                                backOffTrans = true;
                                if (_isUnloading) {
                                    // we are unloading so don't try and requeue the events otherwise let the events get requeued and resent during the backoff sending
                                    // This will also cause the events to be purged based on the priority (if necessary)
                                    reason = 8001 /* EventBatchNotificationReason.NonRetryableStatus */;
                                }
                            }
                        }
                    }
                }
                finally {
                    if (!isRetrying) {
                        // Make sure the clockSkewManager doesn't blocking further sending of requests once we have a proper response
                        // This won't override any previously sent clock Skew value
                        _clockSkewManager[_DYN_SET_CLOCK_SKEW /* @min:%2esetClockSkew */]();
                        _handleRequestFinished(thePayload, reason, sendReason, backOffTrans);
                    }
                    _sendBatchesNotification(droppedBatches, 8004 /* EventBatchNotificationReason.KillSwitch */, thePayload[_DYN_SEND_TYPE /* @min:%2esendType */]);
                }
            }
            function _handleRequestFinished(thePayload, batchReason, sendReason, backOffTrans) {
                try {
                    if (backOffTrans) {
                        // Slow down the transmission requests
                        _postManager[_DYN__BACK_OFF_TRANSMISSI12 /* @min:%2e_backOffTransmission */]();
                    }
                    var theBatches = thePayload[_DYN_BATCHES /* @min:%2ebatches */];
                    if (batchReason === 200 /* EventBatchNotificationReason.Complete */) {
                        theBatches = thePayload.sentEvts || thePayload[_DYN_BATCHES /* @min:%2ebatches */];
                        if (!backOffTrans && !thePayload.isSync) {
                            // We have a successful async response, so the lets open the floodgates
                            // The reason for checking isSync is to avoid unblocking if beacon send occurred as it
                            // doesn't wait for a response.
                            _postManager._clearBackOff();
                        }
                        _addCompleteTimings(theBatches);
                    }
                    // Send the notifications synchronously
                    _sendBatchesNotification(theBatches, batchReason, thePayload[_DYN_SEND_TYPE /* @min:%2esendType */], true);
                }
                finally {
                    if (thePayload[_DYN_SEND_TYPE /* @min:%2esendType */] === 0 /* EventSendType.Batched */) {
                        // we always need to decrement this value otherwise the httpmanager locks up and won't send any more events
                        _outstandingRequests--;
                        // Don't try to send additional queued events if this is a retry operation as the retried
                        // response will eventually call _handleRequestFinished for the retried event
                        if (sendReason !== 5 /* SendRequestReason.Retry */) {
                            // Try and send any other queued batched events
                            _self.sendQueuedRequests(thePayload[_DYN_SEND_TYPE /* @min:%2esendType */], sendReason);
                        }
                    }
                }
            }
            function _addCompleteTimings(theBatches) {
                if (_enableEventTimings) {
                    var sendEventCompleted_1 = getTime();
                    arrForEach(theBatches, function (theBatch) {
                        if (theBatch && theBatch[_DYN_COUNT /* @min:%2ecount */]() > 0) {
                            _addEventCompletedTimings(theBatch[_DYN_EVENTS /* @min:%2eevents */](), sendEventCompleted_1);
                        }
                    });
                }
            }
            function _doAction(cb, isSync, interval) {
                if (isSync) {
                    cb();
                }
                else {
                    _timeoutWrapper.set(cb, interval);
                }
            }
            function _getMsfpc(thePayload) {
                for (var lp = 0; lp < thePayload.batches[_DYN_LENGTH /* @min:%2elength */]; lp++) {
                    var msfpc = thePayload[_DYN_BATCHES /* @min:%2ebatches */][lp].Msfpc();
                    if (msfpc) {
                        return encodeURIComponent(msfpc);
                    }
                }
                return STR_EMPTY;
            }
            function _handleCollectorResponse(responseText) {
                var responseHandlers = _responseHandlers;
                try {
                    for (var i = 0; i < responseHandlers[_DYN_LENGTH /* @min:%2elength */]; i++) {
                        try {
                            responseHandlers[i](responseText);
                        }
                        catch (e) {
                            _throwInternal(_logger, 1 /* eLoggingSeverity.CRITICAL */, 519 /* _eExtendedInternalMessageId.PostResponseHandler */, "Response handler failed: " + e);
                        }
                    }
                    if (responseText) {
                        var response = JSON.parse(responseText);
                        if (isValueAssigned(response.webResult) && isValueAssigned(response.webResult[STR_MSFPC])) {
                            // Set cookie
                            _cookieMgr.set("MSFPC", response.webResult[STR_MSFPC], 365 * 86400);
                        }
                    }
                }
                catch (ex) {
                    // Doing nothing
                }
            }
            function _sendBatchesNotification(theBatches, batchReason, sendType, sendSync) {
                if (theBatches && theBatches[_DYN_LENGTH /* @min:%2elength */] > 0 && actions) {
                    var theAction_1 = actions[_getNotificationAction(batchReason)];
                    if (theAction_1) {
                        var isSyncRequest_1 = sendType !== 0 /* EventSendType.Batched */;
                        doPerf(_core, function () { return "HttpManager:_sendBatchesNotification"; }, function () {
                            _doAction(function () {
                                try {
                                    theAction_1.call(actions, theBatches, batchReason, isSyncRequest_1, sendType);
                                }
                                catch (e) {
                                    _throwInternal(_logger, 1 /* eLoggingSeverity.CRITICAL */, 74 /* _eInternalMessageId.NotificationException */, "send request notification failed: " + e);
                                }
                            }, sendSync || isSyncRequest_1, 0);
                        }, function () { return ({ batches: _createDebugBatches(theBatches), reason: batchReason, isSync: isSyncRequest_1, sendSync: sendSync, sendType: sendType }); }, !isSyncRequest_1);
                    }
                }
            }
            function _getNotificationAction(reason) {
                var action = _eventActionMap[reason];
                if (!isValueAssigned(action)) {
                    action = STR_OTHER;
                    if (reason >= 9000 /* EventBatchNotificationReason.ResponseFailure */ && reason <= 9999 /* EventBatchNotificationReason.ResponseFailureMax */) {
                        action = STR_RESPONSE_FAIL;
                    }
                    else if (reason >= 8000 /* EventBatchNotificationReason.EventsDropped */ && reason <= 8999 /* EventBatchNotificationReason.EventsDroppedMax */) {
                        action = STR_DROPPED;
                    }
                    else if (reason >= 1000 /* EventBatchNotificationReason.SendingUndefined */ && reason <= 1999 /* EventBatchNotificationReason.SendingEventMax */) {
                        action = STR_SENDING;
                    }
                }
                return action;
            }
        });
    }
// Removed Stub for HttpManager.prototype.initialize.
// Removed Stub for HttpManager.prototype.addHeader.
// Removed Stub for HttpManager.prototype.removeHeader.
// Removed Stub for HttpManager.prototype.addResponseHandler.
// Removed Stub for HttpManager.prototype.addBatch.
// Removed Stub for HttpManager.prototype.canSendRequest.
// Removed Stub for HttpManager.prototype.sendQueuedRequests.
// Removed Stub for HttpManager.prototype.isCompletelyIdle.
// Removed Stub for HttpManager.prototype.setUnloading.
// Removed Stub for HttpManager.prototype.teardown.
// Removed Stub for HttpManager.prototype.pause.
// Removed Stub for HttpManager.prototype.resume.
// Removed Stub for HttpManager.prototype.sendSynchronousBatch.
// Removed Stub for HttpManager.prototype.serializeOfflineEvt.
// Removed Stub for HttpManager.prototype.getOfflineRequestDetails.
// Removed Stub for HttpManager.prototype.createOneDSPayload.
    // 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.
    HttpManager.__ieDyn=1;

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