import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
import _inheritsLoose from "@babel/runtime/helpers/inheritsLoose";
import Store from './Store';
import _ from 'lodash';
export var ColumnsStore =
/*#__PURE__*/
function (_Store) {
  _inheritsLoose(ColumnsStore, _Store);

  function ColumnsStore(_ref) {
    var _this;

    var items = _ref.items,
        _ref$storeName = _ref.storeName,
        storeName = _ref$storeName === void 0 ? 'ColumnsStore' : _ref$storeName,
        params = _objectWithoutPropertiesLoose(_ref, ["items", "storeName"]);

    _this = _Store.call(this, {
      stateName: params.stateName,
      fields: {
        id: {
          type: String,
          primaryKey: true
        },
        // custom test automation id, default is id property
        testAutomationId: {
          type: String,
          getter: function getter(item) {
            return item.testAutomationId || item.id;
          }
        },
        // zero based index of column. Columns ordered on grid according to this position
        position: Number,
        // label of column for rendering on grid header
        headerLabel: String,
        // description for grid columns editor
        description: String,
        // required columns can't be hidden on grid columns editor
        isRequired: Boolean,
        // user customization of column visibility
        isVisible: Boolean,
        // business logic checker to be called on particular column
        isAvailable: {
          type: 'custom',
          fieldFilterHandler: function fieldFilterHandler(fieldValue, filter) {
            return filter(fieldValue());
          }
        },
        // customizable columns can be edited by user
        isCustomizable: Boolean,
        // additional filter to be able to getting columns for short view only
        // (when grid represented with short/full view)
        isForShortView: Boolean
      }
    }) || this;
    _this.defaults = items;

    _this.register(storeName);

    return _this;
  }

  var _proto = ColumnsStore.prototype;

  _proto.setVisibleColumns = function setVisibleColumns(listIds) {
    var items = this.getRawData().map(function (item) {
      return Object.assign({}, item, {
        isVisible: item.isCustomizable ? _.includes(listIds, item.id) : true
      });
    });
    this.setItems(items, false);
  };

  _proto.getColumnOffset = function getColumnOffset(id) {
    var columns = this.getRawData();

    var currentPosition = _.find(columns, {
      id: id
    }).position;

    var columnsBefore = _.filter(columns, function (column) {
      var isCustomizable = column.isCustomizable,
          position = column.position;
      return position < currentPosition && !isCustomizable;
    });

    return columnsBefore.length;
  }
  /**
   * Setup new visual position for item
   * @param {Object} record
   * @param {Number} newPosition zero based index
   */
  ;

  _proto.setVisualPosition = function setVisualPosition(record, newPosition) {
    if (record.position === newPosition) {
      return;
    } // get items ordered by position


    var items = this.getSortedByPosition(this.getRawData()); // remove item

    _.remove(items, function (item) {
      return item.position === record.position;
    });

    var head = _.take(items, newPosition);

    var tail = _.takeRight(items, items.length - newPosition);

    var reorderedItems = [].concat(head, [record], tail); // reset position

    reorderedItems = this.setupItemsPosition(reorderedItems);
    this.setItems(reorderedItems, true);
  };

  _proto.setupItemsPosition = function setupItemsPosition(items) {
    for (var i = 0; i < items.length; i++) {
      items[i].position = i;
    }

    return items;
  };

  _proto.getSortedByPosition = function getSortedByPosition(items) {
    return items.sort(function (a, b) {
      return a.position - b.position;
    });
  };

  _proto.isColumnCustomizable = function isColumnCustomizable(id) {
    var columnSpec = _.find(this.getRawData(), {
      id: id
    });

    return columnSpec && columnSpec.isCustomizable;
  };

  _proto.getFromDefaults = function getFromDefaults() {
    var defaults = {
      isVisible: true,
      isAvailable: _.stubTrue,
      isCustomizable: true,
      isForShortView: false,
      isRequired: false
    };

    var normalizeColumnSpec = function normalizeColumnSpec(columnSpec, index) {
      return Object.assign({}, defaults, columnSpec, {
        position: index
      });
    };

    return this.defaults.map(normalizeColumnSpec);
  };

  _proto.mergeItemsWithDefaults = function mergeItemsWithDefaults(items, defaults) {
    var collisions = [];
    var mergedItems = defaults.map(function (defaultSpec) {
      var persistentItem = _.find(items, {
        id: defaultSpec.id
      });

      if (persistentItem) {
        // Prefer some values from defaults
        var isAvailable = persistentItem.isAvailable,
            attrs = _objectWithoutPropertiesLoose(persistentItem, ["isAvailable"]);

        if (!isAvailable && defaultSpec.isAvailable()) {
          collisions.push(persistentItem.id);
        }

        var mergedItem = Object.assign({}, defaultSpec, attrs);
        return mergedItem;
      } else {
        return defaultSpec;
      }
    });

    if (collisions.length > 0) {
      mergedItems = this.resolveCollisions(this.getSortedByPosition(mergedItems), collisions);
    }

    return mergedItems;
  }
  /**
   * Re arrange items using this logic: the id's specified on columnIds should be placed at the end
   * of list of columns. But before the last non editable column.
   *
   * Collision is a case when column currently available by business logic but previously were saved as unavailable.
   * so, to prevents appearing it in a random place we rearrange it.
   * @param {Array} items a list of columns spec
   * @param {Array} columnIds a list of ids of columns which position detected as incorrect
   * @return {Array}
   */
  ;

  _proto.resolveCollisions = function resolveCollisions(items, columnIds) {
    var _items;

    // remove collision items
    var itemsWithCollision = _.remove(items, function (item) {
      return _.includes(columnIds, item.id);
    }); // find new insertion position


    var insertAt = _.findLastIndex(items, function (item) {
      return item.isCustomizable;
    });

    insertAt = Math.max(insertAt, 0);

    (_items = items).splice.apply(_items, [insertAt + 1, 0].concat(itemsWithCollision));

    items = this.setupItemsPosition(items);
    return items;
  };

  _proto.loadAll = function loadAll() {
    var defaults = this.getFromDefaults();
    var savedItems = loadState(this.stateName) || [];
    var items = this.mergeItemsWithDefaults(savedItems, defaults);
    return Promise.resolve(items);
  };

  _proto.save = function save() {
    var items = this.getRawData().map(function (item) {
      var id = item.id,
          position = item.position,
          isVisible = item.isVisible,
          isAvailable = item.isAvailable;
      return {
        id: id,
        position: position,
        isVisible: isVisible,
        isAvailable: isAvailable()
      };
    });
    saveState(this.stateName, items);
  };

  _proto.getGridColumns = function getGridColumns(filterByShortView) {
    if (filterByShortView === void 0) {
      filterByShortView = false;
    }

    return this.getSorted(this.getRawData()).filter(function (_ref2) {
      var isVisible = _ref2.isVisible,
          isAvailable = _ref2.isAvailable,
          isForShortView = _ref2.isForShortView;
      var result = isVisible && isAvailable();

      if (filterByShortView) {
        result = result && isForShortView;
      }

      return result;
    });
  };

  return ColumnsStore;
}(Store);

var loadState = function loadState(key) {
  var str = localStorage.getItem(key);
  var result = undefined;

  if (!_.isNil(str)) {
    try {
      result = JSON.parse(str);
    } catch (e) {
      result = undefined;
    }
  }

  return result;
};

var saveState = function saveState(storageKey, items) {
  localStorage.setItem(storageKey, JSON.stringify(items));
};