"use strict";

var _Object$keys2 = require("@babel/runtime-corejs2/core-js/object/keys");
var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptors");
var _Object$defineProperties = require("@babel/runtime-corejs2/core-js/object/define-properties");
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
var _Array$from = require("@babel/runtime-corejs2/core-js/array/from");
var _Symbol = require("@babel/runtime-corejs2/core-js/symbol");
var _Symbol$iterator = require("@babel/runtime-corejs2/core-js/symbol/iterator");
var _Array$isArray = require("@babel/runtime-corejs2/core-js/array/is-array");
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
  value: true
});
exports.createRegistration = exports.Registration = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
var _now = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/date/now"));
var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
var _values = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/values"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
var _constants = require("../../common/constants");
var _common = require("../../common");
var _webWorkerStr = _interopRequireDefault(require("./webWorkerStr"));
var _types = require("../../Metrics/types");
var _Metrics = require("../../Metrics");
var _calling = require("../calling");
var _Logger = _interopRequireDefault(require("../../Logger"));
var _SDKConnector = _interopRequireDefault(require("../../SDKConnector"));
var _types2 = require("../../common/types");
var _constants2 = require("../constants");
var _types3 = require("../line/types");
var _request = require("../utils/request");
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof _Symbol && r[_Symbol$iterator] || r["@@iterator"]; if (!t) { if (_Array$isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? _Array$from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function ownKeys(e, r) { var t = _Object$keys2(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
/**
 *
 */
var Registration = exports.Registration = /*#__PURE__*/function () {
  /**
   */
  function Registration(webex, serviceData, mutex, lineEmitter, logLevel, jwe) {
    (0, _classCallCheck2.default)(this, Registration);
    (0, _defineProperty2.default)(this, "sdkConnector", void 0);
    (0, _defineProperty2.default)(this, "webex", void 0);
    (0, _defineProperty2.default)(this, "userId", '');
    (0, _defineProperty2.default)(this, "serviceData", void 0);
    (0, _defineProperty2.default)(this, "failback429RetryAttempts", void 0);
    (0, _defineProperty2.default)(this, "registrationStatus", void 0);
    (0, _defineProperty2.default)(this, "failbackTimer", void 0);
    (0, _defineProperty2.default)(this, "activeMobiusUrl", void 0);
    (0, _defineProperty2.default)(this, "rehomingIntervalMin", void 0);
    (0, _defineProperty2.default)(this, "rehomingIntervalMax", void 0);
    (0, _defineProperty2.default)(this, "mutex", void 0);
    (0, _defineProperty2.default)(this, "metricManager", void 0);
    (0, _defineProperty2.default)(this, "lineEmitter", void 0);
    (0, _defineProperty2.default)(this, "callManager", void 0);
    (0, _defineProperty2.default)(this, "deviceInfo", {});
    (0, _defineProperty2.default)(this, "primaryMobiusUris", void 0);
    (0, _defineProperty2.default)(this, "backupMobiusUris", void 0);
    (0, _defineProperty2.default)(this, "registerRetry", false);
    (0, _defineProperty2.default)(this, "reconnectPending", false);
    (0, _defineProperty2.default)(this, "jwe", void 0);
    (0, _defineProperty2.default)(this, "isCCFlow", false);
    (0, _defineProperty2.default)(this, "failoverImmediately", false);
    (0, _defineProperty2.default)(this, "retryAfter", void 0);
    (0, _defineProperty2.default)(this, "scheduled429Retry", false);
    (0, _defineProperty2.default)(this, "webWorker", void 0);
    (0, _defineProperty2.default)(this, "apiRequest", void 0);
    this.jwe = jwe;
    this.sdkConnector = _SDKConnector.default;
    this.serviceData = serviceData;
    this.isCCFlow = serviceData.indicator === _types2.ServiceIndicator.CONTACT_CENTER;
    if (!this.sdkConnector.getWebex()) {
      _SDKConnector.default.setWebex(webex);
    }
    this.webex = this.sdkConnector.getWebex();
    this.userId = this.webex.internal.device.userId;
    this.registrationStatus = _types2.RegistrationStatus.IDLE;
    this.failback429RetryAttempts = 0;
    _Logger.default.setLogger(logLevel, _constants2.REGISTRATION_FILE);
    this.rehomingIntervalMin = _constants2.DEFAULT_REHOMING_INTERVAL_MIN;
    this.rehomingIntervalMax = _constants2.DEFAULT_REHOMING_INTERVAL_MAX;
    this.mutex = mutex;
    this.callManager = (0, _calling.getCallManager)(this.webex, serviceData.indicator);
    this.metricManager = (0, _Metrics.getMetricManager)(this.webex, serviceData.indicator);
    this.lineEmitter = lineEmitter;
    this.primaryMobiusUris = [];
    this.backupMobiusUris = [];
    this.apiRequest = _request.APIRequest.getInstance({
      webex: this.webex
    });
  }
  return (0, _createClass2.default)(Registration, [{
    key: "getServerType",
    value: function getServerType(url) {
      var _this$backupMobiusUri;
      return this.primaryMobiusUris.includes(url) && 'PRIMARY' || ((_this$backupMobiusUri = this.backupMobiusUris) === null || _this$backupMobiusUri === void 0 ? void 0 : _this$backupMobiusUri.includes(url)) && 'BACKUP' || 'UNKNOWN';
    }
  }, {
    key: "getFailoverCacheKey",
    value: function getFailoverCacheKey() {
      return "".concat(_constants2.FAILOVER_CACHE_PREFIX, ".").concat(this.userId || 'unknown');
    }
  }, {
    key: "saveFailoverState",
    value: function saveFailoverState(failoverState) {
      try {
        localStorage.setItem(this.getFailoverCacheKey(), (0, _stringify.default)(failoverState));
      } catch (error) {
        _Logger.default.warn("Storing failover state in cache failed with error: ".concat(String(error)), {
          file: _constants2.REGISTRATION_FILE,
          method: 'saveFailoverState'
        });
      }
    }
  }, {
    key: "clearFailoverState",
    value: function clearFailoverState() {
      try {
        localStorage.removeItem(this.getFailoverCacheKey());
      } catch (_unused) {
        _Logger.default.warn('Clearing failover state from localStorage failed', {
          file: _constants2.REGISTRATION_FILE,
          method: 'clearFailoverState'
        });
      }
    }
  }, {
    key: "resumeFailover",
    value: function () {
      var _resumeFailover = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee() {
        var cachedState, failoverState, currentTime, newElapsed, _t;
        return _regenerator.default.wrap(function (_context) {
          while (1) switch (_context.prev = _context.next) {
            case 0:
              _context.prev = 0;
              cachedState = localStorage.getItem(this.getFailoverCacheKey());
              failoverState = cachedState ? JSON.parse(cachedState) : undefined;
              if (!(failoverState && !this.isDeviceRegistered())) {
                _context.next = 2;
                break;
              }
              currentTime = Math.floor((0, _now.default)() / 1000);
              newElapsed = failoverState.timeElapsed + (currentTime - failoverState.retryScheduledTime);
              this.clearFailoverState();
              _context.next = 1;
              return this.startFailoverTimer(failoverState.attempt, newElapsed);
            case 1:
              return _context.abrupt("return", true);
            case 2:
              _context.next = 4;
              break;
            case 3:
              _context.prev = 3;
              _t = _context["catch"](0);
              _Logger.default.warn("No failover state found in cache", {
                file: _constants2.REGISTRATION_FILE,
                method: 'triggerRegistration'
              });
            case 4:
              return _context.abrupt("return", false);
            case 5:
            case "end":
              return _context.stop();
          }
        }, _callee, this, [[0, 3]]);
      }));
      function resumeFailover() {
        return _resumeFailover.apply(this, arguments);
      }
      return resumeFailover;
    }()
  }, {
    key: "getActiveMobiusUrl",
    value: function getActiveMobiusUrl() {
      return this.activeMobiusUrl;
    }
  }, {
    key: "setActiveMobiusUrl",
    value: function setActiveMobiusUrl(url) {
      _Logger.default.info("".concat(_constants.METHOD_START_MESSAGE, " with ").concat(url), {
        method: _constants2.METHODS.UPDATE_ACTIVE_MOBIUS,
        file: _constants2.REGISTRATION_FILE
      });
      this.activeMobiusUrl = url;
      this.callManager.updateActiveMobius(url);
    }

    /**
     * Populate deviceInfo using a devices response body.
     */
  }, {
    key: "setDeviceInfo",
    value: function setDeviceInfo(devicesInfo) {
      var _devicesInfo$devices = (0, _slicedToArray2.default)(devicesInfo.devices, 1),
        device = _devicesInfo$devices[0];
      this.deviceInfo = {
        userId: devicesInfo.userId,
        device: device,
        devices: devicesInfo.devices
      };
    }
  }, {
    key: "setMobiusServers",
    value: function setMobiusServers(primaryMobiusUris, backupMobiusUris) {
      _Logger.default.log(_constants.METHOD_START_MESSAGE, {
        method: _constants2.METHODS.SET_MOBIUS_SERVERS,
        file: _constants2.REGISTRATION_FILE
      });
      this.primaryMobiusUris = primaryMobiusUris;
      this.backupMobiusUris = backupMobiusUris;
    }

    /**
     * Implementation of delete device.
     *
     */
  }, {
    key: "deleteRegistration",
    value: (function () {
      var _deleteRegistration = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2(url, deviceId, deviceUrl) {
        var response, requestObj, _t2;
        return _regenerator.default.wrap(function (_context2) {
          while (1) switch (_context2.prev = _context2.next) {
            case 0:
              requestObj = {
                uri: "".concat(url).concat(_constants2.DEVICES_ENDPOINT_RESOURCE, "/").concat(deviceId),
                method: _types2.HTTP_METHODS.DELETE,
                headers: (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _constants2.CISCO_DEVICE_URL, deviceUrl), _constants2.SPARK_USER_AGENT, _constants2.CALLING_USER_AGENT),
                service: _types2.ALLOWED_SERVICES.MOBIUS
              };
              if (this.apiRequest.isSocketEnabled()) {
                // @ts-ignore - body is added for mobius wss support, it is not used for mobius http
                requestObj.body = {
                  deviceId: deviceId
                };
              }
              _context2.prev = 1;
              _context2.next = 2;
              return this.apiRequest.makeRequest(requestObj);
            case 2:
              response = _context2.sent;
              _context2.next = 4;
              break;
            case 3:
              _context2.prev = 3;
              _t2 = _context2["catch"](1);
              _Logger.default.warn("Delete failed with Mobius: ".concat((0, _stringify.default)(_t2)), {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.DELETE_REGISTRATION
              });
              _context2.next = 4;
              return (0, _common.uploadLogs)();
            case 4:
              this.setStatus(_types2.RegistrationStatus.INACTIVE);
              this.lineEmitter(_types3.LINE_EVENTS.UNREGISTERED);
              return _context2.abrupt("return", response);
            case 5:
            case "end":
              return _context2.stop();
          }
        }, _callee2, this, [[1, 3]]);
      }));
      function deleteRegistration(_x, _x2, _x3) {
        return _deleteRegistration.apply(this, arguments);
      }
      return deleteRegistration;
    }()
    /**
     * Implementation of POST request for device registration.
     *
     */
    )
  }, {
    key: "postRegistration",
    value: (function () {
      var _postRegistration = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3(url) {
        var deviceInfo;
        return _regenerator.default.wrap(function (_context3) {
          while (1) switch (_context3.prev = _context3.next) {
            case 0:
              deviceInfo = {
                userId: this.userId,
                clientDeviceUri: this.webex.internal.device.url,
                serviceData: this.jwe ? _objectSpread(_objectSpread({}, this.serviceData), {}, {
                  jwe: this.jwe
                }) : this.serviceData
              };
              return _context3.abrupt("return", this.apiRequest.makeRequest({
                uri: "".concat(url, "device"),
                method: _types2.HTTP_METHODS.POST,
                headers: (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _constants2.CISCO_DEVICE_URL, deviceInfo.clientDeviceUri), _constants2.SPARK_USER_AGENT, _constants2.CALLING_USER_AGENT),
                body: deviceInfo,
                service: _types2.ALLOWED_SERVICES.MOBIUS
              }));
            case 1:
            case "end":
              return _context3.stop();
          }
        }, _callee3, this);
      }));
      function postRegistration(_x4) {
        return _postRegistration.apply(this, arguments);
      }
      return postRegistration;
    }()
    /**
     * Re-attempts registration with the mobius url it was last registered
     * to, that mobius url is expected to be updated already in this.activeMobiusUrl.
     */
    )
  }, {
    key: "restorePreviousRegistration",
    value: (function () {
      var _restorePreviousRegistration = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee5(caller) {
        var _this = this;
        var loggerContext, abort;
        return _regenerator.default.wrap(function (_context5) {
          while (1) switch (_context5.prev = _context5.next) {
            case 0:
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.RESTORE_PREVIOUS_REGISTRATION
              };
              _Logger.default.info("".concat(_constants.METHOD_START_MESSAGE, " - caller: ").concat(caller, ", activeMobiusUrl: ").concat(this.activeMobiusUrl), loggerContext);
              abort = false;
              if (!(this.apiRequest.isSocketEnabled() && "".concat(this.apiRequest.getConnectedWebSocketUrl(), "/") !== this.activeMobiusUrl)) {
                _context5.next = 1;
                break;
              }
              _Logger.default.info("Disconnecting from Mobius socket to restore previous registration.", {
                file: _constants2.REGISTRATION_FILE,
                method: 'restorePreviousRegistration'
              });
              _context5.next = 1;
              return this.apiRequest.disconnectFromMobiusSocket({
                code: 3050,
                reason: 'done (permanent)'
              });
            case 1:
              if (!this.activeMobiusUrl) {
                _context5.next = 7;
                break;
              }
              _context5.next = 2;
              return this.attemptRegistrationWithServers(caller, [this.activeMobiusUrl]);
            case 2:
              abort = _context5.sent;
              if (!this.retryAfter) {
                _context5.next = 7;
                break;
              }
              if (!(this.retryAfter < _constants2.RETRY_TIMER_UPPER_LIMIT)) {
                _context5.next = 3;
                break;
              }
              // If retry-after is less than threshold, honor it and schedule retry
              setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4() {
                return _regenerator.default.wrap(function (_context4) {
                  while (1) switch (_context4.prev = _context4.next) {
                    case 0:
                      _context4.next = 1;
                      return _this.restartRegistration(caller);
                    case 1:
                    case "end":
                      return _context4.stop();
                  }
                }, _callee4);
              })), this.retryAfter * 1000);
              _context5.next = 6;
              break;
            case 3:
              if (!(this.primaryMobiusUris.includes(this.activeMobiusUrl) && this.backupMobiusUris.length > 0)) {
                _context5.next = 5;
                break;
              }
              _context5.next = 4;
              return this.attemptRegistrationWithServers(caller, this.backupMobiusUris);
            case 4:
              abort = _context5.sent;
              _context5.next = 6;
              break;
            case 5:
              _context5.next = 6;
              return this.restartRegistration(caller);
            case 6:
              this.retryAfter = undefined;
              _Logger.default.log("restorePreviousRegistration completed via 429 retry-after path - caller: ".concat(caller), loggerContext);
              return _context5.abrupt("return", true);
            case 7:
              _Logger.default.log("restorePreviousRegistration completed - caller: ".concat(caller, ", deviceRegistered: ").concat(this.isDeviceRegistered(), ", abort: ").concat(abort), loggerContext);
              return _context5.abrupt("return", abort);
            case 8:
            case "end":
              return _context5.stop();
          }
        }, _callee5, this);
      }));
      function restorePreviousRegistration(_x5) {
        return _restorePreviousRegistration.apply(this, arguments);
      }
      return restorePreviousRegistration;
    }()
    /**
     * Callback for handling 404 response from the server for register keepalive
     */
    )
  }, {
    key: "handle404KeepaliveFailure",
    value: (function () {
      var _handle404KeepaliveFailure = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee6(caller) {
        var loggerContext, abort;
        return _regenerator.default.wrap(function (_context6) {
          while (1) switch (_context6.prev = _context6.next) {
            case 0:
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.HANDLE_404_KEEPALIVE_FAILURE
              };
              _Logger.default.info("".concat(_constants.METHOD_START_MESSAGE, " - caller: ").concat(caller), loggerContext);
              if (!(caller === _constants2.KEEPALIVE_UTIL)) {
                _context6.next = 4;
                break;
              }
              _context6.next = 1;
              return this.attemptRegistrationWithServers(caller);
            case 1:
              abort = _context6.sent;
              if (!(!abort && !this.isDeviceRegistered())) {
                _context6.next = 3;
                break;
              }
              _Logger.default.warn('Keepalive 404 recovery: re-registration did not complete, starting failover timer', loggerContext);
              _context6.next = 2;
              return this.startFailoverTimer();
            case 2:
              _context6.next = 4;
              break;
            case 3:
              _Logger.default.log("Keepalive 404 recovery handled - deviceRegistered: ".concat(this.isDeviceRegistered(), ", abort: ").concat(abort), loggerContext);
            case 4:
            case "end":
              return _context6.stop();
          }
        }, _callee6, this);
      }));
      function handle404KeepaliveFailure(_x6) {
        return _handle404KeepaliveFailure.apply(this, arguments);
      }
      return handle404KeepaliveFailure;
    }()
    /**
     * Callback for handling 429 retry response from the server
     */
    )
  }, {
    key: "handle429Retry",
    value: (function () {
      var _handle429Retry = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee8(retryAfter, caller) {
        var _this2 = this;
        var interval, abort;
        return _regenerator.default.wrap(function (_context8) {
          while (1) switch (_context8.prev = _context8.next) {
            case 0:
              if (!(caller === _constants2.FAILBACK_UTIL)) {
                _context8.next = 4;
                break;
              }
              if (!(this.failback429RetryAttempts >= _constants2.REG_FAILBACK_429_MAX_RETRIES)) {
                _context8.next = 1;
                break;
              }
              return _context8.abrupt("return");
            case 1:
              this.clearFailbackTimer();
              this.failback429RetryAttempts += 1;
              _Logger.default.log("Received 429 while rehoming, 429 retry count : ".concat(this.failback429RetryAttempts), {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.REG_429_RETRY_UTIL
              });
              interval = this.getRegRetryInterval(this.failback429RetryAttempts);
              this.startFailbackTimer(interval);
              this.scheduled429Retry = true;
              _context8.next = 2;
              return this.restorePreviousRegistration(_constants2.REG_429_RETRY_UTIL);
            case 2:
              abort = _context8.sent;
              if (!(!abort && !this.isDeviceRegistered())) {
                _context8.next = 3;
                break;
              }
              _context8.next = 3;
              return this.restartRegistration(_constants2.REG_429_RETRY_UTIL);
            case 3:
              _context8.next = 5;
              break;
            case 4:
              if (caller === _constants2.KEEPALIVE_UTIL) {
                this.clearKeepaliveTimer();
                setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee7() {
                  var _this2$deviceInfo$dev;
                  return _regenerator.default.wrap(function (_context7) {
                    while (1) switch (_context7.prev = _context7.next) {
                      case 0:
                        _Logger.default.log("Resuming keepalive after ".concat(retryAfter, " seconds"), {
                          file: _constants2.REGISTRATION_FILE,
                          method: _constants2.REG_429_RETRY_UTIL
                        });

                        // Resume the keepalive after waiting for the retry after period
                        _context7.next = 1;
                        return _this2.startKeepaliveTimer((_this2$deviceInfo$dev = _this2.deviceInfo.device) === null || _this2$deviceInfo$dev === void 0 ? void 0 : _this2$deviceInfo$dev.uri, _this2.deviceInfo.keepaliveInterval, 'UNKNOWN');
                      case 1:
                      case "end":
                        return _context7.stop();
                    }
                  }, _callee7);
                })), (retryAfter - Number(this.deviceInfo.keepaliveInterval || 0)) * 1000);
              } else {
                this.retryAfter = retryAfter;
              }
            case 5:
            case "end":
              return _context8.stop();
          }
        }, _callee8, this);
      }));
      function handle429Retry(_x7, _x8) {
        return _handle429Retry.apply(this, arguments);
      }
      return handle429Retry;
    }()
    /**
     * Calculates and returns a random interval value using input argument
     * attempt as the variable factor.
     *
     *                  attempted already.
     */
    )
  }, {
    key: "getRegRetryInterval",
    value: function getRegRetryInterval() {
      var attempt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
      return _constants2.BASE_REG_RETRY_TIMER_VAL_IN_SEC + Math.pow(_constants2.BASE_REG_TIMER_MFACTOR, attempt) + Math.floor((Math.random() * (_constants2.REG_RANDOM_T_FACTOR_UPPER_LIMIT - _constants2.SEC_TO_MSEC_MFACTOR + 1) + _constants2.SEC_TO_MSEC_MFACTOR) / _constants2.SEC_TO_MSEC_MFACTOR);
    }

    /**
     * Schedules registration retry with primary mobius servers at a random
     * interval calculated based on the number of times registration retry is already done
     * Once the time taken since the beginning of retry attempt exceeds the
     * retry threshold, it switches over to backup mobius servers.
     *
     */
  }, {
    key: "startFailoverTimer",
    value: (function () {
      var _startFailoverTimer = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee11() {
        var _this3 = this;
        var attempt,
          timeElapsed,
          loggerContext,
          interval,
          TIMER_THRESHOLD,
          excessVal,
          abort,
          scheduledTime,
          _args11 = arguments;
        return _regenerator.default.wrap(function (_context11) {
          while (1) switch (_context11.prev = _context11.next) {
            case 0:
              attempt = _args11.length > 0 && _args11[0] !== undefined ? _args11[0] : 1;
              timeElapsed = _args11.length > 1 && _args11[1] !== undefined ? _args11[1] : 0;
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.FAILOVER_UTIL
              };
              interval = this.getRegRetryInterval(attempt);
              TIMER_THRESHOLD = _constants2.REG_TRY_BACKUP_TIMER_VAL_IN_SEC;
              if (timeElapsed + interval > TIMER_THRESHOLD) {
                excessVal = timeElapsed + interval - TIMER_THRESHOLD;
                interval -= excessVal;
              }
              if (this.retryAfter != null && interval < this.retryAfter) {
                this.failoverImmediately = this.retryAfter + timeElapsed > TIMER_THRESHOLD;
              }
              if (!(interval > _constants2.BASE_REG_RETRY_TIMER_VAL_IN_SEC && !this.failoverImmediately)) {
                _context11.next = 1;
                break;
              }
              scheduledTime = Math.floor((0, _now.default)() / 1000);
              if (this.retryAfter != null) {
                interval = Math.max(interval, this.retryAfter);
              }
              this.saveFailoverState({
                attempt: attempt,
                timeElapsed: timeElapsed,
                retryScheduledTime: scheduledTime,
                serverType: 'primary'
              });
              setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee0() {
                return _regenerator.default.wrap(function (_context0) {
                  while (1) switch (_context0.prev = _context0.next) {
                    case 0:
                      _context0.next = 1;
                      return _this3.mutex.runExclusive(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee9() {
                        var currentTime;
                        return _regenerator.default.wrap(function (_context9) {
                          while (1) switch (_context9.prev = _context9.next) {
                            case 0:
                              _context9.next = 1;
                              return _this3.attemptRegistrationWithServers(_constants2.FAILOVER_UTIL);
                            case 1:
                              abort = _context9.sent;
                              currentTime = Math.floor((0, _now.default)() / 1000);
                              if (!(!abort && !_this3.isDeviceRegistered())) {
                                _context9.next = 2;
                                break;
                              }
                              _context9.next = 2;
                              return _this3.startFailoverTimer(attempt + 1, timeElapsed + (currentTime - scheduledTime));
                            case 2:
                            case "end":
                              return _context9.stop();
                          }
                        }, _callee9);
                      })));
                    case 1:
                    case "end":
                      return _context0.stop();
                  }
                }, _callee0);
              })), interval * _constants2.SEC_TO_MSEC_MFACTOR);
              _Logger.default.log("Scheduled retry with primary in ".concat(interval, " seconds, number of attempts : ").concat(attempt), loggerContext);
              _context11.next = 7;
              break;
            case 1:
              if (!this.backupMobiusUris.length) {
                _context11.next = 5;
                break;
              }
              if (!this.apiRequest.isSocketEnabled()) {
                _context11.next = 3;
                break;
              }
              _Logger.default.info('Disconnecting from primary Mobius socket for failover to backup servers', loggerContext);
              _context11.next = 2;
              return this.apiRequest.disconnectFromMobiusSocket({
                code: 3050,
                reason: 'done (permanent)'
              });
            case 2:
              _Logger.default.log('Mobius socket disconnect complete prior to backup failover', loggerContext);
            case 3:
              this.saveFailoverState({
                attempt: attempt,
                timeElapsed: timeElapsed,
                retryScheduledTime: Math.floor((0, _now.default)() / 1000),
                serverType: 'backup'
              });
              _Logger.default.info('Failing over to backup servers.', loggerContext);
              this.failoverImmediately = false;
              _context11.next = 4;
              return this.attemptRegistrationWithServers(_constants2.FAILOVER_UTIL, this.backupMobiusUris);
            case 4:
              abort = _context11.sent;
              if (!abort && !this.isDeviceRegistered()) {
                interval = this.getRegRetryInterval();
                if (this.retryAfter != null && this.retryAfter < _constants2.RETRY_TIMER_UPPER_LIMIT) {
                  interval = interval < this.retryAfter ? this.retryAfter : interval;
                }
                setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee10() {
                  return _regenerator.default.wrap(function (_context10) {
                    while (1) switch (_context10.prev = _context10.next) {
                      case 0:
                        _context10.next = 1;
                        return _this3.mutex.runExclusive(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee1() {
                          return _regenerator.default.wrap(function (_context1) {
                            while (1) switch (_context1.prev = _context1.next) {
                              case 0:
                                _context1.next = 1;
                                return _this3.attemptRegistrationWithServers(_constants2.FAILOVER_UTIL, _this3.backupMobiusUris);
                              case 1:
                                abort = _context1.sent;
                                if (!(!abort && !_this3.isDeviceRegistered())) {
                                  _context1.next = 3;
                                  break;
                                }
                                _context1.next = 2;
                                return (0, _common.uploadLogs)();
                              case 2:
                                (0, _common.emitFinalFailure)(function (clientError) {
                                  _this3.lineEmitter(_types3.LINE_EVENTS.ERROR, undefined, clientError);
                                }, loggerContext);
                              case 3:
                              case "end":
                                return _context1.stop();
                            }
                          }, _callee1);
                        })));
                      case 1:
                      case "end":
                        return _context10.stop();
                    }
                  }, _callee10);
                })), interval * _constants2.SEC_TO_MSEC_MFACTOR);
                _Logger.default.log("Scheduled retry with backup servers in ".concat(interval, " seconds."), loggerContext);
              }
              _context11.next = 7;
              break;
            case 5:
              _context11.next = 6;
              return (0, _common.uploadLogs)();
            case 6:
              (0, _common.emitFinalFailure)(function (clientError) {
                _this3.lineEmitter(_types3.LINE_EVENTS.ERROR, undefined, clientError);
              }, loggerContext, interval < 0 ? 'Timer threshold exceeded during failover' : undefined);
            case 7:
            case "end":
              return _context11.stop();
          }
        }, _callee11, this);
      }));
      function startFailoverTimer() {
        return _startFailoverTimer.apply(this, arguments);
      }
      return startFailoverTimer;
    }()
    /**
     * Clears the failback timer if running.
     */
    )
  }, {
    key: "clearFailbackTimer",
    value: function clearFailbackTimer() {
      if (this.failbackTimer) {
        clearTimeout(this.failbackTimer);
        this.failbackTimer = undefined;
      }
    }
  }, {
    key: "postKeepAlive",
    value: function () {
      var _postKeepAlive = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee12(deviceUrl, url) {
        var _this$deviceInfo$devi;
        return _regenerator.default.wrap(function (_context12) {
          while (1) switch (_context12.prev = _context12.next) {
            case 0:
              return _context12.abrupt("return", this.apiRequest.makeRequest({
                uri: "".concat(url, "/status"),
                method: _types2.HTTP_METHODS.POST,
                headers: (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _constants2.CISCO_DEVICE_URL, deviceUrl), _constants2.SPARK_USER_AGENT, _constants2.CALLING_USER_AGENT),
                body: {
                  deviceId: (_this$deviceInfo$devi = this.deviceInfo.device) === null || _this$deviceInfo$devi === void 0 ? void 0 : _this$deviceInfo$devi.deviceId
                },
                service: _types2.ALLOWED_SERVICES.MOBIUS
              }));
            case 1:
            case "end":
              return _context12.stop();
          }
        }, _callee12, this);
      }));
      function postKeepAlive(_x9, _x0) {
        return _postKeepAlive.apply(this, arguments);
      }
      return postKeepAlive;
    }()
  }, {
    key: "isPrimaryActive",
    value: function () {
      var _isPrimaryActive = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee13() {
        var status, _iterator, _step, mobiusUrl, baseUri, response, _ref7, statusCode, _t3, _t4;
        return _regenerator.default.wrap(function (_context13) {
          while (1) switch (_context13.prev = _context13.next) {
            case 0:
              _iterator = _createForOfIteratorHelper(this.primaryMobiusUris);
              _context13.prev = 1;
              _iterator.s();
            case 2:
              if ((_step = _iterator.n()).done) {
                _context13.next = 8;
                break;
              }
              mobiusUrl = _step.value;
              _context13.prev = 3;
              baseUri = mobiusUrl.replace(_constants2.URL_ENDPOINT, '/').replace('wss://', 'https://'); // eslint-disable-next-line no-await-in-loop
              _context13.next = 4;
              return this.webex.request({
                uri: "".concat(baseUri, "ping"),
                method: _types2.HTTP_METHODS.GET,
                headers: (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _constants2.CISCO_DEVICE_URL, this.webex.internal.device.url), _constants2.SPARK_USER_AGENT, _constants2.CALLING_USER_AGENT),
                service: _types2.ALLOWED_SERVICES.MOBIUS
              });
            case 4:
              response = _context13.sent;
              _ref7 = response, statusCode = _ref7.statusCode;
              if (!(statusCode === 200)) {
                _context13.next = 5;
                break;
              }
              _Logger.default.info("Ping successful for primary Mobius: ".concat(mobiusUrl), {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.FAILBACK_UTIL
              });
              status = 'up';
              return _context13.abrupt("continue", 8);
            case 5:
              _context13.next = 7;
              break;
            case 6:
              _context13.prev = 6;
              _t3 = _context13["catch"](3);
              _Logger.default.warn("Ping failed for primary Mobius: ".concat(mobiusUrl, " with error: ").concat((0, _stringify.default)(_t3)), {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.FAILBACK_UTIL
              });
              status = 'down';
            case 7:
              _context13.next = 2;
              break;
            case 8:
              _context13.next = 10;
              break;
            case 9:
              _context13.prev = 9;
              _t4 = _context13["catch"](1);
              _iterator.e(_t4);
            case 10:
              _context13.prev = 10;
              _iterator.f();
              return _context13.finish(10);
            case 11:
              return _context13.abrupt("return", status === 'up');
            case 12:
            case "end":
              return _context13.stop();
          }
        }, _callee13, this, [[1, 9, 10, 11], [3, 6]]);
      }));
      function isPrimaryActive() {
        return _isPrimaryActive.apply(this, arguments);
      }
      return isPrimaryActive;
    }()
    /**
     * Returns true if device is registered with a backup mobius.
     */
  }, {
    key: "isFailbackRequired",
    value: function isFailbackRequired() {
      return this.isDeviceRegistered() && this.primaryMobiusUris.indexOf(this.activeMobiusUrl) === -1;
    }

    /**
     * Calculates and returns a random value between rehomingIntervalMin and
     * rehomingIntervalMax.
     */
  }, {
    key: "getFailbackInterval",
    value: function getFailbackInterval() {
      return Math.floor(Math.random() * (this.rehomingIntervalMax - this.rehomingIntervalMin + 1) + this.rehomingIntervalMin);
    }

    /**
     * Starts failback timer to move to primary mobius if device
     * is registered with a backup mobius.
     */
  }, {
    key: "initiateFailback",
    value: function initiateFailback() {
      var loggerContext = {
        file: _constants2.REGISTRATION_FILE,
        method: _constants2.METHODS.INITIATE_FAILBACK
      };
      if (this.isFailbackRequired()) {
        if (!this.failbackTimer) {
          this.failback429RetryAttempts = 0;
          var intervalInMinutes = this.getFailbackInterval();
          _Logger.default.info("Scheduling failback to primary - intervalMinutes: ".concat(intervalInMinutes), loggerContext);
          this.startFailbackTimer(intervalInMinutes * _constants2.MINUTES_TO_SEC_MFACTOR);
        } else {
          _Logger.default.info('Failback timer already scheduled, skipping', loggerContext);
        }
      } else {
        _Logger.default.info('Failback not required, clearing any pending failback timer', loggerContext);
        this.failback429RetryAttempts = 0;
        this.clearFailbackTimer();
      }
    }

    /**
     * Starts failback timer with the interval value received.
     *
     */
  }, {
    key: "startFailbackTimer",
    value: function startFailbackTimer(intervalInSeconds) {
      var _this4 = this;
      this.failbackTimer = setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee14() {
        return _regenerator.default.wrap(function (_context14) {
          while (1) switch (_context14.prev = _context14.next) {
            case 0:
              return _context14.abrupt("return", _this4.executeFailback());
            case 1:
            case "end":
              return _context14.stop();
          }
        }, _callee14);
      })), intervalInSeconds * _constants2.SEC_TO_MSEC_MFACTOR);
      _Logger.default.log("Failback scheduled after ".concat(intervalInSeconds, " seconds."), {
        file: _constants2.REGISTRATION_FILE,
        method: this.startFailbackTimer.name
      });
    }

    /**
     * Core logic for the failback processing, scheduled and executed
     * at failback timer expiry.
     */
  }, {
    key: "executeFailback",
    value: (function () {
      var _executeFailback = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee16() {
        var _this5 = this;
        var loggerContext;
        return _regenerator.default.wrap(function (_context16) {
          while (1) switch (_context16.prev = _context16.next) {
            case 0:
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.EXECUTE_FAILBACK
              };
              _Logger.default.info(_constants.METHOD_START_MESSAGE, loggerContext);
              _context16.next = 1;
              return this.mutex.runExclusive(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee15() {
                var primaryServerStatus, abort, abortNew;
                return _regenerator.default.wrap(function (_context15) {
                  while (1) switch (_context15.prev = _context15.next) {
                    case 0:
                      if (!_this5.isFailbackRequired()) {
                        _context15.next = 13;
                        break;
                      }
                      _context15.next = 1;
                      return _this5.isPrimaryActive();
                    case 1:
                      primaryServerStatus = _context15.sent;
                      if (!((0, _keys.default)(_this5.callManager.getActiveCalls()).length === 0 && primaryServerStatus)) {
                        _context15.next = 12;
                        break;
                      }
                      _Logger.default.info("Attempting failback to primary.", loggerContext);
                      _context15.next = 2;
                      return _this5.deregister();
                    case 2:
                      if (!_this5.apiRequest.isSocketEnabled()) {
                        _context15.next = 4;
                        break;
                      }
                      _Logger.default.info('Disconnecting from backup Mobius socket for failback to primary', loggerContext);
                      _context15.next = 3;
                      return _this5.apiRequest.disconnectFromMobiusSocket({
                        code: 3050,
                        reason: 'done (permanent)'
                      });
                    case 3:
                      _Logger.default.log('Mobius socket disconnect complete prior to primary failback', loggerContext);
                    case 4:
                      _context15.next = 5;
                      return _this5.attemptRegistrationWithServers(_constants2.FAILBACK_UTIL);
                    case 5:
                      abort = _context15.sent;
                      if (!(_this5.scheduled429Retry || abort || _this5.isDeviceRegistered())) {
                        _context15.next = 6;
                        break;
                      }
                      return _context15.abrupt("return");
                    case 6:
                      _context15.next = 7;
                      return _this5.restorePreviousRegistration(_constants2.FAILBACK_UTIL);
                    case 7:
                      abortNew = _context15.sent;
                      if (!abortNew) {
                        _context15.next = 8;
                        break;
                      }
                      _this5.clearFailbackTimer();
                      return _context15.abrupt("return");
                    case 8:
                      if (_this5.isDeviceRegistered()) {
                        _context15.next = 10;
                        break;
                      }
                      _context15.next = 9;
                      return _this5.restartRegistration(loggerContext.method);
                    case 9:
                      _context15.next = 11;
                      break;
                    case 10:
                      _this5.failbackTimer = undefined;
                      _this5.initiateFailback();
                    case 11:
                      _context15.next = 13;
                      break;
                    case 12:
                      _Logger.default.info('Active calls present or primary Mobius is down, deferring failback to next cycle.', loggerContext);
                      _this5.failbackTimer = undefined;
                      _this5.initiateFailback();
                    case 13:
                    case "end":
                      return _context15.stop();
                  }
                }, _callee15);
              })));
            case 1:
            case "end":
              return _context16.stop();
          }
        }, _callee16, this);
      }));
      function executeFailback() {
        return _executeFailback.apply(this, arguments);
      }
      return executeFailback;
    }()
    /**
     * Updates rehomingIntervalMin and rehomingIntervalMax values
     * if received in registration response from a primary mobius
     * server.
     *
     */
    )
  }, {
    key: "setIntervalValues",
    value: function setIntervalValues(deviceInfo) {
      if (this.primaryMobiusUris.indexOf(this.activeMobiusUrl) !== -1) {
        this.rehomingIntervalMin = deviceInfo !== null && deviceInfo !== void 0 && deviceInfo.rehomingIntervalMin ? deviceInfo.rehomingIntervalMin : _constants2.DEFAULT_REHOMING_INTERVAL_MIN;
        this.rehomingIntervalMax = deviceInfo !== null && deviceInfo !== void 0 && deviceInfo.rehomingIntervalMax ? deviceInfo.rehomingIntervalMax : _constants2.DEFAULT_REHOMING_INTERVAL_MAX;
      }
    }

    /**
     * Retrieves information about the device as {@link IDeviceInfo}.
     *
     */
  }, {
    key: "getDeviceInfo",
    value: function getDeviceInfo() {
      return this.deviceInfo;
    }

    /**
     * Checks if the device is currently registered.
     *
     *          by checking if isRegistered state is set to
     *          ACTIVE, else false.
     */
  }, {
    key: "isDeviceRegistered",
    value: function isDeviceRegistered() {
      return this.registrationStatus === _types2.RegistrationStatus.ACTIVE;
    }
  }, {
    key: "getStatus",
    value: function getStatus() {
      return this.registrationStatus;
    }
  }, {
    key: "setStatus",
    value: function setStatus(value) {
      this.registrationStatus = value;
    }

    /**
     * Start fresh registration cycle with the mobius
     * server list already present.
     *
     */
  }, {
    key: "restartRegistration",
    value: (function () {
      var _restartRegistration = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee17(caller) {
        var loggerContext, abort;
        return _regenerator.default.wrap(function (_context17) {
          while (1) switch (_context17.prev = _context17.next) {
            case 0:
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.RESTART_REGISTRATION
              };
              _Logger.default.info("".concat(_constants.METHOD_START_MESSAGE, " - caller: ").concat(caller), loggerContext);

              /*
               * Cancel any failback timer running
               * and start fresh registration attempt with retry as true.
               */
              this.clearFailbackTimer();
              this.failback429RetryAttempts = 0;
              _context17.next = 1;
              return this.attemptRegistrationWithServers(caller, this.primaryMobiusUris);
            case 1:
              abort = _context17.sent;
              if (!(!abort && !this.isDeviceRegistered())) {
                _context17.next = 2;
                break;
              }
              _context17.next = 2;
              return this.startFailoverTimer();
            case 2:
              _Logger.default.log("restartRegistration completed - caller: ".concat(caller, ", deviceRegistered: ").concat(this.isDeviceRegistered(), ", abort: ").concat(abort), loggerContext);
            case 3:
            case "end":
              return _context17.stop();
          }
        }, _callee17, this);
      }));
      function restartRegistration(_x1) {
        return _restartRegistration.apply(this, arguments);
      }
      return restartRegistration;
    }()
    /**
     * Restores the connection and attempts refreshing existing registration with server.
     * Allows retry if not restored in the first attempt.
     *
     */
    )
  }, {
    key: "handleConnectionRestoration",
    value: (function () {
      var _handleConnectionRestoration = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee19(retry) {
        var _this6 = this;
        return _regenerator.default.wrap(function (_context19) {
          while (1) switch (_context19.prev = _context19.next) {
            case 0:
              _Logger.default.info(_constants.METHOD_START_MESSAGE, {
                method: _constants2.METHODS.HANDLE_CONNECTION_RESTORATION,
                file: _constants2.REGISTRATION_FILE
              });
              _context19.next = 1;
              return this.mutex.runExclusive(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee18() {
                var abort;
                return _regenerator.default.wrap(function (_context18) {
                  while (1) switch (_context18.prev = _context18.next) {
                    case 0:
                      if (!retry) {
                        _context18.next = 4;
                        break;
                      }
                      _Logger.default.log('Network is up again, re-registering with Webex Calling if needed', {
                        file: _constants2.REGISTRATION_FILE,
                        method: _constants2.METHODS.HANDLE_CONNECTION_RESTORATION
                      });
                      _this6.clearKeepaliveTimer();
                      if (!_this6.isDeviceRegistered()) {
                        _context18.next = 1;
                        break;
                      }
                      _context18.next = 1;
                      return _this6.deregister();
                    case 1:
                      if (!_this6.activeMobiusUrl) {
                        _context18.next = 3;
                        break;
                      }
                      _context18.next = 2;
                      return _this6.restorePreviousRegistration(_constants2.METHODS.HANDLE_CONNECTION_RESTORATION);
                    case 2:
                      abort = _context18.sent;
                      if (!(!abort && !_this6.isDeviceRegistered())) {
                        _context18.next = 3;
                        break;
                      }
                      _context18.next = 3;
                      return _this6.restartRegistration(_constants2.METHODS.HANDLE_CONNECTION_RESTORATION);
                    case 3:
                      retry = false;
                    case 4:
                    case "end":
                      return _context18.stop();
                  }
                }, _callee18);
              })));
            case 1:
              return _context19.abrupt("return", retry);
            case 2:
            case "end":
              return _context19.stop();
          }
        }, _callee19, this);
      }));
      function handleConnectionRestoration(_x10) {
        return _handleConnectionRestoration.apply(this, arguments);
      }
      return handleConnectionRestoration;
    }()
    /**
     * Callback function for restoring registration in case of failure during initial registration
     * due to device registration already exists.
     *
     */
    )
  }, {
    key: "restoreRegistrationCallBack",
    value: function restoreRegistrationCallBack() {
      var _this7 = this;
      return /*#__PURE__*/function () {
        var _ref1 = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee20(restoreData, caller) {
          var logContext, restore, finalError;
          return _regenerator.default.wrap(function (_context20) {
            while (1) switch (_context20.prev = _context20.next) {
              case 0:
                logContext = {
                  file: _constants2.REGISTRATION_FILE,
                  method: caller
                };
                if (_this7.isRegRetry()) {
                  _context20.next = 4;
                  break;
                }
                _Logger.default.info('Registration restoration in progress.', logContext);
                restore = _this7.getExistingDevice(restoreData);
                if (!restore) {
                  _context20.next = 3;
                  break;
                }
                _this7.setRegRetry(true);
                _context20.next = 1;
                return _this7.deregister();
              case 1:
                _context20.next = 2;
                return _this7.restorePreviousRegistration(caller);
              case 2:
                finalError = _context20.sent;
                _this7.setRegRetry(false);
                if (_this7.isDeviceRegistered()) {
                  _Logger.default.info('Registration restored successfully.', logContext);
                }
                return _context20.abrupt("return", finalError);
              case 3:
                _this7.lineEmitter(_types3.LINE_EVENTS.UNREGISTERED);
                _context20.next = 5;
                break;
              case 4:
                _this7.lineEmitter(_types3.LINE_EVENTS.UNREGISTERED);
              case 5:
                return _context20.abrupt("return", false);
              case 6:
              case "end":
                return _context20.stop();
            }
          }, _callee20);
        }));
        return function (_x11, _x12) {
          return _ref1.apply(this, arguments);
        };
      }();
    }

    /**
     * Triggers the registration with the given list of Mobius servers
     * Registration is attempted with primary and backup until it succeeds or the list is exhausted
     */
  }, {
    key: "triggerRegistration",
    value: (function () {
      var _triggerRegistration = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee21() {
        var loggerContext, abort;
        return _regenerator.default.wrap(function (_context21) {
          while (1) switch (_context21.prev = _context21.next) {
            case 0:
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.TRIGGER_REGISTRATION
              };
              _Logger.default.info(_constants.METHOD_START_MESSAGE, loggerContext);
              _context21.next = 1;
              return this.resumeFailover();
            case 1:
              if (!_context21.sent) {
                _context21.next = 2;
                break;
              }
              _Logger.default.info('Registration trigger handled by resumeFailover path', loggerContext);
              return _context21.abrupt("return");
            case 2:
              if (!(this.primaryMobiusUris.length > 0)) {
                _context21.next = 5;
                break;
              }
              _context21.next = 3;
              return this.attemptRegistrationWithServers(_constants2.REGISTRATION_UTIL, this.primaryMobiusUris);
            case 3:
              abort = _context21.sent;
              if (!(!this.isDeviceRegistered() && !abort)) {
                _context21.next = 4;
                break;
              }
              _context21.next = 4;
              return this.startFailoverTimer();
            case 4:
              _Logger.default.log("triggerRegistration completed - deviceRegistered: ".concat(this.isDeviceRegistered(), ", abort: ").concat(abort), loggerContext);
              _context21.next = 6;
              break;
            case 5:
              _Logger.default.warn('triggerRegistration skipped: no primary Mobius URIs available', loggerContext);
            case 6:
            case "end":
              return _context21.stop();
          }
        }, _callee21, this);
      }));
      function triggerRegistration() {
        return _triggerRegistration.apply(this, arguments);
      }
      return triggerRegistration;
    }()
    /**
     * Attempts registration with the server list received in
     * argument one by one until registration either succeeds with
     * one or all of them are tried.
     *
     *          attempt has hit a final error and a retry should not be scheduled
     *          else false.
     */
    )
  }, {
    key: "attemptRegistrationWithServers",
    value: (function () {
      var _attemptRegistrationWithServers = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee22(caller) {
        var _this8 = this;
        var servers,
          loggerContext,
          abort,
          connectedWebSocketUrl,
          _iterator2,
          _step2,
          _loop,
          _ret,
          _args23 = arguments,
          _t6;
        return _regenerator.default.wrap(function (_context23) {
          while (1) switch (_context23.prev = _context23.next) {
            case 0:
              servers = _args23.length > 1 && _args23[1] !== undefined ? _args23[1] : this.primaryMobiusUris;
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.REGISTER_UTIL
              };
              abort = false;
              this.retryAfter = undefined;
              if (!this.failoverImmediately) {
                _context23.next = 1;
                break;
              }
              return _context23.abrupt("return", abort);
            case 1:
              if (!this.isDeviceRegistered()) {
                _context23.next = 2;
                break;
              }
              _Logger.default.info("[".concat(caller, "] : Device already registered with : ").concat(this.activeMobiusUrl), loggerContext);
              return _context23.abrupt("return", abort);
            case 2:
              _iterator2 = _createForOfIteratorHelper(servers);
              _context23.prev = 3;
              _loop = /*#__PURE__*/_regenerator.default.mark(function _loop() {
                var url, serverType, _this8$deviceInfo$dev, _resp$headers, _resp$headers$trackin, _resp$headers2, _this8$deviceInfo$dev2, wssNormalizedUrl, resp, body, _yield$handleRegistra, finalError, shouldDisconnect, _t5;
                return _regenerator.default.wrap(function (_context22) {
                  while (1) switch (_context22.prev = _context22.next) {
                    case 0:
                      url = _step2.value;
                      serverType = _this8.getServerType(url);
                      _context22.prev = 1;
                      abort = false;
                      _this8.registrationStatus = _types2.RegistrationStatus.INACTIVE;
                      _this8.lineEmitter(_types3.LINE_EVENTS.CONNECTING);
                      _Logger.default.info("[".concat(caller, "] : Mobius url to contact: ").concat(url), loggerContext);
                      if (!_this8.apiRequest.isSocketEnabled()) {
                        _context22.next = 3;
                        break;
                      }
                      wssNormalizedUrl = url.endsWith('/') ? url.slice(0, -1) : url;
                      _Logger.default.info("[".concat(caller, "] : Connecting to Mobius WebSocket - serverType: ").concat(serverType, ", wssUrl: ").concat(wssNormalizedUrl), loggerContext);

                      // eslint-disable-next-line no-await-in-loop
                      _context22.next = 2;
                      return _this8.apiRequest.connectToMobiusSocket(wssNormalizedUrl);
                    case 2:
                      connectedWebSocketUrl = _context22.sent;
                      connectedWebSocketUrl = connectedWebSocketUrl ? "".concat(connectedWebSocketUrl, "/") : undefined;
                      _Logger.default.log("[".concat(caller, "] : Mobius WebSocket connected - serverType: ").concat(serverType, ", connectedWebSocketUrl: ").concat(connectedWebSocketUrl), loggerContext);
                    case 3:
                      _context22.next = 4;
                      return _this8.postRegistration(url);
                    case 4:
                      resp = _context22.sent;
                      _this8.clearFailoverState();
                      _this8.deviceInfo = resp.body;
                      _this8.registrationStatus = _types2.RegistrationStatus.ACTIVE;
                      _this8.setActiveMobiusUrl(connectedWebSocketUrl || url);
                      _this8.lineEmitter(_types3.LINE_EVENTS.REGISTERED, resp.body);
                      _Logger.default.log("Registration successful for deviceId: ".concat((_this8$deviceInfo$dev = _this8.deviceInfo.device) === null || _this8$deviceInfo$dev === void 0 ? void 0 : _this8$deviceInfo$dev.deviceId, " userId: ").concat(_this8.userId, " responseTrackingId: ").concat((_resp$headers = resp.headers) === null || _resp$headers === void 0 ? void 0 : _resp$headers.trackingid), loggerContext);
                      _this8.setIntervalValues(_this8.deviceInfo);
                      _this8.metricManager.setDeviceInfo(_this8.deviceInfo);
                      _this8.metricManager.submitRegistrationMetric(_types.METRIC_EVENT.REGISTRATION, _types.REG_ACTION.REGISTER, _types.METRIC_TYPE.BEHAVIORAL, caller, serverType, (_resp$headers$trackin = (_resp$headers2 = resp.headers) === null || _resp$headers2 === void 0 ? void 0 : _resp$headers2.trackingid) !== null && _resp$headers$trackin !== void 0 ? _resp$headers$trackin : '', undefined, undefined);
                      _this8.startKeepaliveTimer((_this8$deviceInfo$dev2 = _this8.deviceInfo.device) === null || _this8$deviceInfo$dev2 === void 0 ? void 0 : _this8$deviceInfo$dev2.uri, _this8.deviceInfo.keepaliveInterval, serverType);
                      _this8.initiateFailback();
                      return _context22.abrupt("return", 0);
                    case 5:
                      _context22.prev = 5;
                      _t5 = _context22["catch"](1);
                      body = _t5; // eslint-disable-next-line no-await-in-loop, @typescript-eslint/no-unused-vars
                      _context22.next = 6;
                      return (0, _common.handleRegistrationErrors)(body, function (clientError, isFinalError) {
                        var _body$headers$trackin, _body$headers;
                        if (isFinalError) {
                          _this8.lineEmitter(_types3.LINE_EVENTS.ERROR, undefined, clientError);
                        } else {
                          _this8.lineEmitter(_types3.LINE_EVENTS.UNREGISTERED);
                        }
                        _this8.metricManager.submitRegistrationMetric(_types.METRIC_EVENT.REGISTRATION_ERROR, _types.REG_ACTION.REGISTER, _types.METRIC_TYPE.BEHAVIORAL, caller, serverType, (_body$headers$trackin = (_body$headers = body.headers) === null || _body$headers === void 0 ? void 0 : _body$headers.trackingid) !== null && _body$headers$trackin !== void 0 ? _body$headers$trackin : '', undefined, clientError);
                      }, {
                        method: caller,
                        file: _constants2.REGISTRATION_FILE
                      }, function (retryAfter, retryCaller) {
                        return _this8.handle429Retry(retryAfter, retryCaller);
                      }, _this8.restoreRegistrationCallBack(), servers.length);
                    case 6:
                      _yield$handleRegistra = _context22.sent;
                      finalError = _yield$handleRegistra.finalError;
                      shouldDisconnect = _yield$handleRegistra.shouldDisconnect;
                      abort = finalError;
                      if (!(_this8.registrationStatus === _types2.RegistrationStatus.ACTIVE)) {
                        _context22.next = 7;
                        break;
                      }
                      _Logger.default.info("[".concat(caller, "] : Device is already restored, active mobius url: ").concat(_this8.activeMobiusUrl), loggerContext);
                      return _context22.abrupt("return", 0);
                    case 7:
                      if (!(shouldDisconnect && _this8.apiRequest.isSocketEnabled())) {
                        _context22.next = 9;
                        break;
                      }
                      connectedWebSocketUrl = undefined;
                      _Logger.default.info("[".concat(caller, "] : Tearing down Mobius WebSocket after registration error - serverType: ").concat(serverType), loggerContext);

                      // eslint-disable-next-line no-await-in-loop
                      _context22.next = 8;
                      return _this8.apiRequest.disconnectFromMobiusSocket({
                        code: 3050,
                        reason: 'done (permanent)'
                      });
                    case 8:
                      _Logger.default.log("[".concat(caller, "] : Mobius WebSocket disconnect complete after registration error - serverType: ").concat(serverType), loggerContext);
                    case 9:
                      if (!abort) {
                        _context22.next = 11;
                        break;
                      }
                      _this8.setStatus(_types2.RegistrationStatus.INACTIVE);
                      // eslint-disable-next-line no-await-in-loop
                      _context22.next = 10;
                      return (0, _common.uploadLogs)();
                    case 10:
                      return _context22.abrupt("return", 0);
                    case 11:
                    case "end":
                      return _context22.stop();
                  }
                }, _loop, null, [[1, 5]]);
              });
              _iterator2.s();
            case 4:
              if ((_step2 = _iterator2.n()).done) {
                _context23.next = 7;
                break;
              }
              return _context23.delegateYield(_loop(), "t0", 5);
            case 5:
              _ret = _context23.t0;
              if (!(_ret === 0)) {
                _context23.next = 6;
                break;
              }
              return _context23.abrupt("continue", 7);
            case 6:
              _context23.next = 4;
              break;
            case 7:
              _context23.next = 9;
              break;
            case 8:
              _context23.prev = 8;
              _t6 = _context23["catch"](3);
              _iterator2.e(_t6);
            case 9:
              _context23.prev = 9;
              _iterator2.f();
              return _context23.finish(9);
            case 10:
              return _context23.abrupt("return", abort);
            case 11:
            case "end":
              return _context23.stop();
          }
        }, _callee22, this, [[3, 8, 9, 10]]);
      }));
      function attemptRegistrationWithServers(_x13) {
        return _attemptRegistrationWithServers.apply(this, arguments);
      }
      return attemptRegistrationWithServers;
    }()
    /**
     * This method sets up a timer to periodically send keep-alive requests to maintain a connection.
     * It handles retries, error handling, and re-registration attempts based on the response, ensuring continuous connectivity with the server.
     */
    )
  }, {
    key: "startKeepaliveTimer",
    value: (function () {
      var _startKeepaliveTimer = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee25(url, interval, serverType) {
        var _this9 = this;
        var RETRY_COUNT_THRESHOLD;
        return _regenerator.default.wrap(function (_context26) {
          while (1) switch (_context26.prev = _context26.next) {
            case 0:
              this.clearKeepaliveTimer();
              RETRY_COUNT_THRESHOLD = this.isCCFlow ? 4 : 5;
              _context26.next = 1;
              return this.mutex.runExclusive(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee24() {
                var blob, blobUrl;
                return _regenerator.default.wrap(function (_context25) {
                  while (1) switch (_context25.prev = _context25.next) {
                    case 0:
                      if (_this9.isDeviceRegistered()) {
                        if (!_this9.webWorker) {
                          blob = new Blob([_webWorkerStr.default], {
                            type: 'application/javascript'
                          });
                          blobUrl = URL.createObjectURL(blob);
                          _this9.webWorker = new Worker(blobUrl);
                          URL.revokeObjectURL(blobUrl);
                          _this9.webWorker.postMessage({
                            type: _types2.WorkerMessageType.START_KEEPALIVE,
                            interval: interval,
                            retryCountThreshold: RETRY_COUNT_THRESHOLD
                          });
                          _this9.webWorker.onmessage = /*#__PURE__*/function () {
                            var _ref11 = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee23(event) {
                              var logContext, _this9$webWorker, res, _err$headers, _this9$webWorker2, error, _error, _yield$handleRegistra2, abort, _t7;
                              return _regenerator.default.wrap(function (_context24) {
                                while (1) switch (_context24.prev = _context24.next) {
                                  case 0:
                                    logContext = {
                                      file: _constants2.REGISTRATION_FILE,
                                      method: _constants2.KEEPALIVE_UTIL
                                    };
                                    if (!(event.data.type === _types2.WorkerMessageType.SEND_KEEPALIVE)) {
                                      _context24.next = 4;
                                      break;
                                    }
                                    _context24.prev = 1;
                                    _context24.next = 2;
                                    return _this9.postKeepAlive(String(_this9.webex.internal.device.url), url);
                                  case 2:
                                    res = _context24.sent;
                                    (_this9$webWorker = _this9.webWorker) === null || _this9$webWorker === void 0 ? void 0 : _this9$webWorker.postMessage({
                                      type: _types2.WorkerMessageType.KEEPALIVE_RESULT,
                                      statusCode: res.statusCode
                                    });
                                    _context24.next = 4;
                                    break;
                                  case 3:
                                    _context24.prev = 3;
                                    _t7 = _context24["catch"](1);
                                    error = {
                                      headers: {
                                        trackingid: (_err$headers = _t7.headers) === null || _err$headers === void 0 ? void 0 : _err$headers.trackingid,
                                        'retry-after': _t7.headers['retry-after']
                                      },
                                      statusCode: _t7.statusCode,
                                      statusText: _t7.statusText,
                                      type: _t7.type
                                    };
                                    (_this9$webWorker2 = _this9.webWorker) === null || _this9$webWorker2 === void 0 ? void 0 : _this9$webWorker2.postMessage({
                                      type: _types2.WorkerMessageType.KEEPALIVE_RESULT,
                                      err: error
                                    });
                                  case 4:
                                    if (event.data.type === _types2.WorkerMessageType.KEEPALIVE_SUCCESS) {
                                      _Logger.default.info("Sent Keepalive, status: ".concat(event.data.statusCode), logContext);
                                      _this9.lineEmitter(_types3.LINE_EVENTS.RECONNECTED);
                                    }
                                    if (!(event.data.type === _types2.WorkerMessageType.KEEPALIVE_FAILURE)) {
                                      _context24.next = 11;
                                      break;
                                    }
                                    _error = event.data.err;
                                    _Logger.default.warn("Keep-alive missed ".concat(event.data.keepAliveRetryCount, " times. Status -> ").concat(_error.statusCode, " "), logContext);
                                    _context24.next = 5;
                                    return (0, _common.handleRegistrationErrors)(_error, function (clientError, finalError) {
                                      var _error$headers$tracki, _error$headers;
                                      if (finalError) {
                                        _this9.lineEmitter(_types3.LINE_EVENTS.ERROR, undefined, clientError);
                                      }
                                      _this9.metricManager.submitRegistrationMetric(_types.METRIC_EVENT.KEEPALIVE_ERROR, _types.REG_ACTION.KEEPALIVE_FAILURE, _types.METRIC_TYPE.BEHAVIORAL, _constants2.KEEPALIVE_UTIL, serverType, (_error$headers$tracki = (_error$headers = _error.headers) === null || _error$headers === void 0 ? void 0 : _error$headers.trackingid) !== null && _error$headers$tracki !== void 0 ? _error$headers$tracki : '', event.data.keepAliveRetryCount, clientError);
                                    }, {
                                      method: _constants2.KEEPALIVE_UTIL,
                                      file: _constants2.REGISTRATION_FILE
                                    }, function (retryAfter, retryCaller) {
                                      return _this9.handle429Retry(retryAfter, retryCaller);
                                    });
                                  case 5:
                                    _yield$handleRegistra2 = _context24.sent;
                                    abort = _yield$handleRegistra2.finalError;
                                    if (!(abort || event.data.keepAliveRetryCount >= RETRY_COUNT_THRESHOLD)) {
                                      _context24.next = 10;
                                      break;
                                    }
                                    _this9.failoverImmediately = _this9.isCCFlow;
                                    _this9.setStatus(_types2.RegistrationStatus.INACTIVE);
                                    _this9.clearKeepaliveTimer();
                                    _this9.clearFailbackTimer();
                                    _this9.lineEmitter(_types3.LINE_EVENTS.UNREGISTERED);
                                    _context24.next = 6;
                                    return (0, _common.uploadLogs)();
                                  case 6:
                                    if (abort) {
                                      _context24.next = 8;
                                      break;
                                    }
                                    _context24.next = 7;
                                    return _this9.reconnectOnFailure(_constants2.RECONNECT_ON_FAILURE_UTIL);
                                  case 7:
                                    _context24.next = 9;
                                    break;
                                  case 8:
                                    if (_error.statusCode === 404) {
                                      _this9.handle404KeepaliveFailure(_constants2.KEEPALIVE_UTIL);
                                    }
                                  case 9:
                                    _context24.next = 11;
                                    break;
                                  case 10:
                                    _this9.lineEmitter(_types3.LINE_EVENTS.RECONNECTING);
                                  case 11:
                                  case "end":
                                    return _context24.stop();
                                }
                              }, _callee23, null, [[1, 3]]);
                            }));
                            return function (_x17) {
                              return _ref11.apply(this, arguments);
                            };
                          }();
                        }
                      }
                    case 1:
                    case "end":
                      return _context25.stop();
                  }
                }, _callee24);
              })));
            case 1:
            case "end":
              return _context26.stop();
          }
        }, _callee25, this);
      }));
      function startKeepaliveTimer(_x14, _x15, _x16) {
        return _startKeepaliveTimer.apply(this, arguments);
      }
      return startKeepaliveTimer;
    }()
    /**
     * Clears the keepalive timer if running.
     */
    )
  }, {
    key: "clearKeepaliveTimer",
    value: function clearKeepaliveTimer() {
      if (this.webWorker) {
        this.webWorker.postMessage({
          type: _types2.WorkerMessageType.CLEAR_KEEPALIVE
        });
        this.webWorker.terminate();
        this.webWorker = undefined;
      }
    }
  }, {
    key: "isReconnectPending",
    value: function isReconnectPending() {
      return this.reconnectPending;
    }
  }, {
    key: "deregister",
    value: function () {
      var _deregister = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee26() {
        var closeMobiusWss,
          loggerContext,
          _this$deviceInfo$devi2,
          _this$deviceInfo$devi3,
          _args27 = arguments,
          _t8;
        return _regenerator.default.wrap(function (_context27) {
          while (1) switch (_context27.prev = _context27.next) {
            case 0:
              closeMobiusWss = _args27.length > 0 && _args27[0] !== undefined ? _args27[0] : false;
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.DEREGISTER
              };
              _Logger.default.info(_constants.METHOD_START_MESSAGE, loggerContext);
              _context27.prev = 1;
              _context27.next = 2;
              return this.deleteRegistration(this.activeMobiusUrl, (_this$deviceInfo$devi2 = this.deviceInfo.device) === null || _this$deviceInfo$devi2 === void 0 ? void 0 : _this$deviceInfo$devi2.deviceId, (_this$deviceInfo$devi3 = this.deviceInfo.device) === null || _this$deviceInfo$devi3 === void 0 ? void 0 : _this$deviceInfo$devi3.clientDeviceUri);
            case 2:
              _Logger.default.log('Registration successfully deregistered', loggerContext);
              _context27.next = 4;
              break;
            case 3:
              _context27.prev = 3;
              _t8 = _context27["catch"](1);
              _Logger.default.warn("Delete failed with Mobius: ".concat((0, _stringify.default)(_t8)), loggerContext);
            case 4:
              if (!closeMobiusWss) {
                _context27.next = 6;
                break;
              }
              _context27.next = 5;
              return this.apiRequest.disconnectFromMobiusSocket({
                code: 3050,
                reason: 'done (permanent)'
              });
            case 5:
              _Logger.default.log('Mobius socket disconnect complete after deregistration', loggerContext);
            case 6:
              this.clearKeepaliveTimer();
              this.setStatus(_types2.RegistrationStatus.INACTIVE);
              this.clearFailoverState();
            case 7:
            case "end":
              return _context27.stop();
          }
        }, _callee26, this, [[1, 3]]);
      }));
      function deregister() {
        return _deregister.apply(this, arguments);
      }
      return deregister;
    }()
    /**
     * Indicates whether the calling client is in a mode
     * to retry registration.
     */
  }, {
    key: "isRegRetry",
    value: function isRegRetry() {
      return this.registerRetry;
    }

    /**
     * Sets the received value in instance variable
     * registerRetry for registration retry cases.
     *
     */
  }, {
    key: "setRegRetry",
    value: function setRegRetry(value) {
      this.registerRetry = value;
    }

    /**
     * Restores the deviceInfo object in callingClient when receiving a 403 with error code 101.
     *
     */
  }, {
    key: "getExistingDevice",
    value: function getExistingDevice(restoreData) {
      if (restoreData.devices && restoreData.devices.length > 0) {
        this.deviceInfo = {
          userId: restoreData.userId,
          device: restoreData.devices[0],
          keepaliveInterval: _constants2.DEFAULT_KEEPALIVE_INTERVAL,
          rehomingIntervalMax: _constants2.DEFAULT_REHOMING_INTERVAL_MAX,
          rehomingIntervalMin: _constants2.DEFAULT_REHOMING_INTERVAL_MIN
        };
        var stringToReplace = "".concat(_constants2.DEVICES_ENDPOINT_RESOURCE, "/").concat(restoreData.devices[0].deviceId);
        var uri = restoreData.devices[0].uri.replace(stringToReplace, '');
        if (this.apiRequest.isSocketEnabled()) {
          uri = uri.replace('https://', 'wss://');
          uri = !uri.endsWith('/') ? "".concat(uri, "/") : uri;
        }
        this.setActiveMobiusUrl(uri);
        this.registrationStatus = _types2.RegistrationStatus.ACTIVE;
        return true;
      }
      return false;
    }

    /**
     * Invoked to re-register in cases when the registration
     * is lost due to some failure.
     * If there are active calls, it will only mark reconnectPending
     * as true and then retry will happen when this method gets
     * invoked again on receiving all calls cleared event from
     * callManager.
     *
     */
  }, {
    key: "reconnectOnFailure",
    value: (function () {
      var _reconnectOnFailure = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee27(caller) {
        var abort;
        return _regenerator.default.wrap(function (_context28) {
          while (1) switch (_context28.prev = _context28.next) {
            case 0:
              _Logger.default.info(_constants.METHOD_START_MESSAGE, {
                method: _constants2.METHODS.RECONNECT_ON_FAILURE,
                file: _constants2.REGISTRATION_FILE
              });
              this.reconnectPending = false;
              if (this.isDeviceRegistered()) {
                _context28.next = 4;
                break;
              }
              if (!((0, _keys.default)(this.callManager.getActiveCalls()).length === 0)) {
                _context28.next = 3;
                break;
              }
              _context28.next = 1;
              return this.restorePreviousRegistration(caller);
            case 1:
              abort = _context28.sent;
              if (!(!abort && !this.isDeviceRegistered())) {
                _context28.next = 2;
                break;
              }
              _context28.next = 2;
              return this.restartRegistration(caller);
            case 2:
              _context28.next = 4;
              break;
            case 3:
              this.reconnectPending = true;
              _Logger.default.info('Active call(s) present, deferred reconnect till call cleanup.', {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.RECONNECT_ON_FAILURE
              });
            case 4:
            case "end":
              return _context28.stop();
          }
        }, _callee27, this);
      }));
      function reconnectOnFailure(_x18) {
        return _reconnectOnFailure.apply(this, arguments);
      }
      return reconnectOnFailure;
    }()
    /**
     * Handles an async REGISTRATION_DOWN event emitted by Mobius. Ends the first
     * active call (if any) and runs registration-side cleanup.
     *
     * @param event - The Mobius async event payload (trackingId/eventId used for logs).
     */
    )
  }, {
    key: "handleRegistrationDownEvent",
    value: (function () {
      var _handleRegistrationDownEvent = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee28(event) {
        var _event$trackingId, _event$eventId;
        var loggerContext, _Object$values, _Object$values2, activeCall;
        return _regenerator.default.wrap(function (_context29) {
          while (1) switch (_context29.prev = _context29.next) {
            case 0:
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.HANDLE_REGISTRATION_DOWN_EVENT
              };
              _Logger.default.info("Registration down received - trackingId: ".concat((_event$trackingId = event === null || event === void 0 ? void 0 : event.trackingId) !== null && _event$trackingId !== void 0 ? _event$trackingId : 'unknown', ", eventId: ").concat((_event$eventId = event === null || event === void 0 ? void 0 : event.eventId) !== null && _event$eventId !== void 0 ? _event$eventId : 'unknown'), loggerContext);
              _Object$values = (0, _values.default)(this.callManager.getActiveCalls()), _Object$values2 = (0, _slicedToArray2.default)(_Object$values, 1), activeCall = _Object$values2[0];
              activeCall === null || activeCall === void 0 ? void 0 : activeCall.end();
              _context29.next = 1;
              return this.performRegistrationDownCleanup(_constants2.METHODS.HANDLE_REGISTRATION_DOWN_EVENT);
            case 1:
            case "end":
              return _context29.stop();
          }
        }, _callee28, this);
      }));
      function handleRegistrationDownEvent(_x19) {
        return _handleRegistrationDownEvent.apply(this, arguments);
      }
      return handleRegistrationDownEvent;
    }()
    /**
     * Cleans up registration-side state after a Mobius registration-down event.
     *
     * Stops timers, resets transient flags, clears failover cache, sets status to
     * INACTIVE, tears down the Mobius WebSocket (when enabled), and finally emits
     * `LINE_EVENTS.UNREGISTERED` so the SDK consumer is notified.
     *
     * Runs under the shared mutex to avoid racing with other registration flows.
     *
     * @param caller - Identifier of the caller, used for logs.
     */
    )
  }, {
    key: "performRegistrationDownCleanup",
    value: (function () {
      var _performRegistrationDownCleanup = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee30(caller) {
        var _this0 = this;
        var loggerContext;
        return _regenerator.default.wrap(function (_context31) {
          while (1) switch (_context31.prev = _context31.next) {
            case 0:
              loggerContext = {
                file: _constants2.REGISTRATION_FILE,
                method: _constants2.METHODS.HANDLE_REGISTRATION_DOWN_EVENT
              };
              _Logger.default.info("[".concat(caller, "] : Running registration-down cleanup"), loggerContext);
              _context31.next = 1;
              return this.mutex.runExclusive(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee29() {
                var _t9;
                return _regenerator.default.wrap(function (_context30) {
                  while (1) switch (_context30.prev = _context30.next) {
                    case 0:
                      _this0.clearFailbackTimer();
                      _this0.clearKeepaliveTimer();
                      _this0.reconnectPending = false;
                      _this0.scheduled429Retry = false;
                      _this0.failoverImmediately = false;
                      _this0.retryAfter = undefined;
                      _this0.registerRetry = false;
                      _this0.clearFailoverState();
                      _this0.setStatus(_types2.RegistrationStatus.INACTIVE);
                      if (!_this0.apiRequest.isSocketEnabled()) {
                        _context30.next = 4;
                        break;
                      }
                      _context30.prev = 1;
                      _context30.next = 2;
                      return _this0.apiRequest.disconnectFromMobiusSocket({
                        code: 3050,
                        reason: 'done (permanent)'
                      });
                    case 2:
                      _Logger.default.log('Mobius socket disconnect complete after registration-down', loggerContext);
                      _context30.next = 4;
                      break;
                    case 3:
                      _context30.prev = 3;
                      _t9 = _context30["catch"](1);
                      _Logger.default.warn("Mobius socket disconnect failed after registration-down: ".concat(String(_t9)), loggerContext);
                    case 4:
                      _this0.lineEmitter(_types3.LINE_EVENTS.UNREGISTERED);
                    case 5:
                    case "end":
                      return _context30.stop();
                  }
                }, _callee29, null, [[1, 3]]);
              })));
            case 1:
            case "end":
              return _context31.stop();
          }
        }, _callee30, this);
      }));
      function performRegistrationDownCleanup(_x20) {
        return _performRegistrationDownCleanup.apply(this, arguments);
      }
      return performRegistrationDownCleanup;
    }())
  }]);
}();
/*
 */
var createRegistration = exports.createRegistration = function createRegistration(webex, serviceData, mutex, lineEmitter, logLevel, jwe) {
  return new Registration(webex, serviceData, mutex, lineEmitter, logLevel, jwe);
};
//# sourceMappingURL=register.js.map
