'use strict';

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

var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');

var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);

var _entries = require('babel-runtime/core-js/object/entries');

var _entries2 = _interopRequireDefault(_entries);

var _map = require('babel-runtime/core-js/map');

var _map2 = _interopRequireDefault(_map);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _mutations = require('./mutations');

var _mutations2 = _interopRequireDefault(_mutations);

var _getters = require('./getters');

var _getters2 = _interopRequireDefault(_getters);

var _actions = require('./actions');

var _actions2 = _interopRequireDefault(_actions);

var _actionTypes = require('./action-types');

var actionTypes = _interopRequireWildcard(_actionTypes);

var _getterTypes = require('./getter-types');

var getterTypes = _interopRequireWildcard(_getterTypes);

var _mutationTypes = require('./mutation-types');

var mutationTypes = _interopRequireWildcard(_mutationTypes);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

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

var VuexSearch = function () {
  function VuexSearch(_ref) {
    var store = _ref.store,
        resources = _ref.resources,
        searchApi = _ref.searchApi;
    (0, _classCallCheck3.default)(this, VuexSearch);

    this._base = VuexSearch.base;
    this._store = store;
    this._defaultSearchApi = searchApi;
    this._searchMap = {};
    this._unwatchResource = {};
    this._customSearch = new _map2.default();
    /* eslint-disable-next-line no-param-reassign */
    store.search = this;

    this.initModule();
    this.initResources(resources);
  }

  (0, _createClass3.default)(VuexSearch, [{
    key: 'initModule',
    value: function initModule() {
      var actions = (0, _actions2.default)(this._searchMap);

      this._store.registerModule(this._base, {
        namespaced: true,
        root: true,
        mutations: _mutations2.default,
        actions: actions,
        getters: _getters2.default,
        state: {}
      });
    }
  }, {
    key: 'initResources',
    value: function initResources(resources) {
      var _this = this;

      (0, _entries2.default)(resources).forEach(function (_ref2) {
        var _ref3 = (0, _slicedToArray3.default)(_ref2, 2),
            resourceName = _ref3[0],
            config = _ref3[1];

        _this.registerResource(resourceName, config);
      });
    }
  }, {
    key: 'registerResource',
    value: function registerResource(resourceName, config) {
      var _this2 = this;

      var store = this._store;
      var namespace = this.getNamespace(this._base);

      store.commit('' + namespace + mutationTypes.SET_INIT_RESOURCE, { resourceName: resourceName });

      var getter = config.getter,
          index = config.index,
          _config$searchApi = config.searchApi,
          searchApi = _config$searchApi === undefined ? this._defaultSearchApi : _config$searchApi;


      this._searchMap[resourceName] = searchApi;

      this.searchSubscribeIfNecessary(searchApi, resourceName, function (_ref4) {
        var result = _ref4.result,
            text = _ref4.text;

        _this2._store.dispatch('' + namespace + actionTypes.RECEIVE_RESULT, {
          result: result, resourceName: resourceName, text: text
        });
      });

      store.dispatch('' + namespace + actionTypes.searchApi.INDEX_RESOURCE, {
        fieldNamesOrIndexFunction: index,
        resourceName: resourceName,
        resources: getter(store.state)
      });

      var initialSearchString = store.getters['' + namespace + getterTypes.resourceIndexByName](resourceName).text;
      store.dispatch('' + namespace + actionTypes.SEARCH, {
        resourceName: resourceName, searchString: initialSearchString
      });

      this._unwatchResource[resourceName] = store.watch(getter, function (data) {
        var searchString = store.getters['' + namespace + getterTypes.resourceIndexByName](resourceName).text;

        store.dispatch('' + namespace + actionTypes.searchApi.INDEX_RESOURCE, {
          fieldNamesOrIndexFunction: index,
          resourceName: resourceName,
          resources: data
        });
        store.dispatch('' + namespace + actionTypes.SEARCH, {
          resourceName: resourceName, searchString: searchString
        });
      }, { deep: true });
    }
  }, {
    key: 'unregisterResource',
    value: function unregisterResource(resourceName) {
      var store = this._store;
      var namespace = this.getNamespace(this._base);

      var searchApi = this._searchMap[resourceName];
      this.searchUnsubscribeIfNecessary(searchApi, resourceName);
      searchApi.stopSearch(resourceName);
      delete this._searchMap[resourceName];

      var unwatch = this._unwatchResource[resourceName];
      unwatch();
      delete this._unwatchResource[resourceName];

      store.commit('' + namespace + mutationTypes.DELETE_RESOURCE, { resourceName: resourceName });
    }
  }, {
    key: 'searchSubscribeIfNecessary',
    value: function searchSubscribeIfNecessary(searchApi, resourceName, fn) {
      var map = this._customSearch.get(searchApi);
      if (!map) {
        this._customSearch.set(searchApi, {
          unsubscribe: searchApi.subscribe(fn),
          resources: [resourceName]
        });
      } else {
        map.resources.push(resourceName);
      }
    }
  }, {
    key: 'searchUnsubscribeIfNecessary',
    value: function searchUnsubscribeIfNecessary(searchApi, resourceName) {
      var map = this._customSearch.get(searchApi);
      if (map.resources.length === 1) {
        map.unsubscribe();
        this._customSearch.delete(searchApi);
      } else {
        map.resources = map.resources.filter(function (name) {
          return name !== resourceName;
        });
      }
    }
  }, {
    key: 'getNamespace',
    value: function getNamespace() {
      for (var _len = arguments.length, modulePath = Array(_len), _key = 0; _key < _len; _key++) {
        modulePath[_key] = arguments[_key];
      }

      return this._store._modules.getNamespace(modulePath);
    }
  }]);
  return VuexSearch;
}();

var base = 'vuexSearch';

Object.defineProperty(VuexSearch, 'base', {
  get: function get() {
    return base;
  },
  set: function set(newBase) {
    base = newBase;
  }
});

exports.default = VuexSearch;