"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/master/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 = exports.WAIT_UNTIL_ACTION = 'WAIT_UNTIL_ACTION';
// eslint-disable-next-line func-style
const waitUntilAction = ({
  dispatch,
  getState
}) => {
  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;