(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports", "lodash/omit", "rxjs", "rxjs/operators"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require("lodash/omit"), require("rxjs"), require("rxjs/operators"));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.omit, global.rxjs, global.operators);
    global.send = mod.exports;
  }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _omit, _rxjs, _operators) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.default = _exports.testExports = void 0;
  _omit = _interopRequireDefault(_omit);

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

  const defaultOptions = {
    shouldWaitForConfirmation: false,
    shouldRetry: false,
    maxTimeout: 10000,
    validateResponse: responseArgs => !!responseArgs[0],
    retryDelay: 10000,
    retryCount: 3,
    retryFunction: null
  };

  function getMessageArgs(message) {
    const topic = message.topic || 'message';
    const binary = message.binary ? [message.binary] : [];
    const formattedMessage = (0, _omit.default)(message, 'topic', 'binary');
    return [topic, formattedMessage, ...binary];
  }

  function sendWithTransactions({
    message,
    socket,
    action,
    maxTimeout,
    validateResponse,
    shouldRetry,
    retryDelay,
    retryCount,
    retryFunction
  }) {
    const transaction$ = new _rxjs.Observable(obs => {
      socket.binary(!!message.binary).compress(!!message.binary).emit(...getMessageArgs(message), (...responseArgs) => {
        if (!validateResponse(responseArgs)) {
          return obs.error(new Error('Server did not acknowledge response'));
        }

        obs.next([socket, action]);
        return obs.complete();
      });
    });
    return transaction$.pipe((0, _operators.timeout)(maxTimeout), shouldRetry ? (0, _operators.retryWhen)(retryFunction || (shouldRetry ? error$ => error$.pipe((0, _operators.delay)(retryDelay), (0, _operators.take)(retryCount)) : () => (0, _rxjs.of)())) : (0, _operators.tap)(() => 1));
  }

  function sendMessage(params) {
    const {
      action,
      message,
      shouldWaitForConfirmation,
      socket
    } = params;
    if (shouldWaitForConfirmation) return sendWithTransactions(params);
    socket.binary(!!message.binary).compress(!!message.binary).emit(...getMessageArgs(message));
    return (0, _rxjs.of)([socket, action]);
  }

  const send = function send({
    io$,
    ...options
  }) {
    if (!io$.subscribe) {
      return (0, _rxjs.throwError)(new Error('send() operator takes an Observable as its first parameter.'));
    }

    const config = { ...defaultOptions,
      ...options
    };
    return messageIn$ => {
      const wsEvent$ = io$.pipe((0, _operators.shareReplay)(1));
      const sendStream$ = messageIn$.pipe((0, _operators.withLatestFrom)(wsEvent$), (0, _operators.map)(([message, [socket, action]]) => sendMessage({
        message,
        socket,
        action,
        ...config
      })), (0, _operators.mergeAll)(config.shouldWaitForConfirmation ? 1 : null));
      return (0, _rxjs.merge)(wsEvent$, sendStream$).pipe((0, _operators.filter)(() => false));
    };
  };

  const testExports = {
    sendWithTransactions
  };
  _exports.testExports = testExports;
  var _default = send;
  _exports.default = _default;
});
//# sourceMappingURL=send.js.map