text: const debounce = require('lodash.debounce');
  
  export default class ListLayoutController {
      constructor($scope, $stateParams, $state, $location, $timeout, view, dataStore) {
          this.$scope = $scope;
          this.$state = $state;
          this.$stateParams = $stateParams;
          this.$timeout = $timeout;
          this.view = view;
          this.dataStore = dataStore;
          this.entity = view.getEntity();
          this.actions = view.actions();
          this.batchActions = view.batchActions();
          this.loadingPage = false;
          this.filters = view.filters();
          this.search = ListLayoutController.getCurrentSearchParam($location, this.filters);
          this.path = $location.path();
          // since search isn't a $stateParam of the listLayout state,
          // the controller doesn't change when the search changes
          // so we must update filter values manually when the location changes
          $scope.$watch(
              () => $location.search() && $location.search().search,
              (newval, oldval) => {
                  if (newval === oldval) {
                      return;
                  }
                  if ($location.path() !== this.path) {
                      return; // already transitioned to another page
                  }
                  this.search = ListLayoutController.getCurrentSearchParam($location, this.filters);
                  this.enabledFilters = this.getEnabledFilters();
              }
          );
          // apply filters when filter values change
          $scope.$watch(
              () => this.search,
              debounce((newValues, oldValues) => {
                  if (newValues != oldValues) {
                      this.updateFilters();
                  }
              }, 500),
              true
          );
          this.filters = view.filters();
          this.enabledFilters = this.getEnabledFilters();
          this.hasFilters = Object.keys(this.filters).length > 0;
          this.focusedFilterId = null;
          this.enableFilter = this.enableFilter.bind(this);
          this.removeFilter = this.removeFilter.bind(this);
          if (this.batchActions.length) {
              // required in scope to communicate with listView
              $scope.selectionUpdater = selection => $scope.selection = selection;
              $scope.selection = [];
          }
  
          if(this.hasFilters){
              this.updateFilters();
          }
  
          $scope.$on('$destroy', this.destroy.bind(this));
      }
  
      static getCurrentSearchParam(location, filters) {
          const baseSearch = location.search().search ? JSON.parse(location.search().search) : {};
  
          return filters
          .reduce((search, filter) => {
              if (typeof search[filter.name()] !== 'undefined') {
                  return {
                      ...search,
                      [filter.name()]: filter.getMappedValue(search[filter.name()])
                  }
              }
              return search;
          }, baseSearch);
      }
  
      enableFilter(filter) {
          let defaultValue = filter.defaultValue();
          if (defaultValue !== null) {
              this.search[filter.name()] = defaultValue;
          }
          this.enabledFilters.push(filter);
          this.focusedFilterId = filter.name();
          this.$timeout(() => {
              let el = window.document.getElementById(this.focusedFilterId);
              if (el && el.focus) {
                  el.focus();
              }
          }, 200, false);
      }
  
      getEnabledFilters() {
          return this.filters.filter(filter => {
              if (filter.pinned()) {
                  return true;
              }
              return this.search && (filter.name() in this.search);
          });
      }
  
      updateFilters() {
          var values = {},
              filters = this.enabledFilters,
              fieldName,
              field,
              i;
          for (i in filters) {
              field = filters[i];
              fieldName = field.name();
              if (this.search[fieldName] === '') {
                  delete this.search[fieldName];
                  continue;
              }
  
              if ((field.type() === 'boolean' && fieldName in this.search) || // for boolean false is the same as null
                  (field.type() !== 'boolean' && this.search[fieldName] !== null)) {
                  values[fieldName] = field.getTransformedValue(this.search[fieldName]);
              }
          }
          this.$stateParams.search = values;
          this.$stateParams.page = 1;
          this.$state.go('list', this.$stateParams);
      }
  
      removeFilter(filter) {
          delete this.search[filter.name()];
          this.enabledFilters = this.enabledFilters.filter(f => f !== filter);
      }
  
      destroy() {
          this.$scope = undefined;
          this.$state = undefined;
          this.$stateParams = undefined;
          this.$timeout = undefined;
          this.dataStore = undefined;
      }
  }
  
  ListLayoutController.$inject = ['$scope', '$stateParams', '$state', '$location', '$timeout', 'view', 'dataStore'];
  