text: "use strict";
  var __extends = (this && this.__extends) || (function () {
      var extendStatics = function (d, b) {
          extendStatics = Object.setPrototypeOf ||
              ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
              function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
          return extendStatics(d, b);
      };
      return function (d, b) {
          extendStatics(d, b);
          function __() { this.constructor = d; }
          d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
      };
  })();
  var __assign = (this && this.__assign) || function () {
      __assign = Object.assign || function(t) {
          for (var s, i = 1, n = arguments.length; i < n; i++) {
              s = arguments[i];
              for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                  t[p] = s[p];
          }
          return t;
      };
      return __assign.apply(this, arguments);
  };
  var __rest = (this && this.__rest) || function (s, e) {
      var t = {};
      for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
          t[p] = s[p];
      if (s != null && typeof Object.getOwnPropertySymbols === "function")
          for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
              if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                  t[p[i]] = s[p[i]];
          }
      return t;
  };
  var __importDefault = (this && this.__importDefault) || function (mod) {
      return (mod && mod.__esModule) ? mod : { "default": mod };
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  var react_1 = __importDefault(require("react"));
  var react_redux_1 = require("react-redux");
  var hoist_non_react_statics_1 = __importDefault(require("hoist-non-react-statics"));
  var shallowequal_1 = __importDefault(require("shallowequal"));
  var createApiDataBinding_1 = require("./helpers/createApiDataBinding");
  var getActions_1 = require("./helpers/getActions");
  var getApiDataRequest_1 = require("./selectors/getApiDataRequest");
  var performApiDataRequest_1 = require("./actions/performApiDataRequest");
  exports.shouldPerformApiRequest = function (newProps, oldProps, bindings, bindingKey) {
      var keyParamsHaveChanged = function (key) { return !shallowequal_1.default(newProps.params[key], oldProps.params[key]); };
      var getRequest = function (props, key) {
          return getApiDataRequest_1.getApiDataRequest(props.apiData, bindings[key], props.params[key]);
      };
      var hasBeenInvalidated = function (oldRequest, newRequest) {
          return !!oldRequest && oldRequest.networkStatus !== 'ready' && !!newRequest && newRequest.networkStatus === 'ready';
      };
      var apiDataChanged = newProps.apiData !== oldProps.apiData;
      return ((keyParamsHaveChanged(bindingKey) && exports.shouldAutoTrigger(newProps.apiData, bindings[bindingKey]) === true) ||
          (apiDataChanged &&
              hasBeenInvalidated(getRequest(oldProps, bindingKey), getRequest(newProps, bindingKey)) &&
              exports.shouldAutoTrigger(newProps.apiData, bindings[bindingKey]) === true) ||
          (apiDataChanged &&
              exports.shouldAutoTrigger(oldProps.apiData, bindings[bindingKey]) === false &&
              exports.shouldAutoTrigger(newProps.apiData, bindings[bindingKey]) === true));
  };
  exports.shouldAutoTrigger = function (apiData, endpointKey) {
      var _a, _b;
      var endpointConfig = apiData.endpointConfig[endpointKey];
      return (_b = (_a = endpointConfig.autoTrigger, (_a !== null && _a !== void 0 ? _a : apiData.globalConfig.autoTrigger)), (_b !== null && _b !== void 0 ? _b : (endpointConfig && endpointConfig.method === 'GET')));
  };
  /**
   * Binds api data to component props and automatically triggers loading of data if it hasn't been loaded yet. The wrapped
   * component will get an ApiDataBinding added to each property key of the bindings param.
   * @param bindings - maps prop names to endpoint keys
   * @param [getParams] - optionally provide the params of the endpoint
   * @returns {Function} - Function to wrap your component
   * @example
   * withApiData({
   *    wishList: 'getWishLists',
   *    settings: 'getSettings'
   *  }, (ownProps, state) => ({
   *    wishList: {
   *      projectSlug: ownProps.match.params.projectSlug,
   *      env: ownProps.match.params.env
   *    },
   *    settings: {
   *      projectSlug: ownProps.match.params.projectSlug,
   *      env: ownProps.match.params.env
   *    }
   *  }))
   */
  function withApiData(bindings, getParams) {
      // note: return type ComponentType<TChildProps> and ComponentClass<TChildProps> have been replaced with <any> because
      // these generics don't support the new feature of params array with array of ApiDataBinding as a result
      return function (WrappedComponent) {
          var WithApiData = /** @class */ (function (_super) {
              __extends(WithApiData, _super);
              function WithApiData() {
                  var _this = _super !== null && _super.apply(this, arguments) || this;
                  // keep track of binding instances (each propName can have multiple bindings through getInstance)
                  _this.bindingPropNameBindingsStore = {};
                  return _this;
              }
              WithApiData.prototype.componentDidMount = function () {
                  this.fetchDataIfNeeded();
              };
              WithApiData.prototype.componentDidUpdate = function (prevProps, prevState) {
                  var _this = this;
                  // automatically fetch when parameters change or re-fetch when a request gets invalidated
                  Object.keys(bindings).forEach(function (bindingKey) {
                      if (Array.isArray(prevProps.params[bindingKey])) {
                          var paramsArray = prevProps.params[bindingKey];
                          paramsArray.forEach(function (params, index) {
                              var _a, _b;
                              if (exports.shouldPerformApiRequest(__assign(__assign({}, _this.props), { params: (_a = {}, _a[bindingKey] = _this.props.params[bindingKey][index], _a) }), __assign(__assign({}, prevProps), { params: (_b = {}, _b[bindingKey] = params, _b) }), bindings, bindingKey)) {
                                  _this.props.dispatch(performApiDataRequest_1.performApiRequest(bindings[bindingKey], params, undefined, index.toString()));
                              }
                          });
                      }
                      else {
                          if (exports.shouldPerformApiRequest(_this.props, prevProps, bindings, bindingKey)) {
                              _this.props.dispatch(performApiDataRequest_1.performApiRequest(bindings[bindingKey], _this.props.params[bindingKey]));
                          }
                      }
                  });
              };
              WithApiData.prototype.getApiDataBinding = function (endpointKey, params, dispatch, propName, instanceId, apiData) {
                  if (instanceId === void 0) { instanceId = ''; }
                  // check if we already have an instance of this bindingStore
                  var propNameBindingsStore = this.bindingPropNameBindingsStore[propName];
                  if (propNameBindingsStore === undefined) {
                      propNameBindingsStore = new createApiDataBinding_1.BindingsStore();
                      this.bindingPropNameBindingsStore[propName] = propNameBindingsStore;
                  }
                  return propNameBindingsStore.getBinding(endpointKey, params, dispatch, instanceId, apiData);
              };
              WithApiData.prototype.fetchDataIfNeeded = function () {
                  var _this = this;
                  var _a = this.props, params = _a.params, dispatch = _a.dispatch;
                  Object.keys(bindings).forEach(function (propName) {
                      var endpointKey = bindings[propName];
                      if (exports.shouldAutoTrigger(_this.props.apiData, endpointKey)) {
                          // performApiRequest will check if fetch is needed
                          if (Array.isArray(params[propName])) {
                              var paramsArray = params[propName];
                              paramsArray.forEach(function (propNameParams, index) {
                                  dispatch(performApiDataRequest_1.performApiRequest(endpointKey, propNameParams, undefined, index.toString(), _this.bindingPropNameBindingsStore[propName]));
                              });
                          }
                          else {
                              dispatch(performApiDataRequest_1.performApiRequest(endpointKey, params[propName], undefined, '', _this.bindingPropNameBindingsStore[propName]));
                          }
                      }
                  });
              };
              WithApiData.prototype.render = function () {
                  var _this = this;
                  var _a = this.props, apiData = _a.apiData, params = _a.params, dispatch = _a.dispatch, componentProps = __rest(_a, ["apiData", "params", "dispatch"]);
                  var addProps = {};
                  Object.keys(bindings).forEach(function (propName) {
                      var endpointKey = bindings[propName];
                      if (Array.isArray(params[propName])) {
                          var paramsArray = params[propName];
                          addProps[propName] = paramsArray.map(function (propNameParams, index) {
                              return _this.getApiDataBinding(endpointKey, propNameParams, dispatch, propName, index.toString(), apiData);
                          });
                      }
                      else {
                          addProps[propName] = _this.getApiDataBinding(endpointKey, params[propName], dispatch, propName, '', apiData);
                      }
                  });
                  var apiDataActions = getActions_1.getActions(dispatch);
                  return react_1.default.createElement(WrappedComponent, __assign({}, componentProps, addProps, { apiDataActions: apiDataActions }));
              };
              WithApiData.displayName = "WithApiData(" + (WrappedComponent.displayName || WrappedComponent.name || 'Component') + ")";
              return WithApiData;
          }(react_1.default.Component));
          hoist_non_react_statics_1.default(WithApiData, WrappedComponent); // move static methods to wrapper
          return react_redux_1.connect(function (state, ownProps) { return ({
              params: typeof getParams === 'function' ? getParams(ownProps, state) : {},
              apiData: state.apiData,
          }); })(WithApiData);
      };
  }
  exports.default = withApiData;
  //# sourceMappingURL=withApiData.js.map