"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.waitUntilAction = exports.WAIT_UNTIL_ACTION = void 0;
// Based on wait-service by Mozilla:
// https://github.com/mozilla/gecko-dev/blob/main/devtools/client/shared/redux/middleware/wait-service.js

/**
 * A middleware that provides the ability for actions to install a
 * function to be run once when a specific condition is met by an
 * action coming through the system. Think of it as a thunk that
 * blocks until the condition is met.
 */
const WAIT_UNTIL_ACTION = 'WAIT_UNTIL_ACTION';
exports.WAIT_UNTIL_ACTION = WAIT_UNTIL_ACTION;

// eslint-disable-next-line func-style
const waitUntilAction = _ref => {
  let {
    dispatch,
    getState
  } = _ref;
  let pending = [];

  function checkPending(action) {
    const readyRequests = [];
    const stillPending = []; // Find the pending requests whose predicates are satisfied with
    // this action. Wait to run the requests until after we update the
    // pending queue because the request handler may synchronously
    // dispatch again and run this service (that use case is
    // completely valid).

    for (const request of pending) {
      if (request.predicate(action)) {
        readyRequests.push(request);
      } else {
        stillPending.push(request);
      }
    }

    pending = stillPending;

    for (const request of readyRequests) {
      request.run(dispatch, getState, action);
    }
  }

  return next => action => {
    if (action.type === WAIT_UNTIL_ACTION) {
      pending.push(action);
      return null;
    }

    const result = next(action);
    checkPending(action);
    return result;
  };
};

exports.waitUntilAction = waitUntilAction;