text: var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
  
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  import algoliasearchHelper from 'algoliasearch-helper';
  import isEqual from 'lodash/isEqual';
  
  var RoutingManager = function () {
    function RoutingManager() {
      var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
          instantSearchInstance = _ref.instantSearchInstance,
          router = _ref.router,
          stateMapping = _ref.stateMapping;
  
      _classCallCheck(this, RoutingManager);
  
      this.originalConfig = null;
      this.firstRender = true;
  
      this.router = router;
      this.stateMapping = stateMapping;
      this.instantSearchInstance = instantSearchInstance;
  
      this.originalUIState = this.stateMapping.routeToState(this.router.read());
    }
  
    _createClass(RoutingManager, [{
      key: 'init',
      value: function init(_ref2) {
        var state = _ref2.state;
  
        // store the initial state from the storage
        // so that we can compare it with the state after the first render
        // in case the searchFunction has modifyied it.
        this.initState = this.getAllUIStates({
          searchParameters: state
        });
      }
    }, {
      key: 'getConfiguration',
      value: function getConfiguration(currentConfiguration) {
        // we need to create a REAL helper to then get its state. Because some parameters
        // like hierarchicalFacet.rootPath are then triggering a default refinement that would
        // be not present if it was not going trough the SearchParameters constructor
        this.originalConfig = algoliasearchHelper({}, currentConfiguration.index, currentConfiguration).state;
        // The content of getAllSearchParameters is destructured to return a plain object
        return _extends({}, this.getAllSearchParameters({
          currentSearchParameters: this.originalConfig,
          uiState: this.originalUIState
        }));
      }
    }, {
      key: 'render',
      value: function render(_ref3) {
        var state = _ref3.state;
  
        if (this.firstRender) {
          this.firstRender = false;
          this.setupRouting(state);
        }
      }
    }, {
      key: 'setupRouting',
      value: function setupRouting(state) {
        var _this = this;
  
        var helper = this.instantSearchInstance.helper;
  
        this.router.onUpdate(function (route) {
          var uiState = _this.stateMapping.routeToState(route);
          var currentUIState = _this.getAllUIStates({
            searchParameters: helper.state
          });
  
          if (isEqual(uiState, currentUIState)) return;
  
          var searchParameters = _this.getAllSearchParameters({
            currentSearchParameters: state,
            instantSearchInstance: _this.instantSearchInstance,
            uiState: uiState
          });
  
          var fullHelperState = _extends({}, _this.originalConfig, searchParameters);
  
          if (isEqual(fullHelperState, searchParameters)) return;
  
          helper.overrideStateWithoutTriggeringChangeEvent(searchParameters).search();
        });
  
        this.renderURLFromState = function (searchParameters) {
          var uiState = _this.getAllUIStates({
            searchParameters: searchParameters
          });
          var route = _this.stateMapping.stateToRoute(uiState);
          _this.router.write(route);
        };
        helper.on('change', this.renderURLFromState);
  
        // Compare initial state and post first render state, in order
        // to see if the query has been changed by a searchFunction
  
        var firstRenderState = this.getAllUIStates({
          searchParameters: state
        });
  
        if (!isEqual(this.initState, firstRenderState)) {
          // force update the URL, if the state has changed since the initial URL read
          // We do this in order to make a URL update when there is search function
          // that prevent the search of the initial rendering
          // See: https://github.com/algolia/instantsearch.js/issues/2523#issuecomment-339356157
          var route = this.stateMapping.stateToRoute(firstRenderState);
          this.router.write(route);
        }
      }
    }, {
      key: 'dispose',
      value: function dispose() {
        if (this.renderURLFromState) {
          this.instantSearchInstance.helper.removeListener('change', this.renderURLFromState);
        }
        this.router.dispose();
      }
    }, {
      key: 'getAllSearchParameters',
      value: function getAllSearchParameters(_ref4) {
        var currentSearchParameters = _ref4.currentSearchParameters,
            uiState = _ref4.uiState;
        var widgets = this.instantSearchInstance.widgets;
  
        var searchParameters = widgets.reduce(function (sp, w) {
          if (!w.getWidgetSearchParameters) return sp;
          return w.getWidgetSearchParameters(sp, {
            uiState: uiState
          });
        }, currentSearchParameters);
        return searchParameters;
      }
    }, {
      key: 'getAllUIStates',
      value: function getAllUIStates(_ref5) {
        var searchParameters = _ref5.searchParameters;
        var _instantSearchInstanc = this.instantSearchInstance,
            widgets = _instantSearchInstanc.widgets,
            helper = _instantSearchInstanc.helper;
  
        var uiState = widgets.filter(function (w) {
          return Boolean(w.getWidgetState);
        }).reduce(function (u, w) {
          return w.getWidgetState(u, {
            helper: helper,
            searchParameters: searchParameters
          });
        }, {});
  
        return uiState;
      }
  
      // External API's
  
    }, {
      key: 'createURL',
      value: function createURL(state) {
        var uiState = this.getAllUIStates({
          searchParameters: state
        });
        var route = this.stateMapping.stateToRoute(uiState);
        return this.router.createURL(route);
      }
    }, {
      key: 'onHistoryChange',
      value: function onHistoryChange(fn) {
        var _this2 = this;
  
        var helper = this.instantSearchInstance.helper;
  
        this.router.onUpdate(function (route) {
          var uiState = _this2.stateMapping.routeToState(route);
          var currentUIState = _this2.getAllUIStates({
            searchParameters: helper.state
          });
  
          if (isEqual(uiState, currentUIState)) return;
  
          var searchParameters = _this2.getAllSearchParameters({
            currentSearchParameters: helper.state,
            instantSearchInstance: _this2.instantSearchInstance,
            uiState: uiState
          });
  
          var fullSearchParameters = _extends({}, _this2.originalConfig, searchParameters);
  
          fn(fullSearchParameters);
        });
        return;
      }
    }]);
  
    return RoutingManager;
  }();
  
  export default RoutingManager;