"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = exports.IdleTimeout = void 0;

var _propTypes = _interopRequireDefault(require("prop-types"));

var _react = _interopRequireWildcard(require("react"));

var _useInterval = _interopRequireDefault(require("./useInterval"));

var _IdleTimeoutDialog = _interopRequireDefault(require("./IdleTimeoutDialog"));

var _checkPassive = require("./utilities/checkPassive");

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

/**
 *
 * @param timeTilTimeout {number} time in minutes until timeout occurs
 * @returns {string | ReactNode}
 */
var defaultMessageFormatter = function defaultMessageFormatter(timeTilTimeout) {
  var unitOfTime = timeTilTimeout === 1 ? 'minute' : 'minutes';
  return /*#__PURE__*/_react.default.createElement("p", null, "You've been inactive for a while.", /*#__PURE__*/_react.default.createElement("br", null), "Your session will end in", ' ', /*#__PURE__*/_react.default.createElement("strong", null, timeTilTimeout, " ", unitOfTime), ".", /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("br", null), "Select \"Continue session\" below if you want more time.");
}; // local storage variable name


var lastActiveCookieName = 'CMS_DS_IT_LAST_ACTIVE';

var IdleTimeout = function IdleTimeout(_ref) {
  var _ref$closeButtonText = _ref.closeButtonText,
      closeButtonText = _ref$closeButtonText === void 0 ? 'Close' : _ref$closeButtonText,
      _ref$continueSessionT = _ref.continueSessionText,
      continueSessionText = _ref$continueSessionT === void 0 ? 'Continue session' : _ref$continueSessionT,
      _ref$heading = _ref.heading,
      heading = _ref$heading === void 0 ? 'Are you still there?' : _ref$heading,
      _ref$endSessionButton = _ref.endSessionButtonText,
      endSessionButtonText = _ref$endSessionButton === void 0 ? 'Logout' : _ref$endSessionButton,
      _ref$endSessionUrl = _ref.endSessionUrl,
      endSessionUrl = _ref$endSessionUrl === void 0 ? '/logout' : _ref$endSessionUrl,
      _ref$formatMessage = _ref.formatMessage,
      formatMessage = _ref$formatMessage === void 0 ? defaultMessageFormatter : _ref$formatMessage,
      onSessionContinue = _ref.onSessionContinue,
      onSessionForcedEnd = _ref.onSessionForcedEnd,
      onTimeout = _ref.onTimeout,
      _ref$showSessionEndBu = _ref.showSessionEndButton,
      showSessionEndButton = _ref$showSessionEndBu === void 0 ? false : _ref$showSessionEndBu,
      timeToTimeout = _ref.timeToTimeout,
      timeToWarning = _ref.timeToWarning;

  if (timeToWarning > timeToTimeout) {
    console.error('Error in TimeoutManager component. `timeToWarning` is greater or equal to `timeToTimeout`');
  }

  var msBetweenStatusChecks = 30000; // convert minutes to milliseconds

  var msToTimeout = timeToTimeout * 60000;
  var msToWarning = timeToWarning * 60000;

  var _useState = (0, _react.useState)(null),
      _useState2 = _slicedToArray(_useState, 2),
      checkStatusTime = _useState2[0],
      setCheckStatusTime = _useState2[1];

  var _useState3 = (0, _react.useState)(false),
      _useState4 = _slicedToArray(_useState3, 2),
      showWarning = _useState4[0],
      setShowWarning = _useState4[1];

  var _useState5 = (0, _react.useState)(Math.ceil(timeToTimeout - timeToWarning)),
      _useState6 = _slicedToArray(_useState5, 2),
      timeInWarning = _useState6[0],
      setTimeInWarning = _useState6[1]; // cleanup timeouts & intervals


  var clearTimeouts = function clearTimeouts() {
    setCheckStatusTime(null);
  }; // when the countdown for the session ends, clean up, call callback & close modal


  var handleTimeout = function handleTimeout() {
    clearTimeouts();
    removeEventListeners();
    onTimeout();
    setShowWarning(false);
  }; // when it's time to warn the user about idleness,
  // set an interval that updates the modal message


  var handleWarningTimeout = function handleWarningTimeout() {
    removeEventListeners();
    setShowWarning(true);
  };

  var setTimeoutCookies = function setTimeoutCookies() {
    localStorage.setItem(lastActiveCookieName, Date.now().toString());

    if (checkStatusTime === null) {
      setCheckStatusTime(msBetweenStatusChecks);
    }
  }; // have to useCallback so that the function can be removed properly from event listeners


  var resetTimeouts = (0, _react.useCallback)(function () {
    clearTimeouts();
    setTimeoutCookies();
  }, []);

  var removeEventListeners = function removeEventListeners() {
    document.removeEventListener('mousemove', resetTimeouts);
    document.removeEventListener('keypress', resetTimeouts);
  };

  var addEventListeners = function addEventListeners() {
    var passiveSupported = (0, _checkPassive.checkPassiveSupport)();
    var options = passiveSupported ? {
      passive: true
    } : false;
    document.addEventListener('mousemove', resetTimeouts, options);
    document.addEventListener('keypress', resetTimeouts, options);
  };

  var checkWarningStatus = function checkWarningStatus() {
    var lastActiveTime = Number(localStorage.getItem(lastActiveCookieName));
    var now = Date.now();
    var msSinceLastActive = now - lastActiveTime;

    if (msSinceLastActive >= msToTimeout) {
      handleTimeout();
    } else if (!showWarning && msSinceLastActive >= msToWarning) {
      removeEventListeners();
      handleWarningTimeout();
    } else if (showWarning && msSinceLastActive >= msToWarning) {
      // if the warning is showing, update the timeInWarning variable (in minutes)
      var minutesLeft = Math.ceil((msToTimeout - msSinceLastActive) / 60000);
      setTimeInWarning(minutesLeft);
    } else if (showWarning && msSinceLastActive < msToWarning) {
      // if another tab updates the last active time, hide current warning modal
      setShowWarning(false);
    }
  };

  (0, _react.useEffect)(function () {
    setTimeoutCookies(); // event listeners have to be added before status check in case they are removed in status check

    addEventListeners();
    checkWarningStatus();
    return function () {
      clearTimeouts();
      removeEventListeners();
    };
  }, []);
  (0, _react.useEffect)(function () {
    setTimeInWarning(Math.ceil(timeToTimeout - timeToWarning));
    resetTimeouts();
  }, [timeToWarning, timeToTimeout]); // setup interval to check status every 30 seconds

  (0, _useInterval.default)(checkWarningStatus, checkStatusTime);

  var handleSessionContinue = function handleSessionContinue() {
    if (onSessionContinue) {
      onSessionContinue();
    }

    setShowWarning(false);
    setTimeInWarning(Math.ceil(timeToTimeout - timeToWarning));
    resetTimeouts();
    addEventListeners();
  };

  var handleSessionForcedEnd = function handleSessionForcedEnd() {
    if (onSessionForcedEnd) {
      onSessionForcedEnd();
    } else {
      onTimeout();
    }

    clearTimeouts();
    removeEventListeners();
    setShowWarning(false);
  };

  return showWarning ? /*#__PURE__*/_react.default.createElement(_IdleTimeoutDialog.default, {
    continueSessionText: continueSessionText,
    heading: heading,
    endSessionButtonText: endSessionButtonText,
    endSessionUrl: endSessionUrl,
    message: formatMessage(timeInWarning),
    onSessionContinue: handleSessionContinue,
    onSessionForcedEnd: handleSessionForcedEnd,
    showSessionEndButton: showSessionEndButton,
    closeButtonText: closeButtonText,
    onClose: handleSessionContinue
  }) : null;
};

exports.IdleTimeout = IdleTimeout;
IdleTimeout.propTypes = {
  /**
     *  The text for the dialog's 'close' button
     */
  closeButtonText: _propTypes.default.string,

  /**
     * The text for the 'continue session' button in warning dialog.
     */
  continueSessionText: _propTypes.default.string,

  /**
     * The heading text for the warning dialog.
     */
  heading: _propTypes.default.string,

  /**
     * The text for the button that ends the session in warning dialog.
     */
  endSessionButtonText: _propTypes.default.string,

  /**
     * The URL to direct to when the user intentionally ends the session.
     */
  endSessionUrl: _propTypes.default.string,

  /**
     * A formatting function that returns the string to be used in the warning modal.
     * The formatting function is provided the timeTilTimeout (in minutes).
     */
  formatMessage: _propTypes.default.func,

  /**
     * Optional function that is called when the user chooses to keep the session alive. This function is called by the 'continue session' button or the 'close' button.
     * The IdleTimeout component will reset the countdown internally.
     */
  onSessionContinue: _propTypes.default.func,

  /**
     * Optional function that is called when the session is manually ended by user.
     * If not provided, the behavior of `onTimeout` will be used.
     */
  onSessionForcedEnd: _propTypes.default.func,

  /**
     * Function that is called when the timeout countdown reaches zero.
     */
  onTimeout: _propTypes.default.func.isRequired,

  /**
     * Describes if the button to manually end session should be shown in the warning dialog.
     */
  showSessionEndButton: _propTypes.default.bool,

  /**
     * Defines the amount of minutes of idle activity until the session is timed out
     */
  timeToTimeout: _propTypes.default.number.isRequired,

  /**
     * Defines the amount of minutes of idle activity that will trigger the warning message.
     */
  timeToWarning: _propTypes.default.number.isRequired
};
var _default = IdleTimeout;
exports.default = _default;