'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _immutable = require('immutable');

var _every = require('lodash/every');

var _every2 = _interopRequireDefault(_every);

var _isObject = require('lodash/isObject');

var _isObject2 = _interopRequireDefault(_isObject);

var _MultiWeakMap = require('./MultiWeakMap');

var _MultiWeakMap2 = _interopRequireDefault(_MultiWeakMap);

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

// This is a method decorator that helps the stateHelper perform caching via
// WeakMaps. It accepts a function which returns a list of paths to pieces of
// the global Redux store, e.g., ['quizEntries']. It then looks up the value
// being stored in this path and checks to see if the decorated method has been
// called before with the same value, and if so, returns the cached result.
/* eslint "no-param-reassign": "warn" */
exports.default = function (fnToGetPaths) {
  return function (target, name, descriptor) {
    var decoratedMethod = descriptor.value;
    var cache = void 0;

    descriptor.value = function () {
      var paths = fnToGetPaths(this);
      cache = cache || new _MultiWeakMap2.default(paths.length + 1);

      var state = this.state();
      var fields = paths.map(function (path) {
        return state.getIn(path, (0, _immutable.Map)());
      });
      var keys = [this].concat(fields);
      if (cache.has(keys)) {
        return cache.get(keys);
      }

      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      var result = decoratedMethod.apply(this, args);
      if (allAreObjects(fields)) {
        cache.set(keys, result);
      }

      return result;
    };

    return descriptor;
  };
};

var allAreObjects = function allAreObjects(values) {
  return (0, _every2.default)(values, _isObject2.default);
};