/*
 * Application Insights JavaScript SDK - Properties Plugin, 3.4.3
 * Copyright (c) Microsoft and contributors. All rights reserved.
 */


import dynamicProto from "@microsoft/dynamicproto-js";
import { _throwInternal, dateNow, dumpObj, getExceptionName, isFunction, newId, onConfigChange, safeGetCookieMgr, safeGetLogger, utlCanUseLocalStorage, utlGetLocalStorage, utlSetLocalStorage } from "@microsoft/applicationinsights-core-js";
import { _DYN_ACQUISITION_DATE, _DYN_AUTOMATIC_SESSION, _DYN_RENEWAL_DATE, _DYN_SESSION_COOKIE_POSTF6 } from "../__DynamicConstants";
var SESSION_COOKIE_NAME = "ai_session";
var ACQUISITION_SPAN = 86400000; // 24 hours in ms
var RENEWAL_SPAN = 1800000; // 30 minutes in ms
var COOKIE_UPDATE_INTERVAL = 60000; // 1 minute in ms
var Session = /** @class */ (function () {
    function Session() {
    }
    return Session;
}());
export { Session };
var _SessionManager = /** @class */ (function () {
    function _SessionManager(config, core, unloadHookContainer) {
        var self = this;
        var _storageNamePrefix;
        var _cookieUpdatedTimestamp;
        var _logger = safeGetLogger(core);
        var _cookieManager = safeGetCookieMgr(core);
        var _sessionExpirationMs;
        var _sessionRenewalMs;
        dynamicProto(_SessionManager, self, function (_self) {
            if (!config) {
                config = {};
            }
            var unloadHook = onConfigChange(config, function (details) {
                _sessionExpirationMs = config.sessionExpirationMs || ACQUISITION_SPAN;
                _sessionRenewalMs = config.sessionRenewalMs || RENEWAL_SPAN;
                // sessionCookiePostfix takes the preference if it is configured, otherwise takes namePrefix if configured.
                var sessionCookiePostfix = config[_DYN_SESSION_COOKIE_POSTF6 /* @min:%2esessionCookiePostfix */] || config.namePrefix || "";
                _storageNamePrefix = SESSION_COOKIE_NAME + sessionCookiePostfix;
            });
            unloadHookContainer && unloadHookContainer.add(unloadHook);
            _self[_DYN_AUTOMATIC_SESSION /* @min:%2eautomaticSession */] = new Session();
            _self.update = function () {
                // Always using Date getTime() as there is a bug in older IE instances that causes the performance timings to have the hi-bit set eg 0x800000000 causing
                // the number to be incorrect.
                var nowMs = dateNow();
                var isExpired = false;
                var session = _self[_DYN_AUTOMATIC_SESSION /* @min:%2eautomaticSession */];
                if (!session.id) {
                    isExpired = !_initializeAutomaticSession(session, nowMs);
                }
                if (!isExpired && _sessionExpirationMs > 0) {
                    var timeSinceAcqMs = nowMs - session[_DYN_ACQUISITION_DATE /* @min:%2eacquisitionDate */];
                    var timeSinceRenewalMs = nowMs - session[_DYN_RENEWAL_DATE /* @min:%2erenewalDate */];
                    isExpired = timeSinceAcqMs < 0 || timeSinceRenewalMs < 0; // expired if the acquisition or last renewal are in the future
                    isExpired = isExpired || timeSinceAcqMs > _sessionExpirationMs; // expired if the time since acquisition is more than session Expiration
                    isExpired = isExpired || timeSinceRenewalMs > _sessionRenewalMs; // expired if the time since last renewal is more than renewal period
                }
                // renew if acquisitionSpan or renewalSpan has elapsed
                if (isExpired) {
                    // update automaticSession so session state has correct id
                    _renew(nowMs);
                }
                else {
                    // do not update the cookie more often than cookieUpdateInterval
                    if (!_cookieUpdatedTimestamp || nowMs - _cookieUpdatedTimestamp > COOKIE_UPDATE_INTERVAL) {
                        _setCookie(session, nowMs);
                    }
                }
            };
            /**
             *  Record the current state of the automatic session and store it in our cookie string format
             *  into the browser's local storage. This is used to restore the session data when the cookie
             *  expires.
             */
            _self.backup = function () {
                var session = _self[_DYN_AUTOMATIC_SESSION /* @min:%2eautomaticSession */];
                _setStorage(session.id, session[_DYN_ACQUISITION_DATE /* @min:%2eacquisitionDate */], session[_DYN_RENEWAL_DATE /* @min:%2erenewalDate */]);
            };
            /**
             * Use config.namePrefix + ai_session cookie data or local storage data (when the cookie is unavailable) to
             * initialize the automatic session.
             * @returns true if values set otherwise false
             */
            function _initializeAutomaticSession(session, now) {
                var isValid = false;
                var cookieValue = _cookieManager.get(_storageNamePrefix);
                if (cookieValue && isFunction(cookieValue.split)) {
                    isValid = _initializeAutomaticSessionWithData(session, cookieValue);
                }
                else {
                    // There's no cookie, but we might have session data in local storage
                    // This can happen if the session expired or the user actively deleted the cookie
                    // We only want to recover data if the cookie is missing from expiry. We should respect the user's wishes if the cookie was deleted actively.
                    // The User class handles this for us and deletes our local storage object if the persistent user cookie was removed.
                    var storageValue = utlGetLocalStorage(_logger, _storageNamePrefix);
                    if (storageValue) {
                        isValid = _initializeAutomaticSessionWithData(session, storageValue);
                    }
                }
                return isValid || !!session.id;
            }
            /**
             * Extract id, acquisitionDate, and renewalDate from an ai_session payload string and
             * use this data to initialize automaticSession.
             *
             * @param sessionData - The string stored in an ai_session cookie or local storage backup
             * @returns true if values set otherwise false
             */
            function _initializeAutomaticSessionWithData(session, sessionData) {
                var isValid = false;
                var sessionReset = ", session will be reset";
                var tokens = sessionData.split("|");
                if (tokens.length >= 2) {
                    try {
                        var acqMs = +tokens[1] || 0;
                        var renewalMs = +tokens[2] || 0;
                        if (isNaN(acqMs) || acqMs <= 0) {
                            _throwInternal(_logger, 2 /* eLoggingSeverity.WARNING */, 27 /* _eInternalMessageId.SessionRenewalDateIsZero */, "AI session acquisition date is 0" + sessionReset);
                        }
                        else if (isNaN(renewalMs) || renewalMs <= 0) {
                            _throwInternal(_logger, 2 /* eLoggingSeverity.WARNING */, 27 /* _eInternalMessageId.SessionRenewalDateIsZero */, "AI session renewal date is 0" + sessionReset);
                        }
                        else if (tokens[0]) {
                            // Everything looks valid so set the values
                            session.id = tokens[0];
                            session[_DYN_ACQUISITION_DATE /* @min:%2eacquisitionDate */] = acqMs;
                            session[_DYN_RENEWAL_DATE /* @min:%2erenewalDate */] = renewalMs;
                            isValid = true;
                        }
                    }
                    catch (e) {
                        _throwInternal(_logger, 1 /* eLoggingSeverity.CRITICAL */, 9 /* _eInternalMessageId.ErrorParsingAISessionCookie */, "Error parsing ai_session value [" + (sessionData || "") + "]" + sessionReset + " - " + getExceptionName(e), { exception: dumpObj(e) });
                    }
                }
                return isValid;
            }
            function _renew(nowMs) {
                var getNewId = config.getNewId || newId;
                _self[_DYN_AUTOMATIC_SESSION /* @min:%2eautomaticSession */].id = getNewId(config.idLength || 22);
                _self[_DYN_AUTOMATIC_SESSION /* @min:%2eautomaticSession */][_DYN_ACQUISITION_DATE /* @min:%2eacquisitionDate */] = nowMs;
                _setCookie(_self[_DYN_AUTOMATIC_SESSION /* @min:%2eautomaticSession */], nowMs);
                // If this browser does not support local storage, fire an internal log to keep track of it at this point
                if (!utlCanUseLocalStorage()) {
                    _throwInternal(_logger, 2 /* eLoggingSeverity.WARNING */, 0 /* _eInternalMessageId.BrowserDoesNotSupportLocalStorage */, "Browser does not support local storage. Session durations will be inaccurate.");
                }
            }
            function _setCookie(session, nowMs) {
                var acq = session[_DYN_ACQUISITION_DATE /* @min:%2eacquisitionDate */];
                session[_DYN_RENEWAL_DATE /* @min:%2erenewalDate */] = nowMs;
                var renewalPeriodMs = _sessionRenewalMs;
                // Set cookie to expire after the session expiry time passes or the session renewal deadline, whichever is sooner
                // Expiring the cookie will cause the session to expire even if the user isn't on the page
                var acqTimeLeftMs = (acq + _sessionExpirationMs) - nowMs;
                var cookie = [session.id, acq, nowMs];
                var maxAgeSec = 0;
                if (acqTimeLeftMs < renewalPeriodMs) {
                    maxAgeSec = acqTimeLeftMs / 1000;
                }
                else {
                    maxAgeSec = renewalPeriodMs / 1000;
                }
                var cookieDomain = config.cookieDomain || null;
                // if sessionExpirationMs is set to 0, it means the expiry is set to 0 for this session cookie
                // A cookie with 0 expiry in the session cookie will never expire for that browser session.  If the browser is closed the cookie expires.
                // Depending on the browser, another instance does not inherit this cookie, however, another tab will
                _cookieManager.set(_storageNamePrefix, cookie.join("|"), _sessionExpirationMs > 0 ? maxAgeSec : null, cookieDomain);
                _cookieUpdatedTimestamp = nowMs;
            }
            function _setStorage(guid, acq, renewal) {
                // Keep data in local storage to retain the last session id, allowing us to cleanly end the session when it expires
                // Browsers that don't support local storage won't be able to end sessions cleanly from the client
                // The server will notice this and end the sessions itself, with loss of accurate session duration
                utlSetLocalStorage(_logger, _storageNamePrefix, [guid, acq, renewal].join("|"));
            }
        });
    }
// Removed Stub for _SessionManager.prototype.update.
// Removed Stub for _SessionManager.prototype.backup.
    // 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.
    _SessionManager.__ieDyn=1;

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