"use strict";

var _Object$keys = 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 _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
  value: true
});
exports.createAPIRequest = exports.APIRequest = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
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 _uuid = require("uuid");
var _mobiusSocket = require("../../mobius-socket");
var _Logger = _interopRequireDefault(require("../../Logger"));
var _mobiusSocketMapper = require("./mobiusSocketMapper");
var _constants = require("./constants");
var _wsFeatureFlag = require("./wsFeatureFlag");
var _constants2 = require("../constants");
var _Metrics = require("../../Metrics");
var _types = require("../../Metrics/types");
function ownKeys(e, r) { var t = _Object$keys(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; }
/**
 * Converts a MobiusSocketResponse into the WebexRequestPayload shape that
 * all callers (registration, call, keepalive error-handlers) expect.
 */
function normalizeWsResponse(wsResponse) {
  var _ref, _ref2;
  return {
    statusCode: wsResponse.statusCode,
    body: (_ref = wsResponse.data) !== null && _ref !== void 0 ? _ref : undefined,
    headers: _objectSpread({
      trackingid: wsResponse.trackingId
    }, (_ref2 = wsResponse.metadata) !== null && _ref2 !== void 0 ? _ref2 : {})
  };
}

/**
 * Converts a MobiusSocketResponseError rejection into a WebexRequestPayload-shaped
 * error so handleRegistrationErrors / handleCallErrors can process it identically.
 */
function normalizeWsError(err) {
  var _ref3, _wsErr$response, _ref4, _wsErr$trackingId, _wsErr$response2, _ref5, _wsErr$response3;
  var wsErr = err;
  return {
    statusCode: wsErr.statusCode,
    body: (_ref3 = (_wsErr$response = wsErr.response) === null || _wsErr$response === void 0 ? void 0 : _wsErr$response.data) !== null && _ref3 !== void 0 ? _ref3 : undefined,
    headers: _objectSpread({
      trackingid: (_ref4 = (_wsErr$trackingId = wsErr.trackingId) !== null && _wsErr$trackingId !== void 0 ? _wsErr$trackingId : (_wsErr$response2 = wsErr.response) === null || _wsErr$response2 === void 0 ? void 0 : _wsErr$response2.trackingId) !== null && _ref4 !== void 0 ? _ref4 : ''
    }, (_ref5 = (_wsErr$response3 = wsErr.response) === null || _wsErr$response3 === void 0 ? void 0 : _wsErr$response3.metadata) !== null && _ref5 !== void 0 ? _ref5 : {})
  };
}

/**
 * APIRequest routes Mobius traffic over HTTP (`webex.request`) or the Mobius WebSocket path
 * (`mobiusSocketRequest`). `isMobiusSocketEnabled` is set in the constructor from WDM
 * `webrtc-calling-over-ws` and/or SDK config (interim until WDM is fully in prod).
 */
var APIRequest = exports.APIRequest = /*#__PURE__*/function () {
  /**
   * @param config - Webex instance plus optional SDK Mobius-socket override
   */
  function APIRequest(config) {
    (0, _classCallCheck2.default)(this, APIRequest);
    (0, _defineProperty2.default)(this, "isMobiusSocketEnabled", void 0);
    (0, _defineProperty2.default)(this, "webex", void 0);
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    (0, _defineProperty2.default)(this, "mobiusSocket", void 0);
    (0, _defineProperty2.default)(this, "metricManager", void 0);
    var logContext = {
      file: _constants2.REQUEST_FILE,
      method: _constants2.METHODS.CONSTRUCTOR
    };
    if (!config.webex) {
      _Logger.default.error('APIRequest instantiation failed: WebexSDK instance is required', logContext);
      throw new Error('WebexSDK instance is required');
    }
    this.webex = config.webex;
    this.isMobiusSocketEnabled = (0, _wsFeatureFlag.isMobiusWssEnabled)(config.webex) || false;
    this.mobiusSocket = (0, _mobiusSocket.getMobiusSocketInstance)(this.webex);
    this.metricManager = (0, _Metrics.getMetricManager)(this.webex);
    _Logger.default.info("APIRequest initialized with transport: ".concat(this.isMobiusSocketEnabled ? 'WSS' : 'HTTP'), logContext);
  }

  /**
   * Whether the Mobius WebSocket transport is active for this instance.
   */
  return (0, _createClass2.default)(APIRequest, [{
    key: "isSocketEnabled",
    value: function isSocketEnabled() {
      return this.isMobiusSocketEnabled;
    }

    /**
     * Ensures the Mobius WebSocket is connected before sending API requests.
     * If the socket is already connected, resolves immediately. Otherwise,
     * initiates a new connection to the provided WebSocket URL.
     * On failure, throws a normalized WebexRequestPayload-shaped error.
     *
     * @param wssUrl - The Mobius WebSocket URL to connect to.
     */
  }, {
    key: "connectToMobiusSocket",
    value: (function () {
      var _connectToMobiusSocket = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee(wssUrl) {
        var logContext, _this$metricManager, _this$metricManager2, _t;
        return _regenerator.default.wrap(function (_context) {
          while (1) switch (_context.prev = _context.next) {
            case 0:
              logContext = {
                file: _constants2.REQUEST_FILE,
                method: _constants2.METHODS.CONNECT_TO_MOBIUS_SOCKET
              };
              if (!this.mobiusSocket.isConnected()) {
                _context.next = 1;
                break;
              }
              _Logger.default.info('Mobius WebSocket already connected', logContext);
              return _context.abrupt("return", this.mobiusSocket.getConnectedWebSocketUrl());
            case 1:
              _Logger.default.info('Mobius WebSocket not connected, initiating connection', logContext);
              _context.prev = 2;
              _context.next = 3;
              return this.mobiusSocket.connect(wssUrl);
            case 3:
              _Logger.default.log('Mobius WebSocket connected successfully', logContext);
              (_this$metricManager = this.metricManager) === null || _this$metricManager === void 0 ? void 0 : _this$metricManager.submitMobiusSocketMetric(_types.METRIC_EVENT.MOBIUS_SOCKET, _types.MOBIUS_SOCKET_ACTION.CONNECT, _types.METRIC_TYPE.BEHAVIORAL, wssUrl);
              return _context.abrupt("return", wssUrl);
            case 4:
              _context.prev = 4;
              _t = _context["catch"](2);
              _Logger.default.warn("Mobius WebSocket connection failed: ".concat(String(_t)), logContext);
              (_this$metricManager2 = this.metricManager) === null || _this$metricManager2 === void 0 ? void 0 : _this$metricManager2.submitMobiusSocketMetric(_types.METRIC_EVENT.MOBIUS_SOCKET_ERROR, _types.MOBIUS_SOCKET_ACTION.CONNECT, _types.METRIC_TYPE.BEHAVIORAL, wssUrl, undefined, String(_t));
              throw normalizeWsError(_t);
            case 5:
            case "end":
              return _context.stop();
          }
        }, _callee, this, [[2, 4]]);
      }));
      function connectToMobiusSocket(_x) {
        return _connectToMobiusSocket.apply(this, arguments);
      }
      return connectToMobiusSocket;
    }())
  }, {
    key: "getConnectedWebSocketUrl",
    value: function getConnectedWebSocketUrl() {
      return this.mobiusSocket.getConnectedWebSocketUrl();
    }

    /**
     * Disconnects the default session from the Mobius WebSocket.
     */
  }, {
    key: "disconnectFromMobiusSocket",
    value: (function () {
      var _disconnectFromMobiusSocket = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2(options) {
        var logContext, wssUrl, _this$metricManager3, _this$metricManager4, _t2;
        return _regenerator.default.wrap(function (_context2) {
          while (1) switch (_context2.prev = _context2.next) {
            case 0:
              logContext = {
                file: _constants2.REQUEST_FILE,
                method: _constants2.METHODS.DISCONNECT_FROM_MOBIUS_SOCKET
              };
              _Logger.default.info('Disconnecting from Mobius WebSocket', logContext);
              wssUrl = this.mobiusSocket.getConnectedWebSocketUrl();
              _context2.prev = 1;
              _context2.next = 2;
              return this.mobiusSocket.disconnect(options);
            case 2:
              _Logger.default.log('Mobius WebSocket disconnected successfully', logContext);
              (_this$metricManager3 = this.metricManager) === null || _this$metricManager3 === void 0 ? void 0 : _this$metricManager3.submitMobiusSocketMetric(_types.METRIC_EVENT.MOBIUS_SOCKET, _types.MOBIUS_SOCKET_ACTION.DISCONNECT, _types.METRIC_TYPE.BEHAVIORAL, wssUrl);
              _context2.next = 4;
              break;
            case 3:
              _context2.prev = 3;
              _t2 = _context2["catch"](1);
              // silent error - no need to throw an error
              _Logger.default.warn("Mobius WebSocket disconnection failed: ".concat(String(_t2)), logContext);
              (_this$metricManager4 = this.metricManager) === null || _this$metricManager4 === void 0 ? void 0 : _this$metricManager4.submitMobiusSocketMetric(_types.METRIC_EVENT.MOBIUS_SOCKET_ERROR, _types.MOBIUS_SOCKET_ACTION.DISCONNECT, _types.METRIC_TYPE.BEHAVIORAL, wssUrl, undefined,
              // add trackingId
              String(_t2));
            case 4:
            case "end":
              return _context2.stop();
          }
        }, _callee2, this, [[1, 3]]);
      }));
      function disconnectFromMobiusSocket(_x2) {
        return _disconnectFromMobiusSocket.apply(this, arguments);
      }
      return disconnectFromMobiusSocket;
    }()
    /**
     * Makes a request using HTTP or WebSocket transport per the flag set in the constructor.
     * When using WebSocket, the response is normalized to the WebexRequestPayload shape
     * so callers do not need to know which transport was used.
     * @param request - Request options (uri, method, body, headers, service)
     * @returns Promise resolving to WebexRequestPayload
     */
    )
  }, {
    key: "makeRequest",
    value: (function () {
      var _makeRequest = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3(request) {
        var logContext, trackingId, socketType, isSupplementaryService, wsResponse, _t3, _t4, _t5, _t6, _t7, _t8, _t9, _t0, _t1, _t10, _t11, _t12, _t13, _t14;
        return _regenerator.default.wrap(function (_context3) {
          while (1) switch (_context3.prev = _context3.next) {
            case 0:
              logContext = {
                file: _constants2.REQUEST_FILE,
                method: _constants2.METHODS.MAKE_REQUEST
              };
              _Logger.default.info("Dispatching request via ".concat(this.isMobiusSocketEnabled ? 'WSS' : 'HTTP', " "), logContext);
              if (!this.isMobiusSocketEnabled) {
                _context3.next = 8;
                break;
              }
              trackingId = "webex-js-sdk_".concat((0, _uuid.v4)());
              socketType = (0, _mobiusSocketMapper.deriveMobiusSocketMessageType)(request.uri, request.method);
              if (!(socketType === _constants.MOBIUS_SOCKET_MESSAGE_TYPE.UNKNOWN)) {
                _context3.next = 1;
                break;
              }
              _Logger.default.error("Unknown Mobius Socket message type for uri: ".concat(request.uri, ", httpMethod: ").concat(request.method), logContext);
              throw new Error("Unknown Mobius Socket message type: ".concat(socketType));
            case 1:
              isSupplementaryService = (0, _mobiusSocketMapper.isSupplementaryServiceMessageType)(socketType);
              _context3.prev = 2;
              _t3 = this.mobiusSocket;
              _t4 = socketType;
              _t5 = trackingId;
              _t6 = _objectSpread;
              _t7 = _objectSpread({}, request.headers);
              _t8 = {};
              _t9 = _constants2.CALLING_USER_AGENT;
              _t0 = "";
              _t10 = isSupplementaryService;
              if (!_t10) {
                _context3.next = 4;
                break;
              }
              _context3.next = 3;
              return this.webex.credentials.getUserToken();
            case 3:
              _t10 = _context3.sent;
            case 4:
              _t1 = _t10;
              if (_t1) {
                _context3.next = 5;
                break;
              }
              _t1 = '';
            case 5:
              _t11 = _t0.concat.call(_t0, _t1);
              _t12 = _t6(_t7, _t8, {
                userAgent: _t9,
                authorization: _t11
              });
              _t13 = request.body;
              _context3.next = 6;
              return _t3.sendWssRequest.call(_t3, {
                type: _t4,
                trackingId: _t5,
                metadata: _t12,
                data: _t13
              });
            case 6:
              wsResponse = _context3.sent;
              _Logger.default.log("WSS request succeeded - socketType: ".concat(socketType, ", trackingId: ").concat(trackingId, ", statusCode: ").concat(wsResponse.statusCode), logContext);
              return _context3.abrupt("return", normalizeWsResponse(wsResponse));
            case 7:
              _context3.prev = 7;
              _t14 = _context3["catch"](2);
              _Logger.default.error("WSS request failed - socketType: ".concat(socketType, ", trackingId: ").concat(trackingId, ", error: ").concat(String(_t14)), logContext);
              throw normalizeWsError(_t14);
            case 8:
              return _context3.abrupt("return", this.webex.request(request));
            case 9:
            case "end":
              return _context3.stop();
          }
        }, _callee3, this, [[2, 7]]);
      }));
      function makeRequest(_x3) {
        return _makeRequest.apply(this, arguments);
      }
      return makeRequest;
    }())
  }, {
    key: "registerMobiusSocketListener",
    value: function registerMobiusSocketListener(cb) {
      var _this$metricManager5;
      var logContext = {
        file: _constants2.REQUEST_FILE,
        method: _constants2.METHODS.REGISTER_MOBIUS_SOCKET_LISTENER
      };
      _Logger.default.info('Attaching Mobius async event listener', logContext);
      this.mobiusSocket.on('event:async_event', function (data) {
        var _data$data$eventType, _data$data;
        _Logger.default.trace("Mobius async event received - eventType: ".concat((_data$data$eventType = data === null || data === void 0 ? void 0 : (_data$data = data.data) === null || _data$data === void 0 ? void 0 : _data$data.eventType) !== null && _data$data$eventType !== void 0 ? _data$data$eventType : 'unknown'), logContext);
        cb(data);
      });
      _Logger.default.log('Mobius async event listener attached', logContext);
      (_this$metricManager5 = this.metricManager) === null || _this$metricManager5 === void 0 ? void 0 : _this$metricManager5.submitMobiusSocketMetric(_types.METRIC_EVENT.MOBIUS_SOCKET, _types.MOBIUS_SOCKET_ACTION.LISTENER_REGISTERED, _types.METRIC_TYPE.BEHAVIORAL);
    }
  }, {
    key: "unregisterMobiusSocketListener",
    value: function unregisterMobiusSocketListener() {
      var _this$metricManager6;
      var logContext = {
        file: _constants2.REQUEST_FILE,
        method: _constants2.METHODS.UNREGISTER_MOBIUS_SOCKET_LISTENER
      };
      _Logger.default.info('Detaching Mobius async event listener', logContext);
      this.mobiusSocket.off('event:async_event');
      _Logger.default.log('Mobius async event listener detached', logContext);
      (_this$metricManager6 = this.metricManager) === null || _this$metricManager6 === void 0 ? void 0 : _this$metricManager6.submitMobiusSocketMetric(_types.METRIC_EVENT.MOBIUS_SOCKET, _types.MOBIUS_SOCKET_ACTION.LISTENER_UNREGISTERED, _types.METRIC_TYPE.BEHAVIORAL);
    }
  }], [{
    key: "getInstance",
    value: function getInstance(config) {
      if (!APIRequest.instance) {
        APIRequest.instance = new APIRequest(config);
      }
      return APIRequest.instance;
    }
  }, {
    key: "resetInstance",
    value: function resetInstance() {
      APIRequest.instance = undefined;
    }
  }]);
}();
/**
 * Factory function to create a singleton APIRequest instance
 * @param config - Configuration object for APIRequest
 * @returns APIRequest instance
 */
// eslint-disable-next-line no-use-before-define
(0, _defineProperty2.default)(APIRequest, "instance", void 0);
var createAPIRequest = exports.createAPIRequest = function createAPIRequest(config) {
  return APIRequest.getInstance(config);
};
//# sourceMappingURL=request.js.map
