"use strict";

var _typeof = require("@babel/runtime-corejs2/helpers/typeof");
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 _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 _WeakMap = require("@babel/runtime-corejs2/core-js/weak-map");
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
  value: true
});
exports.emitFinalFailure = emitFinalFailure;
exports.fetchVoicemailList = fetchVoicemailList;
exports.filterMobiusUris = filterMobiusUris;
exports.getCallingBackEnd = getCallingBackEnd;
exports.getSortedVoicemailList = getSortedVoicemailList;
exports.getVgActionEndpoint = getVgActionEndpoint;
exports.getXsiActionEndpoint = getXsiActionEndpoint;
exports.handleCallErrors = handleCallErrors;
exports.handleCallingClientErrors = handleCallingClientErrors;
exports.handleRegistrationErrors = handleRegistrationErrors;
exports.inferIdFromUuid = inferIdFromUuid;
exports.isValidServiceDomain = isValidServiceDomain;
exports.modifySdpForIPv4 = modifySdpForIPv4;
exports.normalizeMobiusUris = normalizeMobiusUris;
exports.parseMediaQualityStatistics = parseMediaQualityStatistics;
exports.resolveCallerIdByName = resolveCallerIdByName;
exports.resolveCallerIdDisplay = resolveCallerIdDisplay;
exports.resolveContact = resolveContact;
exports.scimQuery = scimQuery;
exports.serviceErrorCodeHandler = serviceErrorCodeHandler;
exports.storeVoicemailList = storeVoicemailList;
exports.uploadLogs = uploadLogs;
exports.validateServiceData = validateServiceData;
exports.waitForMsecs = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
var _values = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/values"));
var _parseInt2 = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/parse-int"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
var platform = _interopRequireWildcard(require("platform"));
var _uuid = require("uuid");
var _types = require("../Metrics/types");
var _Metrics = require("../Metrics");
var _CallError = require("../Errors/catalog/CallError");
var _types2 = require("../Errors/types");
var _types3 = require("./types");
var _Logger = _interopRequireDefault(require("../Logger"));
var _CallingDeviceError = require("../Errors/catalog/CallingDeviceError");
var _constants = require("../CallingClient/constants");
var _constants2 = require("./constants");
var _SDKConnector = _interopRequireDefault(require("../SDKConnector"));
var _LineError = require("../Errors/catalog/LineError");
function _interopRequireWildcard(e, t) { if ("function" == typeof _WeakMap) var r = new _WeakMap(), n = new _WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t1 in e) "default" !== _t1 && {}.hasOwnProperty.call(e, _t1) && ((i = (o = _Object$defineProperty) && _Object$getOwnPropertyDescriptor(e, _t1)) && (i.get || i.set) ? o(f, _t1, i) : f[_t1] = e[_t1]); return f; })(e, t); }
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; }
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; } /* eslint-disable no-fallthrough */ /* eslint-disable no-underscore-dangle */ /* eslint-disable @typescript-eslint/no-shadow */
function filterMobiusUris(mobiusServers, defaultMobiusUrl) {
  var _mobiusServers$primar, _mobiusServers$primar2, _mobiusServers$backup, _mobiusServers$backup2;
  var logContext = {
    file: _constants.UTILS_FILE,
    method: 'filterMobiusUris'
  };
  var urisArrayPrimary = [];
  var urisArrayBackup = [];
  var wssArrayPrimary = [];
  var wssArrayBackup = [];
  if (mobiusServers !== null && mobiusServers !== void 0 && (_mobiusServers$primar = mobiusServers.primary) !== null && _mobiusServers$primar !== void 0 && _mobiusServers$primar.uris) {
    _Logger.default.info('Adding Primary uris', logContext);
    var _iterator = _createForOfIteratorHelper(mobiusServers.primary.uris),
      _step;
    try {
      for (_iterator.s(); !(_step = _iterator.n()).done;) {
        var uri = _step.value;
        urisArrayPrimary.push("".concat(uri).concat(_constants.URL_ENDPOINT));
      }
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }
  }
  if (mobiusServers !== null && mobiusServers !== void 0 && (_mobiusServers$primar2 = mobiusServers.primary) !== null && _mobiusServers$primar2 !== void 0 && _mobiusServers$primar2.wss) {
    _Logger.default.info('Adding Primary wss uris', logContext);
    var _iterator2 = _createForOfIteratorHelper(mobiusServers.primary.wss),
      _step2;
    try {
      for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
        var wssUri = _step2.value;
        wssArrayPrimary.push(wssUri);
      }
    } catch (err) {
      _iterator2.e(err);
    } finally {
      _iterator2.f();
    }
  }
  if (mobiusServers !== null && mobiusServers !== void 0 && (_mobiusServers$backup = mobiusServers.backup) !== null && _mobiusServers$backup !== void 0 && _mobiusServers$backup.uris) {
    _Logger.default.info('Adding Backup uris', logContext);
    var _iterator3 = _createForOfIteratorHelper(mobiusServers.backup.uris),
      _step3;
    try {
      for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
        var _uri = _step3.value;
        urisArrayBackup.push("".concat(_uri).concat(_constants.URL_ENDPOINT));
      }
    } catch (err) {
      _iterator3.e(err);
    } finally {
      _iterator3.f();
    }
  }
  if (mobiusServers !== null && mobiusServers !== void 0 && (_mobiusServers$backup2 = mobiusServers.backup) !== null && _mobiusServers$backup2 !== void 0 && _mobiusServers$backup2.wss) {
    _Logger.default.info('Adding Backup wss uris', logContext);
    var _iterator4 = _createForOfIteratorHelper(mobiusServers.backup.wss),
      _step4;
    try {
      for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
        var _wssUri = _step4.value;
        wssArrayBackup.push(_wssUri);
      }
    } catch (err) {
      _iterator4.e(err);
    } finally {
      _iterator4.f();
    }
  }

  /*
   * If there are no entries in both primary and backup arrays then add the default
   * uri in primary array, otherwise in backup.
   */
  _Logger.default.info('Adding Default uri', logContext);
  if (!urisArrayPrimary.length && !urisArrayBackup.length) {
    urisArrayPrimary.push("".concat(defaultMobiusUrl).concat(_constants.URL_ENDPOINT));
  } else {
    urisArrayBackup.push("".concat(defaultMobiusUrl).concat(_constants.URL_ENDPOINT));
  }
  var primaryUris = [];
  var backupUris = [];
  var primaryWss = [];
  var backupWss = [];

  /* Remove duplicates from primary by keeping the order intact */
  for (var i = 0; i < urisArrayPrimary.length; i += 1) {
    if (primaryUris.indexOf(urisArrayPrimary[i]) === -1) {
      primaryUris.push(urisArrayPrimary[i]);
    }
  }

  /* Remove duplicates from backup by keeping the order intact */
  for (var _i = 0; _i < urisArrayBackup.length; _i += 1) {
    if (backupUris.indexOf(urisArrayBackup[_i]) === -1) {
      backupUris.push(urisArrayBackup[_i]);
    }
  }

  /* Remove duplicates from primary wss by keeping the order intact */
  for (var _i2 = 0; _i2 < wssArrayPrimary.length; _i2 += 1) {
    if (primaryWss.indexOf(wssArrayPrimary[_i2]) === -1) {
      primaryWss.push(wssArrayPrimary[_i2]);
    }
  }

  /* Remove duplicates from backup wss by keeping the order intact */
  for (var _i3 = 0; _i3 < wssArrayBackup.length; _i3 += 1) {
    if (backupWss.indexOf(wssArrayBackup[_i3]) === -1) {
      backupWss.push(wssArrayBackup[_i3]);
    }
  }
  return {
    primary: primaryUris,
    backup: backupUris,
    primaryWss: primaryWss,
    backupWss: backupWss
  };
}

/**
 * Updates the error context for a particular calling client instance.
 *
 * @param errContext - Error Context as generated by the caller.
 * @param type - Error type based on status code.
 * @param message - Custom message for user.
 * @param correlationId - Unique identifier for a call.
 * @param callError - Call error instance.
 */
function updateCallErrorContext(errContext, type, message, correlationId, callError) {
  var errObj = {};
  errObj.context = errContext;
  errObj.type = type;
  errObj.message = message;
  errObj.correlationId = correlationId;
  callError.setCallError(errObj);
}

/**
 * Updates the error context for a particular line instance.
 *
 * @param errContext - Error Context.
 * @param type - Error type based on status code.
 * @param message - Custom message for user.
 * @param status - Status of line.
 * @param lineError - Line error instance.
 */
function updateLineErrorContext(errContext, type, message, status, lineError) {
  var errObj = {};
  errObj.context = errContext;
  errObj.type = type;
  errObj.message = message;
  errObj.status = status;
  lineError.setError(errObj);
}

/**
 * Updates the error context for a particular calling client instance.
 *
 * @param errContext - Error Context as generated by the caller.
 * @param type - Error type based on status code.
 * @param message - Custom message for user.
 * @param clientError - Client Error.
 */
function updateErrorContext(errContext, type, message, clientError) {
  var errObj = {};
  errObj.context = errContext;
  errObj.type = type;
  errObj.message = message;
  clientError.setError(errObj);
}

/**
 * Emits final failure to the client after it gives up
 * retrying registration and records error metric.
 *
 * @param line - Instance of line.
 * @param caller - Method which called this handler.
 * @param file - File name from where error got reported.
 */
function emitFinalFailure(emitterCb, loggerContext, message) {
  var clientError = (0, _LineError.createLineError)(message || '', {}, _types2.ERROR_TYPE.DEFAULT, _types3.RegistrationStatus.INACTIVE);
  updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.SERVICE_UNAVAILABLE, message || 'An unknown error occurred. Wait a moment and try again. Please contact the administrator if the problem persists.', _types3.RegistrationStatus.INACTIVE, clientError);
  emitterCb(clientError);
}

/**
 * Handle various Registration related Error flows here. Decide whether to emit event or retry.
 * @param err - Error body.
 * @param emitterCb - LineErrorEmitterCallback
 * @param loggerContext - Logging context that has method and file name
 * @param restoreRegCb - Callback which will try restoring resgistration in case of 403
 *
 * In emitterCb,
 * For non final error scenarios in registration flow,
 * send Unregistered event only without any error message
 * in order to have the web client update only the UI
 * state to disconnected and not show any error dialog
 * to the end user as in those scenarios a retry will
 * be scheduled to attempt registration again.
 *
 */
function handleRegistrationErrors(_x, _x2, _x3, _x4, _x5) {
  return _handleRegistrationErrors.apply(this, arguments);
}
/**
 * Handle various Error flows related to calling client here. Decide whether to emit event or retry.
 * @param err - Error body.
 * @param emitterCb - CallingClientErrorEmitter
 * @param loggerContext - Logging context that has method and file name
 * @param restoreRegCb - Callback which will try restoring resgistration in case of 403
 */
function _handleRegistrationErrors() {
  _handleRegistrationErrors = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee(err, emitterCb, loggerContext, retry429Cb, restoreRegCb) {
    var serverCount,
      shouldDisconnect,
      lineError,
      errorCode,
      finalError,
      caller,
      retryAfter,
      errorBody,
      code,
      errorMessage,
      _caller,
      _errorMessage,
      _errorMessage2,
      _errorMessage3,
      _args = arguments,
      _t,
      _t2;
    return _regenerator.default.wrap(function (_context) {
      while (1) switch (_context.prev = _context.next) {
        case 0:
          serverCount = _args.length > 5 && _args[5] !== undefined ? _args[5] : 1;
          shouldDisconnect = false;
          lineError = (0, _LineError.createLineError)('', {}, _types2.ERROR_TYPE.DEFAULT, _types3.RegistrationStatus.INACTIVE);
          errorCode = Number(err.statusCode);
          finalError = false;
          _Logger.default.warn("Status code: -> ".concat(errorCode), loggerContext);
          _t = errorCode;
          _context.next = _t === _types2.ERROR_CODE.BAD_REQUEST ? 1 : _t === _types2.ERROR_CODE.UNAUTHORIZED ? 2 : _t === _types2.ERROR_CODE.DEVICE_NOT_FOUND ? 3 : _t === _types2.ERROR_CODE.TOO_MANY_REQUESTS ? 4 : _t === _types2.ERROR_CODE.INTERNAL_SERVER_ERROR ? 6 : _t === _types2.ERROR_CODE.SERVICE_UNAVAILABLE ? 7 : _t === _types2.ERROR_CODE.FORBIDDEN ? 8 : 16;
          break;
        case 1:
          finalError = true;
          _Logger.default.warn("400 Bad Request", loggerContext);
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.BAD_REQUEST, 'Invalid input. Please verify the required parameters, sign out and then sign back in with the valid data', _types3.RegistrationStatus.INACTIVE, lineError);
          emitterCb(lineError, finalError);
          shouldDisconnect = serverCount > 1;
          return _context.abrupt("continue", 17);
        case 2:
          // Return it to the Caller
          finalError = true;
          _Logger.default.warn("401 Unauthorized", loggerContext);
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.TOKEN_ERROR, 'User is unauthorized due to an expired token. Sign out, then sign back in.', _types3.RegistrationStatus.INACTIVE, lineError);
          emitterCb(lineError, finalError);
          shouldDisconnect = serverCount > 1;
          return _context.abrupt("continue", 17);
        case 3:
          finalError = true;
          _Logger.default.warn("404 Device Not Found", loggerContext);
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.NOT_FOUND, 'Webex Calling is unable to find your device. Sign out, then sign back in', _types3.RegistrationStatus.INACTIVE, lineError);
          emitterCb(lineError, finalError);
          shouldDisconnect = serverCount > 1;
          return _context.abrupt("continue", 17);
        case 4:
          _Logger.default.warn("429 Too Many Requests", loggerContext);
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.TOO_MANY_REQUESTS, 'Server is handling too many request at the time. Wait a moment and try again', _types3.RegistrationStatus.INACTIVE, lineError);
          caller = loggerContext.method || 'handleErrors';
          if (!(retry429Cb && err.headers)) {
            _context.next = 5;
            break;
          }
          retryAfter = Number(err.headers['retry-after']);
          _context.next = 5;
          return retry429Cb(retryAfter, caller);
        case 5:
          shouldDisconnect = false;
          return _context.abrupt("continue", 17);
        case 6:
          _Logger.default.warn("500 Internal Server Error", loggerContext);
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred while placing the request. Wait a moment and try again.', _types3.RegistrationStatus.INACTIVE, lineError);
          emitterCb(lineError, finalError);
          shouldDisconnect = serverCount > 1;
          return _context.abrupt("continue", 17);
        case 7:
          _Logger.default.warn("503 Service Unavailable", loggerContext);
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.SERVICE_UNAVAILABLE, 'An error occurred on the server while processing the request. Wait a moment and try again.', _types3.RegistrationStatus.INACTIVE, lineError);
          emitterCb(lineError, finalError);
          shouldDisconnect = serverCount > 1;
          return _context.abrupt("continue", 17);
        case 8:
          _Logger.default.warn("403 Forbidden", loggerContext);
          errorBody = err.body;
          if (errorBody) {
            _context.next = 9;
            break;
          }
          _Logger.default.warn('Error response has no body, throwing default error', loggerContext);
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.FORBIDDEN_ERROR, 'An unauthorized action has been received. This action has been blocked. Please contact the administrator if this persists.', _types3.RegistrationStatus.INACTIVE, lineError);
          emitterCb(lineError, finalError);
          shouldDisconnect = serverCount > 1;
          return _context.abrupt("return", {
            finalError: finalError,
            shouldDisconnect: shouldDisconnect
          });
        case 9:
          code = Number(errorBody.errorCode);
          _Logger.default.warn("Error code found : ".concat(code), loggerContext);
          _t2 = code;
          _context.next = _t2 === _types2.DEVICE_ERROR_CODE.DEVICE_LIMIT_EXCEEDED ? 10 : _t2 === _types2.DEVICE_ERROR_CODE.DEVICE_CREATION_DISABLED ? 12 : _t2 === _types2.DEVICE_ERROR_CODE.DEVICE_CREATION_FAILED ? 13 : 14;
          break;
        case 10:
          errorMessage = 'User device limit exceeded';
          _Logger.default.warn(errorMessage, loggerContext);
          if (!restoreRegCb) {
            _context.next = 11;
            break;
          }
          _caller = loggerContext.method || 'handleErrors';
          _context.next = 11;
          return restoreRegCb(errorBody, _caller);
        case 11:
          shouldDisconnect = false;
          return _context.abrupt("continue", 15);
        case 12:
          _errorMessage = 'User is not configured for WebRTC calling. Please contact the administrator to resolve this issue.';
          finalError = true;
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.FORBIDDEN_ERROR, _errorMessage, _types3.RegistrationStatus.INACTIVE, lineError);
          _Logger.default.warn(_errorMessage, loggerContext);
          emitterCb(lineError, true);
          shouldDisconnect = true;
          return _context.abrupt("continue", 15);
        case 13:
          _errorMessage2 = 'An unknown error occurred while provisioning the device. Wait a moment and try again.';
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.FORBIDDEN_ERROR, _errorMessage2, _types3.RegistrationStatus.INACTIVE, lineError);
          _Logger.default.warn(_errorMessage2, loggerContext);
          emitterCb(lineError, finalError);
          shouldDisconnect = serverCount > 1;
          return _context.abrupt("continue", 15);
        case 14:
          _errorMessage3 = 'An unknown error occurred. Wait a moment and try again. Please contact the administrator if the problem persists.';
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.FORBIDDEN_ERROR, _errorMessage3, _types3.RegistrationStatus.INACTIVE, lineError);
          _Logger.default.warn(_errorMessage3, loggerContext);
          emitterCb(lineError, finalError);
          shouldDisconnect = serverCount > 1;
        case 15:
          return _context.abrupt("continue", 17);
        case 16:
          updateLineErrorContext(loggerContext, _types2.ERROR_TYPE.DEFAULT, 'Unknown error', _types3.RegistrationStatus.INACTIVE, lineError);
          _Logger.default.warn("Unknown Error", loggerContext);
          emitterCb(lineError, finalError);
          shouldDisconnect = serverCount > 1;
        case 17:
          return _context.abrupt("return", {
            finalError: finalError,
            shouldDisconnect: shouldDisconnect
          });
        case 18:
        case "end":
          return _context.stop();
      }
    }, _callee);
  }));
  return _handleRegistrationErrors.apply(this, arguments);
}
function handleCallingClientErrors(_x6, _x7, _x8) {
  return _handleCallingClientErrors.apply(this, arguments);
}
/**
 * Handler for call related errors.
 *
 * @param emitterCb - Event emitter function.
 * @param errorType - Type of error experienced.
 * @param errorLayer - Call control or media layer.
 * @param retryCb - Failure retry function.
 * @param correlationId - CorrelationId of the call.
 * @param err - Error Response.
 * @param caller - Caller function.
 * @param file - File name.
 *
 * @returns boolean - whether to abort the call or not.
 */
function _handleCallingClientErrors() {
  _handleCallingClientErrors = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2(err, emitterCb, loggerContext) {
    var clientError, errorCode, finalError, _t3;
    return _regenerator.default.wrap(function (_context2) {
      while (1) switch (_context2.prev = _context2.next) {
        case 0:
          clientError = (0, _CallingDeviceError.createClientError)('', {}, _types2.ERROR_TYPE.DEFAULT, _types3.RegistrationStatus.INACTIVE);
          errorCode = Number(err.statusCode);
          finalError = false;
          _Logger.default.warn("Status code: -> ".concat(errorCode), loggerContext);
          _t3 = errorCode;
          _context2.next = _t3 === _types2.ERROR_CODE.UNAUTHORIZED ? 1 : _t3 === _types2.ERROR_CODE.INTERNAL_SERVER_ERROR ? 2 : 3;
          break;
        case 1:
          finalError = true;
          _Logger.default.warn("401 Unauthorized", loggerContext);
          updateErrorContext(loggerContext, _types2.ERROR_TYPE.TOKEN_ERROR, 'User is unauthorized due to an expired token.', clientError);
          emitterCb(clientError, finalError);
          return _context2.abrupt("continue", 4);
        case 2:
          _Logger.default.warn("500 Internal Server Error", loggerContext);
          updateErrorContext(loggerContext, _types2.ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred while placing the request. Wait a moment and try again.', clientError);
          emitterCb(clientError, finalError);
          return _context2.abrupt("continue", 4);
        case 3:
          updateErrorContext(loggerContext, _types2.ERROR_TYPE.DEFAULT, 'Unknown error', clientError);
          _Logger.default.warn("Unknown Error", loggerContext);
          emitterCb(clientError, finalError);
        case 4:
          _context2.next = 5;
          return uploadLogs();
        case 5:
          return _context2.abrupt("return", finalError);
        case 6:
        case "end":
          return _context2.stop();
      }
    }, _callee2);
  }));
  return _handleCallingClientErrors.apply(this, arguments);
}
function handleCallErrors(_x9, _x0, _x1, _x10, _x11, _x12, _x13) {
  return _handleCallErrors.apply(this, arguments);
}
/**
 *Function to return error details.
 *
 * @param errorCode - WebexRequestPayload // Error status code for failed cases.
 * @param err -.
 * @param loggerContext -.
 * @returns Error response (status code and error message).
 */
function _handleCallErrors() {
  _handleCallErrors = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3(emitterCb, errorLayer, retryCb, correlationId, err, caller, file) {
    var abort, loggerContext, callError, errorCode, isKeepalive, errorBody, retryInterval, code, message, _retryInterval, _t4, _t5;
    return _regenerator.default.wrap(function (_context3) {
      while (1) switch (_context3.prev = _context3.next) {
        case 0:
          abort = false;
          loggerContext = {
            file: file,
            method: caller
          };
          callError = (0, _CallError.createCallError)('', loggerContext, _types2.ERROR_TYPE.DEFAULT, '', errorLayer);
          errorCode = Number(err.statusCode);
          _Logger.default.warn("Status code: ->".concat(errorCode), loggerContext);
          isKeepalive = caller === _constants.METHODS.HANDLE_CALL_ESTABLISHED;
          _t4 = errorCode;
          _context3.next = _t4 === _types2.ERROR_CODE.UNAUTHORIZED ? 1 : _t4 === _types2.ERROR_CODE.FORBIDDEN ? 2 : _t4 === _types2.ERROR_CODE.SERVICE_UNAVAILABLE ? 3 : _t4 === _types2.ERROR_CODE.DEVICE_NOT_FOUND ? 17 : _t4 === _types2.ERROR_CODE.INTERNAL_SERVER_ERROR ? 18 : 19;
          break;
        case 1:
          _Logger.default.warn("401 Unauthorized", loggerContext);
          updateCallErrorContext(loggerContext, _types2.ERROR_TYPE.TOKEN_ERROR, 'User is unauthorized due to an expired token. Sign out, then sign back in.', correlationId, callError);
          emitterCb(callError);
          if (isKeepalive) {
            abort = true;
          }
          return _context3.abrupt("continue", 20);
        case 2:
          if (!isKeepalive) {
            _context3.next = 3;
            break;
          }
          abort = true;
          updateCallErrorContext(loggerContext, _types2.ERROR_TYPE.FORBIDDEN_ERROR, 'An unauthorized action has been received. This action has been blocked. Please contact the administrator if this persists.', correlationId, callError);
          emitterCb(callError);
          return _context3.abrupt("continue", 20);
        case 3:
          errorBody = err.body;
          if (errorBody) {
            _context3.next = 4;
            break;
          }
          _Logger.default.warn('Error response has no body, throwing default error', loggerContext);
          updateCallErrorContext(loggerContext, err.statusCode === 403 ? _types2.ERROR_TYPE.FORBIDDEN_ERROR : _types2.ERROR_TYPE.SERVICE_UNAVAILABLE, err.statusCode === 403 ? 'An unauthorized action has been received. This action has been blocked. Please contact the administrator if this persists.' : 'An error occurred on the server while processing the request. Wait a moment and try again.', correlationId, callError);
          emitterCb(callError);
          return _context3.abrupt("return", abort);
        case 4:
          if (!(err.headers && 'retry-after' in err.headers && retryCb)) {
            _context3.next = 5;
            break;
          }
          retryInterval = Number(err.headers['retry-after']);
          _Logger.default.warn("Retry Interval received: ".concat(retryInterval), loggerContext);
          retryCb(retryInterval);
          return _context3.abrupt("return", abort);
        case 5:
          if (isKeepalive) {
            retryCb(_constants.DEFAULT_KEEPALIVE_INTERVAL); // This is applicable only for the keepalive scenario
          }

          /* Handling various Error codes */
          code = Number(errorBody.errorCode);
          _t5 = code;
          _context3.next = _t5 === _types2.CALL_ERROR_CODE.INVALID_STATUS_UPDATE ? 6 : _t5 === _types2.CALL_ERROR_CODE.DEVICE_NOT_REGISTERED ? 7 : _t5 === _types2.CALL_ERROR_CODE.CALL_NOT_FOUND ? 8 : _t5 === _types2.CALL_ERROR_CODE.ERROR_PROCESSING ? 9 : _t5 === _types2.CALL_ERROR_CODE.USER_BUSY ? 10 : _t5 === _types2.CALL_ERROR_CODE.PARSING_ERROR ? 11 : _t5 === _types2.CALL_ERROR_CODE.NOT_ACCEPTABLE ? 12 : _t5 === _types2.CALL_ERROR_CODE.CALL_REJECTED ? 13 : _t5 === _types2.CALL_ERROR_CODE.NOT_AVAILABLE ? 14 : 15;
          break;
        case 6:
          message = 'An invalid status update has been received for the call. Wait a moment and try again.';
          return _context3.abrupt("continue", 16);
        case 7:
          message = 'The client has unregistered. Please wait for the client to register before attempting the call. If error persists, sign out, sign back in and attempt the call.';
          return _context3.abrupt("continue", 16);
        case 8:
          message = 'Call is not found on the server. Wait a moment and try again.';
          return _context3.abrupt("continue", 16);
        case 9:
          message = 'An error occurred while processing the call on the server. Wait a moment and try again.';
          return _context3.abrupt("continue", 16);
        case 10:
          message = 'Called user is busy.';
          return _context3.abrupt("continue", 16);
        case 11:
          message = 'An error occurred while parsing the provided information. Wait a moment and try again.';
          return _context3.abrupt("continue", 16);
        case 12:
          message = 'An error occurred on the server while accepting the call. Wait a moment and try again. Please contact the administrator if this persists.';
          return _context3.abrupt("continue", 16);
        case 13:
          message = 'Call rejected by the server. Wait a moment and try again. Please contact the administrator if this persists.';
          return _context3.abrupt("continue", 16);
        case 14:
          message = 'Calling services not available. Wait a moment and try again. Please contact the administrator if this persists.';
          return _context3.abrupt("continue", 16);
        case 15:
          message = 'An unknown error occurred. Wait a moment and try again.';
        case 16:
          /* We just emit the errors to the app */

          updateCallErrorContext(loggerContext, err.statusCode === 403 ? _types2.ERROR_TYPE.FORBIDDEN_ERROR : _types2.ERROR_TYPE.SERVICE_UNAVAILABLE, message, correlationId, callError);
          emitterCb(callError);
          return _context3.abrupt("continue", 20);
        case 17:
          _Logger.default.warn("404 Call Not Found", loggerContext);
          updateCallErrorContext(loggerContext, _types2.ERROR_TYPE.NOT_FOUND, 'Call is no longer active. Wait a moment and try again.', correlationId, callError);
          emitterCb(callError);
          if (isKeepalive) {
            abort = true;
          }
          return _context3.abrupt("continue", 20);
        case 18:
          _Logger.default.warn("500 Internal Server Error", loggerContext);
          updateCallErrorContext(loggerContext, _types2.ERROR_TYPE.SERVER_ERROR, 'An unknown error occurred in the call. Wait a moment and try again.', correlationId, callError);
          emitterCb(callError);
          if (isKeepalive && retryCb) {
            _retryInterval = err.headers && 'retry-after' in err.headers ? Number(err.headers['retry-after']) : _constants.DEFAULT_KEEPALIVE_INTERVAL;
            retryCb(_retryInterval);
          }
          return _context3.abrupt("continue", 20);
        case 19:
          _Logger.default.warn("Unknown Error", loggerContext);
          updateCallErrorContext(loggerContext, _types2.ERROR_TYPE.DEFAULT, 'An unknown error occurred in the call.', correlationId, callError);
          emitterCb(callError);
        case 20:
          return _context3.abrupt("return", abort);
        case 21:
        case "end":
          return _context3.stop();
      }
    }, _callee3);
  }));
  return _handleCallErrors.apply(this, arguments);
}
function serviceErrorCodeHandler(_x14, _x15) {
  return _serviceErrorCodeHandler.apply(this, arguments);
}
/**
 * @param stats - RTC peer connection stats.
 * @returns CallRtpStats.
 */
function _serviceErrorCodeHandler() {
  _serviceErrorCodeHandler = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4(err, loggerContext) {
    var errorCode, failureMessage, errorDetails, _errorDetails, _errorDetails2, _errorDetails3, _errorDetails4, _errorDetails5, _errorDetails6, _errorDetails7, _errorDetails8, _t6;
    return _regenerator.default.wrap(function (_context4) {
      while (1) switch (_context4.prev = _context4.next) {
        case 0:
          errorCode = Number(err.statusCode);
          failureMessage = 'FAILURE';
          _t6 = errorCode;
          _context4.next = _t6 === _types2.ERROR_CODE.BAD_REQUEST ? 1 : _t6 === _types2.ERROR_CODE.UNAUTHORIZED ? 2 : _t6 === _types2.ERROR_CODE.FORBIDDEN ? 3 : _t6 === _types2.ERROR_CODE.DEVICE_NOT_FOUND ? 4 : _t6 === _types2.ERROR_CODE.REQUEST_TIMEOUT ? 5 : _t6 === _types2.ERROR_CODE.NOT_IMPLEMENTED ? 6 : _t6 === _types2.ERROR_CODE.INTERNAL_SERVER_ERROR ? 7 : _t6 === _types2.ERROR_CODE.SERVICE_UNAVAILABLE ? 8 : 9;
          break;
        case 1:
          _Logger.default.warn("400 Bad request", loggerContext);
          errorDetails = {
            statusCode: 400,
            data: {
              error: '400 Bad request'
            },
            message: failureMessage
          };
          return _context4.abrupt("return", errorDetails);
        case 2:
          _Logger.default.warn("401 User is unauthorised, possible token expiry", loggerContext);
          _errorDetails = {
            statusCode: 401,
            data: {
              error: 'User is unauthorised, possible token expiry'
            },
            message: failureMessage
          };
          return _context4.abrupt("return", _errorDetails);
        case 3:
          _Logger.default.warn("403 User request is forbidden", loggerContext);
          _errorDetails2 = {
            statusCode: 403,
            data: {
              error: 'User request is forbidden'
            },
            message: failureMessage
          };
          return _context4.abrupt("return", _errorDetails2);
        case 4:
          _Logger.default.warn("404 User info not found", loggerContext);
          _errorDetails3 = {
            statusCode: 404,
            data: {
              error: 'User info not found'
            },
            message: failureMessage
          };
          return _context4.abrupt("return", _errorDetails3);
        case 5:
          _Logger.default.warn("408 Request to the server timedout", loggerContext);
          _errorDetails4 = {
            statusCode: 408,
            data: {
              error: 'Request to the server timedout'
            },
            message: failureMessage
          };
          return _context4.abrupt("return", _errorDetails4);
        case 6:
          _Logger.default.warn("501 Not Implemented error occurred", loggerContext);
          _errorDetails5 = {
            statusCode: 501,
            data: {
              error: 'Method is not implemented at the backend'
            },
            message: failureMessage
          };
          return _context4.abrupt("return", _errorDetails5);
        case 7:
          _Logger.default.warn("500 Internal server error occurred", loggerContext);
          _errorDetails6 = {
            statusCode: 500,
            data: {
              error: 'Internal server error occurred'
            },
            message: failureMessage
          };
          return _context4.abrupt("return", _errorDetails6);
        case 8:
          _Logger.default.warn("503 Unable to establish a connection with the server", loggerContext);
          _errorDetails7 = {
            statusCode: 503,
            data: {
              error: 'Unable to establish a connection with the server'
            },
            message: failureMessage
          };
          return _context4.abrupt("return", _errorDetails7);
        case 9:
          _Logger.default.warn("".concat(errorCode || 422, " Exception has occurred"), loggerContext);
          _errorDetails8 = {
            statusCode: errorCode || 422,
            data: {
              error: "".concat(errorCode || 422, " Exception has occurred")
            },
            message: failureMessage
          };
          return _context4.abrupt("return", _errorDetails8);
        case 10:
        case "end":
          return _context4.stop();
      }
    }, _callee4);
  }));
  return _serviceErrorCodeHandler.apply(this, arguments);
}
function parseMediaQualityStatistics(stats) {
  if (!stats || navigator.userAgent.indexOf('Firefox') !== -1) {
    _Logger.default.info('RTCStatsReport is null, adding dummy stats', {
      file: _constants.UTILS_FILE,
      method: 'parseMediaQualityStatistics'
    });
    return _constants.DUMMY_METRICS;
  }
  try {
    var type;
    var id;
    var inboundCodec;
    var outboundCodec;
    var localCandidates = {};
    var candidatePairs = {};
    var codecList = {};
    var rxStat = {};
    var txStat = {};
    var vqPayload = {};
    var jitterBufferDelay = 0;
    var jitterBufferEmittedCount = 0;
    var totalRoundTripTime = 0;
    var roundTripTimeMeasurements = 0;
    var selectedPair = '';
    var bitRate = 0;

    /* Set defaults */
    vqPayload.maxJitter = 0;
    vqPayload.VoPktSizeMs = 20;

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    stats.forEach(function (report) {
      (0, _keys.default)(report).forEach(function (statName) {
        if (statName !== _constants.TIMESTAMP) {
          if (!type || statName === _constants.TYPE) {
            type = report[statName];
          } else if (!id || statName === _constants.MEDIA_ID) {
            id = report[statName];
          } else if (id && id.indexOf(_constants.RTC_ICE_CANDIDATE_PAIR) !== -1) {
            if (statName === _constants.LOCAL_CANDIDATE_ID) {
              candidatePairs[id] = report[statName];
            }
          } else if (id && id.indexOf(_constants.RTC_ICE_CANDIDATE) !== -1) {
            if (statName === _constants.NETWORK_TYPE) {
              localCandidates[id] = report[statName];
            }
          } else if (id && (id.indexOf(_constants.INBOUND_CODEC_MATCH) !== -1 || id.indexOf(_constants.OUTBOUND_CODEC_MATCH) !== -1 || id.indexOf(_constants.RTC_CODEC) !== -1)) {
            if (statName === _constants.MIME_TYPE) {
              codecList[id] = report[statName];
            }
          } else if (type && type === _constants.REMOTE_INBOUND_RTP) {
            switch (statName) {
              case _constants.TOTAL_ROUND_TRIP_TIME:
                {
                  totalRoundTripTime = report[statName];
                  break;
                }
              case _constants.ROUND_TRIP_TIME_MEASUREMENTS:
                {
                  roundTripTimeMeasurements = report[statName];
                  break;
                }
              default:
                {
                  // We don't care about the other stats
                }
            }
          } else if (type && type === _constants.INBOUND_RTP) {
            switch (statName) {
              case _constants.CODEC_ID:
                {
                  inboundCodec = report[statName];
                  break;
                }
              case _constants.PACKETS_RECEIVED:
                {
                  rxStat.Pkt = report[statName];
                  break;
                }
              case _constants.BYTES_RECEIVED:
                {
                  rxStat.Oct = report[statName];
                  break;
                }
              case _constants.PACKETS_DISCARDED:
                {
                  rxStat.LatePkt = report[statName];
                  break;
                }
              case _constants.PACKETS_LOST:
                {
                  rxStat.LostPkt = report[statName];
                  break;
                }
              case _constants.JITTER_BUFFER_DELAY:
                {
                  jitterBufferDelay = report[statName];
                  break;
                }
              case _constants.JITTER_BUFFER_EMITTED_COUNT:
                {
                  jitterBufferEmittedCount = report[statName];
                  break;
                }
              default:
                {
                  // We don't care about the other stats
                }
            }
          } else if (type && type === _constants.TRANSPORT) {
            switch (statName) {
              case _constants.SELECTED_CANDIDATE_PAIR_ID:
                {
                  selectedPair = report[statName];
                  break;
                }
              default:
                {
                  // We don't care about the other stats
                }
            }
          } else if (type && type === _constants.OUTBOUND_RTP) {
            switch (statName) {
              case _constants.CODEC_ID:
                {
                  outboundCodec = report[statName];
                  break;
                }
              case _constants.PACKETS_SENT:
                {
                  txStat.Pkt = report[statName];
                  break;
                }
              case _constants.BYTES_SENT:
                {
                  txStat.Oct = report[statName];
                  break;
                }
              case _constants.TARGET_BIT_RATE:
                {
                  bitRate = report[statName];
                  break;
                }
              default:
                {
                  // We don't care about the other stats
                }
            }
          } else if (type && type === _constants.MEDIA_SOURCE) {
            switch (statName) {
              case _constants.TOTAL_SAMPLES_DURATION:
                {
                  rxStat.Dur = report[statName];
                  txStat.Dur = report[statName];
                  break;
                }
              default:
                {
                  // We don't care about the other stats
                }
            }
          }
        }
      });
    });

    /* One way Delay */
    if (roundTripTimeMeasurements !== 0) {
      vqPayload.VoOneWayDelayMs = totalRoundTripTime / (2 * roundTripTimeMeasurements);
    } else {
      vqPayload.VoOneWayDelayMs = 0;
    }
    /* Application type */
    vqPayload.hwType = "".concat(platform.os, "/").concat(platform.name, "-").concat(platform.version);

    /* Network type */
    vqPayload.networkType = localCandidates[candidatePairs[selectedPair]];

    /* Average Jitter */
    rxStat.AvgJit = jitterBufferDelay / jitterBufferEmittedCount;

    /* Update codec */
    // eslint-disable-next-line prefer-destructuring
    vqPayload.VoRxCodec = codecList[inboundCodec].split('/')[1];
    var txVqPayload = {};

    // eslint-disable-next-line prefer-destructuring
    txVqPayload.VoTxCodec = codecList[outboundCodec].split('/')[1];
    txVqPayload.rtpBitRate = bitRate;
    var byeStats = {};
    rxStat.VQMetrics = vqPayload;
    txStat.VQMetrics = txVqPayload;
    byeStats[_constants.RTP_RX_STAT] = rxStat;
    byeStats[_constants.RTP_TX_STAT] = txStat;
    _Logger.default.log((0, _stringify.default)(byeStats), {
      file: _constants.UTILS_FILE,
      method: 'parseMediaQualityStatistics'
    });
    return byeStats;
  } catch (err) {
    _Logger.default.warn("Caught error while parsing RTP stats, ".concat(err), {
      file: _constants.UTILS_FILE,
      method: 'parseMediaQualityStatistics'
    });
    return _constants.DUMMY_METRICS;
  }
}

/**
 * To simulate delays.
 *
 * @param msec - Amount of delay.
 * @returns - Promise.
 */
var waitForMsecs = exports.waitForMsecs = function waitForMsecs(msec) {
  return new _promise.default(function (resolve) {
    setTimeout(resolve, msec);
  });
};

/**
 * Register calling backend.
 *
 * @param webex -.
 * @returns CallingBackEnd.
 */
function getCallingBackEnd(webex) {
  var entModels = webex.internal.device.features.entitlement.models;
  var callingBackend;
  if (webex.internal.device.callingBehavior === _constants2.NATIVE_WEBEX_TEAMS_CALLING) {
    for (var i = 0; i < entModels.length; i += 1) {
      if (entModels[i][_constants2.VALUES][_constants2.KEY] === _constants2.ENTITLEMENT_BASIC || entModels[i][_constants2.VALUES][_constants2.KEY] === _constants2.ENTITLEMENT_STANDARD) {
        callingBackend = _types3.CALLING_BACKEND.WXC;
        break;
      } else if (entModels[i][_constants2.VALUES][_constants2.KEY] === _constants2.ENTITLEMENT_BROADWORKS_CONN) {
        callingBackend = _types3.CALLING_BACKEND.BWRKS;
        break;
      }
    }
  } else if (webex.internal.device.callingBehavior === _constants2.NATIVE_SIP_CALL_TO_UCM) {
    callingBackend = _types3.CALLING_BACKEND.UCM;
  } else {
    callingBackend = _types3.CALLING_BACKEND.INVALID;
  }
  return callingBackend;
}

/**
 * Register XSI endpoint based on calling backend.
 *
 * @param webex -.
 * @param loggerContext -.
 * @param callingBackend -.
 * @returns Promise.
 */
function getXsiActionEndpoint(_x16, _x17, _x18) {
  return _getXsiActionEndpoint.apply(this, arguments);
}
/**
 * Get sorted VoicemailList based on sort order passed.
 *
 * @param webex - Webex object to get service urls.
 * @param callingBackend - CallingBackend will have info like UCM.
 * @returns VGEndpointUrl.
 */
function _getXsiActionEndpoint() {
  _getXsiActionEndpoint = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee5(webex, loggerContext, callingBackend) {
    var _userIdResponse$heade, userIdResponse, response, xsiEndpoint, _bwTokenResponse$head, bwTokenResponse, _response, _xsiEndpoint, xsiUrl, errorInfo, _t7, _t8;
    return _regenerator.default.wrap(function (_context5) {
      while (1) switch (_context5.prev = _context5.next) {
        case 0:
          _context5.prev = 0;
          _t7 = callingBackend;
          _context5.next = _t7 === _types3.CALLING_BACKEND.WXC ? 1 : _t7 === _types3.CALLING_BACKEND.BWRKS ? 3 : 5;
          break;
        case 1:
          _context5.next = 2;
          return webex.request({
            uri: "".concat(webex.internal.services._serviceUrls.hydra, "/").concat(_constants2.XSI_ACTION_ENDPOINT_ORG_URL_PARAM),
            method: _types3.HTTP_METHODS.GET
          });
        case 2:
          userIdResponse = _context5.sent;
          _Logger.default.log("Response code: ".concat(userIdResponse.statusCode, ", Response trackingid: ").concat(userIdResponse === null || userIdResponse === void 0 ? void 0 : (_userIdResponse$heade = userIdResponse.headers) === null || _userIdResponse$heade === void 0 ? void 0 : _userIdResponse$heade.trackingid), {
            file: _constants.UTILS_FILE,
            method: 'getXsiActionEndpoint'
          });
          response = userIdResponse.body;
          xsiEndpoint = response[_constants2.ITEMS][0][_constants2.XSI_ACTION_ENDPOINT];
          return _context5.abrupt("return", xsiEndpoint);
        case 3:
          _context5.next = 4;
          return webex.request({
            uri: "".concat(webex.internal.services._serviceUrls.wdm, "/").concat(_constants2.DEVICES),
            method: _types3.HTTP_METHODS.GET
          });
        case 4:
          bwTokenResponse = _context5.sent;
          _Logger.default.log("Response code: ".concat(bwTokenResponse.statusCode, ", Response trackingid: ").concat(bwTokenResponse === null || bwTokenResponse === void 0 ? void 0 : (_bwTokenResponse$head = bwTokenResponse.headers) === null || _bwTokenResponse$head === void 0 ? void 0 : _bwTokenResponse$head.trackingid), {
            file: _constants.UTILS_FILE,
            method: 'getXsiActionEndpoint'
          });
          _response = bwTokenResponse.body;
          _xsiEndpoint = _response[_constants2.DEVICES][0][_constants2.SETTINGS][_constants2.BW_XSI_URL];
          xsiUrl = _response[_constants2.DEVICES][0][_constants2.SETTINGS][_constants2.BW_XSI_URL]; // Check if it ends with specific version and slice accordingly
          if (xsiUrl.endsWith(_constants2.BW_XSI_ENDPOINT_VERSION)) {
            _xsiEndpoint = xsiUrl.slice(0, -5); // Remove 'v2.0'
          } else if (xsiUrl.endsWith(_constants2.BW_XSI_ENDPOINT_VERSION_WITH_SLASH)) {
            _xsiEndpoint = xsiUrl.slice(0, -6); // Remove 'v2.0/'
          }
          return _context5.abrupt("return", _xsiEndpoint);
        case 5:
          throw new Error('Calling backend is not identified, exiting....');
        case 6:
          _context5.next = 8;
          break;
        case 7:
          _context5.prev = 7;
          _t8 = _context5["catch"](0);
          errorInfo = _t8;
          serviceErrorCodeHandler(errorInfo, loggerContext);
          return _context5.abrupt("return", errorInfo);
        case 8:
        case "end":
          return _context5.stop();
      }
    }, _callee5, null, [[0, 7]]);
  }));
  return _getXsiActionEndpoint.apply(this, arguments);
}
function getVgActionEndpoint(webex, callingBackend) {
  try {
    if (callingBackend && callingBackend === _types3.CALLING_BACKEND.UCM) {
      return webex.internal.services._serviceUrls['ucmgmt-gateway'];
    }
    throw new Error('Calling backend is not identified, exiting....');
  } catch (err) {
    var errorInfo = err;
    return errorInfo;
  }
}

/**
 * Get sorted VoiceMailList based on sort order passed.
 *
 * @param voiceMessageList - List of voicemessage.
 * @param sortOrder - Type of sort either ascending or descending.
 * @returns Sorted voicemessageList .
 */
function getSortedVoicemailList(voiceMessageList, sortOrder) {
  /* istanbul ignore else */
  if (sortOrder === _types3.SORT.DESC) {
    voiceMessageList.sort(function (voiceMail, nextVoiceMail) {
      return nextVoiceMail[_constants2.TIME][_constants2.PLACEHOLDER_KEY] - voiceMail[_constants2.TIME][_constants2.PLACEHOLDER_KEY];
    });
  } else if (sortOrder === _types3.SORT.ASC) {
    voiceMessageList.sort(function (voiceMail, nextVoiceMail) {
      return voiceMail[_constants2.TIME][_constants2.PLACEHOLDER_KEY] - nextVoiceMail[_constants2.TIME][_constants2.PLACEHOLDER_KEY];
    });
  }
  return voiceMessageList;
}

/**
 *  Handler to perform a SCIM Query.
 *
 * @param filter - A filter for the query.
 * @returns - Promise.
 */
function scimQuery(_x19) {
  return _scimQuery.apply(this, arguments);
}
/**
 * Resolve Caller Id display information using SCIM query.
 *
 * @param filter - CI userId.
 */
function _scimQuery() {
  _scimQuery = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee6(filter) {
    var _response$headers;
    var sdkConnector, webex, isProd, webexHost, scimUrl, query, response;
    return _regenerator.default.wrap(function (_context6) {
      while (1) switch (_context6.prev = _context6.next) {
        case 0:
          _Logger.default.info("Starting resolution for filter:- ".concat(filter), {
            file: _constants.UTILS_FILE,
            method: 'scimQuery'
          });
          sdkConnector = _SDKConnector.default;
          webex = sdkConnector.getWebex();
          isProd = !webex.internal.device.url.includes('-int');
          webexHost = isProd ? _constants2.WEBEX_API_PROD : _constants2.WEBEX_API_BTS;
          scimUrl = "".concat(webexHost, "/").concat(_constants2.IDENTITY_ENDPOINT_RESOURCE, "/").concat(_constants2.SCIM_ENDPOINT_RESOURCE, "/").concat(webex.internal.device.orgId, "/").concat(_constants2.SCIM_USER_FILTER);
          query = scimUrl + encodeURIComponent(filter);
          _context6.next = 1;
          return webex.request({
            uri: query,
            method: _types3.HTTP_METHODS.GET,
            headers: (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _constants.CISCO_DEVICE_URL, webex.internal.device.url), _constants.SPARK_USER_AGENT, _constants.CALLING_USER_AGENT)
          });
        case 1:
          response = _context6.sent;
          _Logger.default.log("Response code: ".concat(response.statusCode, ", Response trackingid: ").concat(response === null || response === void 0 ? void 0 : (_response$headers = response.headers) === null || _response$headers === void 0 ? void 0 : _response$headers.trackingid), {
            file: _constants.UTILS_FILE,
            method: 'scimQuery'
          });
          return _context6.abrupt("return", response);
        case 2:
        case "end":
          return _context6.stop();
      }
    }, _callee6);
  }));
  return _scimQuery.apply(this, arguments);
}
function resolveCallerIdDisplay(_x20) {
  return _resolveCallerIdDisplay.apply(this, arguments);
}
/**
 * Resolve contact info from display name, using people search API.
 *
 * @param name - Display name.
 */
function _resolveCallerIdDisplay() {
  _resolveCallerIdDisplay = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee7(filter) {
    var _resolution;
    var resolution, displayResult, response, res, _scimResource$phoneNu, _scimResource$phoneNu2, _scimResource$photos, scimResource, numberObj, photo, _t9;
    return _regenerator.default.wrap(function (_context7) {
      while (1) switch (_context7.prev = _context7.next) {
        case 0:
          displayResult = {};
          _context7.prev = 1;
          _context7.next = 2;
          return scimQuery(filter);
        case 2:
          response = _context7.sent;
          resolution = response.body;
          _Logger.default.info("Number of records found for this user :- ".concat(resolution.totalResults), {
            file: _constants.UTILS_FILE,
            method: 'resolveCallerIdDisplay'
          });
          _context7.next = 4;
          break;
        case 3:
          _context7.prev = 3;
          _t9 = _context7["catch"](1);
          res = _t9;
          _Logger.default.warn("Error response: - ".concat(res.statusCode), {
            file: _constants.UTILS_FILE,
            method: 'resolveCallerIdDisplay'
          });
        case 4:
          if ((_resolution = resolution) !== null && _resolution !== void 0 && _resolution.totalResults && resolution.totalResults > 0) {
            /* Every user has single resource from what we have discussed. May need to revisit this later
             * for shared-line use-cases.
             */
            scimResource = resolution.Resources[0];
            displayResult.name = scimResource.displayName;

            /* Pick only the primary number  OR  2nd preference Work */
            numberObj = ((_scimResource$phoneNu = scimResource.phoneNumbers) === null || _scimResource$phoneNu === void 0 ? void 0 : _scimResource$phoneNu.find(function (num) {
              return num.primary;
            })) || ((_scimResource$phoneNu2 = scimResource.phoneNumbers) === null || _scimResource$phoneNu2 === void 0 ? void 0 : _scimResource$phoneNu2.find(function (num) {
              return num.type.toLowerCase() === 'work';
            }));
            if (numberObj) {
              displayResult.num = numberObj.value;
            } else if (scimResource.phoneNumbers && scimResource.phoneNumbers.length > 0) {
              /* When no primary number exists OR PA-ID/From failed to populate, we take the first number */
              _Logger.default.info('Failure to resolve caller information. Setting number as caller ID', {
                file: _constants.UTILS_FILE,
                method: 'resolveCallerIdDisplay'
              });
              displayResult.num = scimResource.phoneNumbers[0].value;
            }

            /* For Webapp, we are only picking thumbnail photo */
            photo = (_scimResource$photos = scimResource.photos) === null || _scimResource$photos === void 0 ? void 0 : _scimResource$photos.find(function (photo) {
              return photo.type === 'thumbnail';
            });
            displayResult.avatarSrc = photo ? photo.value : 'unknown';
            displayResult.id = scimResource.id;
          }
          return _context7.abrupt("return", displayResult);
        case 5:
        case "end":
          return _context7.stop();
      }
    }, _callee7, null, [[1, 3]]);
  }));
  return _resolveCallerIdDisplay.apply(this, arguments);
}
function resolveCallerIdByName(_x21) {
  return _resolveCallerIdByName.apply(this, arguments);
}
/**
 * Resolve the contact information.
 *
 * @param callingPartyInfo - Calling Party Info.
 */
function _resolveCallerIdByName() {
  _resolveCallerIdByName = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee8(name) {
    var displayResult, sdkConnector, webex, searchDirectory;
    return _regenerator.default.wrap(function (_context8) {
      while (1) switch (_context8.prev = _context8.next) {
        case 0:
          displayResult = {};
          sdkConnector = _SDKConnector.default;
          webex = sdkConnector.getWebex();
          /**
           * @param query - Display name.
           */
          searchDirectory = function searchDirectory(query) {
            return webex.people.list({
              displayName: query
            });
          };
          _context8.next = 1;
          return searchDirectory(name).then(function (results) {
            _Logger.default.info("DS Result: ".concat(results), {
              file: _constants.UTILS_FILE,
              method: 'resolveCallerIdByName'
            });
            if (results && results.items && results.items.length > 0) {
              var resolution = results.items[0];
              displayResult.name = resolution.displayName;

              /* id is like cisco spark://us/PEOPLE/b853bbd1-1136-4d25-938d-0c37541b1234
               *  We need to extract UUID portion. */
              var id = Buffer.from(resolution.id, 'base64').toString('binary');
              displayResult.id = id.split('/').pop();
              var numObj = resolution.phoneNumbers.find(function (num) {
                return num.type === 'work';
              });
              if (numObj) {
                displayResult.num = numObj.value;
              } else if (resolution.phoneNumbers.length > 0) {
                displayResult.num = resolution.phoneNumbers[0].value;
              }
              displayResult.avatarSrc = resolution.avatar;
              _Logger.default.info("Extracted details:- name: ".concat(displayResult.name, " , number: ").concat(displayResult.num, ", photo: ").concat(displayResult.avatarSrc, ", id: ").concat(displayResult.id), {
                file: _constants.UTILS_FILE,
                method: 'resolveCallerIdByName'
              });
            }
          });
        case 1:
          return _context8.abrupt("return", displayResult);
        case 2:
        case "end":
          return _context8.stop();
      }
    }, _callee8);
  }));
  return _resolveCallerIdByName.apply(this, arguments);
}
function resolveContact(_x22) {
  return _resolveContact.apply(this, arguments);
}
/**
 * Store encrypted voicemailList in SessionStorage.
 *
 * @param context - Context for storage.
 * @param voiceMessageList - List of voicemessage.
 */
function _resolveContact() {
  _resolveContact = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee9(callingPartyInfo) {
    return _regenerator.default.wrap(function (_context9) {
      while (1) switch (_context9.prev = _context9.next) {
        case 0:
          if (!(callingPartyInfo.userExternalId && callingPartyInfo.userExternalId.$)) {
            _context9.next = 1;
            break;
          }
          return _context9.abrupt("return", resolveCallerIdDisplay("id eq \"".concat(callingPartyInfo.userExternalId.$, "\"")));
        case 1:
          if (!(callingPartyInfo.name && callingPartyInfo.name.$)) {
            _context9.next = 2;
            break;
          }
          return _context9.abrupt("return", resolveCallerIdByName(callingPartyInfo.name.$));
        case 2:
          return _context9.abrupt("return", null);
        case 3:
        case "end":
          return _context9.stop();
      }
    }, _callee9);
  }));
  return _resolveContact.apply(this, arguments);
}
function storeVoicemailList(context, voiceMessageList) {
  var vmEncodedList = Buffer.from((0, _stringify.default)(voiceMessageList), 'utf8').toString('base64');
  sessionStorage.setItem(context, vmEncodedList.toString());
}

/**
 * Fetch decrypted voicemailList from SessionStorage.
 *
 * @param context - Context for the storage.
 * @param offset - Number of voicemail records to skip.
 * @param offsetLimit - Number of voicemail list to fetch from the offset.
 * @param loggerContext - File, method name object.
 * @returns - Array containing voicemails and flag to indicate availability of more voicemails.
 */
function fetchVoicemailList(context, offset, offsetLimit, loggerContext) {
  var moreVoicemails = false;
  var requiredVoicemailList = [];
  try {
    var voicemailList = JSON.parse(Buffer.from(sessionStorage.getItem(context), 'base64').toString('utf8'));
    _Logger.default.info("Length of voicemail list:  ".concat(voicemailList.length), loggerContext);
    if (voicemailList.length > offset + offsetLimit) {
      moreVoicemails = true;
    }
    requiredVoicemailList = voicemailList.slice(offset, offset + offsetLimit);
  } catch (err) {
    _Logger.default.warn("Caught exception while fetching voicemail from storage. ".concat(err), loggerContext);
    var errorInfo = err;
    serviceErrorCodeHandler(errorInfo, {});
  }
  return {
    messages: requiredVoicemailList,
    moreVMAvailable: moreVoicemails
  };
}

/**
 * Converts a uuid to a hydra id without a network dip.
 *
 * @param id - ID to be encoded to base64.
 * @param decodeType - DecodeType.
 * @returns - Encoded string value.
 */
function inferIdFromUuid(id, decodeType) {
  return Buffer.from("".concat(_constants2.INFER_ID_CONSTANT, "/").concat(decodeType, "/").concat(id), 'binary').toString('base64');
}

/**
 * Validates service indicator.
 *
 * @param indicator - Must match with one of the values in ServiceIndicator enum.
 * @returns True if validation is successful else false.
 */
function isValidServiceIndicator(indicator) {
  return (0, _values.default)(_types3.ServiceIndicator).some(function (v) {
    return v === indicator;
  });
}

/**
 * Validates domain field in input service data object.
 * Domain value must be in valid domain format for service
 * type contactcenter.
 * But for service type calling it's allowed to be empty or
 * undefined however if it's not empty/undefined for service
 * type calling then even that will be validated to see if it
 * is in valid domain format.
 *
 * @param serviceData - .
 * @returns True if validation is successful else false.
 */
function isValidServiceDomain(serviceData) {
  var regexp = /^[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,6}$/i;
  var domain = serviceData.domain;
  if (!domain) {
    return serviceData.indicator === _types3.ServiceIndicator.CALLING || serviceData.indicator === _types3.ServiceIndicator.GUEST_CALLING;
  }
  return regexp.test(domain);
}

/**
 * Validates service data object(indicator) and throws
 * exception with a message indicating the reason for validation
 * failure.
 *
 * @param serviceData - Input service data to be validated.
 */
function validateServiceData(serviceData) {
  var allowedValues = (0, _values.default)(_types3.ServiceIndicator);
  var formattedValues = allowedValues.join(', ').replace(/,([^,]*)$/, ' and$1');
  if (!isValidServiceIndicator(serviceData.indicator)) {
    throw new Error("Invalid service indicator, Allowed values are: ".concat(formattedValues));
  }
}

/**
 * Modifies SDP to replace IPv6 "c=" lines with IPv4.And adds an IPv4 candidate if none exists.
 *
 * @param sdp - Session Description Protocol string.
 * @returns Modified SDP string.
 */
function modifySdpForIPv4(sdp) {
  try {
    // Normalize line endings to avoid issues
    sdp = sdp.replace(/\r\n|\r/g, '\n');

    // Ensure consistent spacing without removing intentional indentation
    sdp = sdp.replace(/^[ \t]+/gm, '');

    // Check if at least one IPv6 "c=" line is present
    var ipv6CLineMatches = sdp.match(/c=IN IP6 [\da-f:.]+/gi) || [];
    var hasIPv6CLine = ipv6CLineMatches.length > 0;
    if (hasIPv6CLine) {
      _Logger.default.info('Modifying SDP for IPv4 compatibility', {
        file: _constants.UTILS_FILE,
        method: 'modifySdpForIPv4'
      });

      // Extract an existing IPv4 candidate's IP, if available
      var ipv4CandidateMatch = sdp.match(/a=candidate:\d+ \d+ \w+ \d+ ([\d.]+) \d+ typ \w+/);
      var ipv4Address = (ipv4CandidateMatch === null || ipv4CandidateMatch === void 0 ? void 0 : ipv4CandidateMatch[1]) || '192.1.1.1'; // Default fallback

      // Replace all IPv6 "c=" lines with IPv4 using the extracted IP (or default)
      sdp = sdp.replace(/c=IN IP6 [\da-f:.]+/gi, "c=IN IP4 ".concat(ipv4Address));

      // Ensure newline separation between candidate lines
      if (!ipv4CandidateMatch) {
        var ipv4CandidateAdded = false;
        sdp = sdp.replace(/(a=candidate:(\d+) (\d+) (\w+) (\d+) ([\da-f:.]+) (\d+) typ (\w+)[^\n]*)/g, function (match, full, foundation, componentId, transport, priority, connectionAddress, port, candidateType) {
          if (!ipv4CandidateAdded && connectionAddress.includes(':')) {
            // Ensure it's IPv6 and only add once
            ipv4CandidateAdded = true;
            var newFoundation = ((0, _parseInt2.default)(foundation, 10) + 1).toString();
            return "".concat(full, "\n") + "a=candidate:".concat(newFoundation, " ").concat(componentId, " ").concat(transport, " ").concat(priority, " ").concat(ipv4Address, " ").concat(port, " typ ").concat(candidateType, " generation 0 network-id 1 network-cost 10");
          }
          return match;
        });
      }
    }
    return sdp;
  } catch (error) {
    _Logger.default.warn("Error modifying SDP for IPv4 compatibility: ".concat(error), {
      file: _constants.UTILS_FILE,
      method: 'modifySdpForIPv4'
    });
    return sdp; // Return original SDP in case of an error
  }
}

/**
 * Uploads logs to backend.
 *
 * @param metaData - Metadata to be uploaded.
 * @param throwError - Whether to throw exception on failure (default: false).
 * @returns Promise containing upload response if successful.
 */
function uploadLogs() {
  return _uploadLogs.apply(this, arguments);
}
function _uploadLogs() {
  _uploadLogs = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee0() {
    var metaData,
      throwError,
      webex,
      feedbackId,
      response,
      errorLog,
      _args0 = arguments,
      _t0;
    return _regenerator.default.wrap(function (_context0) {
      while (1) switch (_context0.prev = _context0.next) {
        case 0:
          metaData = _args0.length > 0 && _args0[0] !== undefined ? _args0[0] : {};
          throwError = _args0.length > 1 && _args0[1] !== undefined ? _args0[1] : false;
          webex = _SDKConnector.default.getWebex(); // const feedbackId = crypto.randomUUID();
          feedbackId = (0, _uuid.v4)();
          _context0.prev = 1;
          _context0.next = 2;
          return webex.internal.support.submitLogs(_objectSpread(_objectSpread({}, metaData), {}, {
            feedbackId: feedbackId
          }), undefined,
          // we dont send logs but take from webex logger
          {
            type: 'diff'
          } // this is to take the diff logs from previous upload
          );
        case 2:
          response = _context0.sent;
          _Logger.default.info("Logs uploaded successfully with feedbackId: ".concat(feedbackId), {
            file: _constants.UTILS_FILE,
            method: 'uploadLogs'
          });
          (0, _Metrics.getMetricManager)().submitUploadLogsMetric(_types.METRIC_EVENT.UPLOAD_LOGS_SUCCESS, _types.UPLOAD_LOGS_ACTION, _types.METRIC_TYPE.BEHAVIORAL, response === null || response === void 0 ? void 0 : response.trackingid, feedbackId, metaData === null || metaData === void 0 ? void 0 : metaData.correlationId, undefined, metaData === null || metaData === void 0 ? void 0 : metaData.callId, metaData === null || metaData === void 0 ? void 0 : metaData.broadworksCorrelationInfo);
          return _context0.abrupt("return", _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
            trackingid: response.trackingid
          }, response.url ? {
            url: response.url
          } : {}), response.userId ? {
            userId: response.userId
          } : {}), response.correlationId ? {
            correlationId: response.correlationId
          } : {}), metaData !== null && metaData !== void 0 && metaData.broadworksCorrelationInfo ? {
            broadworksCorrelationInfo: metaData === null || metaData === void 0 ? void 0 : metaData.broadworksCorrelationInfo
          } : {}), {}, {
            feedbackId: feedbackId
          }));
        case 3:
          _context0.prev = 3;
          _t0 = _context0["catch"](1);
          errorLog = new Error("Failed to upload Logs ".concat((0, _stringify.default)(_t0)));
          _Logger.default.error(errorLog.message, {
            file: _constants.UTILS_FILE,
            method: 'uploadLogs'
          });
          (0, _Metrics.getMetricManager)().submitUploadLogsMetric(_types.METRIC_EVENT.UPLOAD_LOGS_FAILED, _types.UPLOAD_LOGS_ACTION, _types.METRIC_TYPE.BEHAVIORAL, undefined, feedbackId, metaData === null || metaData === void 0 ? void 0 : metaData.correlationId, errorLog.message, metaData === null || metaData === void 0 ? void 0 : metaData.callId, metaData === null || metaData === void 0 ? void 0 : metaData.broadworksCorrelationInfo);
          if (!throwError) {
            _context0.next = 4;
            break;
          }
          throw _t0;
        case 4:
          return _context0.abrupt("return", undefined);
        case 5:
        case "end":
          return _context0.stop();
      }
    }, _callee0, null, [[1, 3]]);
  }));
  return _uploadLogs.apply(this, arguments);
}
function normalizeMobiusUris(urls) {
  return urls.map(function (url) {
    return !url.endsWith('/') ? "".concat(url, "/") : url;
  });
}
//# sourceMappingURL=Utils.js.map
