"use strict";

exports.__esModule = true;
require("core-js/modules/es.error.cause.js");
require("core-js/modules/es.array.push.js");
require("core-js/modules/esnext.iterator.constructor.js");
require("core-js/modules/esnext.iterator.find.js");
require("core-js/modules/esnext.iterator.reduce.js");
var _base = require("./_base");
var _object = require("../../../helpers/object");
var _array = require("../../../helpers/array");
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/**
 * Action that tracks data changes.
 *
 * @class DataChangeAction
 * @private
 */
class DataChangeAction extends _base.BaseAction {
  constructor(_ref) {
    let {
      changes,
      selected
    } = _ref;
    super();
    /**
     * @param {Array} changes 2D array containing information about each of the edited cells.
     */
    _defineProperty(this, "changes", void 0);
    /**
     * @param {number[]} selected The cell selection.
     */
    _defineProperty(this, "selected", void 0);
    this.changes = changes;
    this.selected = selected;
  }
  static startRegisteringEvents(hot, undoRedoPlugin) {
    hot.addHook('afterChange', function (changes, source) {
      const changesLen = changes && changes.length;
      if (!changesLen) {
        return;
      }
      const hasDifferences = changes.find(change => {
        const [,, oldValue, newValue] = change;
        return oldValue !== newValue;
      });
      if (!hasDifferences) {
        return;
      }
      const wrappedAction = () => {
        const clonedChanges = changes.reduce((arr, change) => {
          arr.push([...change]);
          return arr;
        }, []);
        (0, _array.arrayEach)(clonedChanges, change => {
          change[1] = hot.propToCol(change[1]);
        });
        const selected = changesLen > 1 ? this.getSelected() : [[clonedChanges[0][0], clonedChanges[0][1]]];
        return new DataChangeAction({
          changes: clonedChanges,
          selected
        });
      };
      undoRedoPlugin.done(wrappedAction, source);
    });
  }

  /**
   * @param {Core} hot The Handsontable instance.
   * @param {function(): void} undoneCallback The callback to be called after the action is undone.
   */
  undo(hot, undoneCallback) {
    const data = (0, _object.deepClone)(this.changes);
    const emptyRowsAtTheEnd = hot.countEmptyRows(true);
    const emptyColsAtTheEnd = hot.countEmptyCols(true);
    for (let i = 0, len = data.length; i < len; i++) {
      data[i].splice(3, 1);
    }
    hot.addHookOnce('afterChange', undoneCallback);
    hot.setDataAtCell(data, null, null, 'UndoRedo.undo');
    for (let i = 0, len = data.length; i < len; i++) {
      const [row, column] = data[i];
      if (hot.getSettings().minSpareRows && row + 1 + hot.getSettings().minSpareRows === hot.countRows() && emptyRowsAtTheEnd === hot.getSettings().minSpareRows) {
        hot.alter('remove_row', parseInt(row + 1, 10), hot.getSettings().minSpareRows);
        hot.getPlugin('undoRedo').doneActions.pop();
      }
      if (hot.getSettings().minSpareCols && column + 1 + hot.getSettings().minSpareCols === hot.countCols() && emptyColsAtTheEnd === hot.getSettings().minSpareCols) {
        hot.alter('remove_col', parseInt(column + 1, 10), hot.getSettings().minSpareCols);
        hot.getPlugin('undoRedo').doneActions.pop();
      }
    }
    hot.scrollToFocusedCell();
    hot.selectCells(this.selected, false, false);
  }

  /**
   * @param {Core} hot The Handsontable instance.
   * @param {function(): void} redoneCallback The callback to be called after the action is redone.
   */
  redo(hot, redoneCallback) {
    const data = (0, _object.deepClone)(this.changes);
    for (let i = 0, len = data.length; i < len; i++) {
      data[i].splice(2, 1);
    }
    hot.addHookOnce('afterChange', redoneCallback);
    hot.setDataAtCell(data, null, null, 'UndoRedo.redo');
    if (this.selected) {
      hot.selectCells(this.selected, false, false);
    }
  }
}
exports.DataChangeAction = DataChangeAction;