"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.ClipboardState = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _mobx = require("mobx");
var _utils = require("./utils");
class ClipboardState {
  constructor(parent) {
    (0, _defineProperty2.default)(this, "copiedCells", new Set());
    (0, _defineProperty2.default)(this, "isCut", false);
    (0, _defineProperty2.default)(this, "_copiedDataString", '');
    (0, _defineProperty2.default)(this, "_copiedValues", new Map());
    (0, _defineProperty2.default)(this, "_parent", void 0);
    this._parent = parent;
    (0, _mobx.makeObservable)(this, {
      copiedCells: _mobx.observable,
      isCut: _mobx.observable,
      hasCopiedCells: _mobx.computed,
      copy: _mobx.action,
      cut: _mobx.action,
      paste: _mobx.action,
      clear: _mobx.action
    });
  }

  /**
   * Copy selected cells. Returns serialized TSV string for clipboard.
   */
  copy() {
    this.clear();
    return this._storeCells();
  }

  /**
   * Cut selected cells. Returns serialized TSV string for clipboard.
   */
  cut() {
    this.clear();
    this.isCut = true;
    return this._storeCells();
  }

  /**
   * Paste data starting at target position.
   * If the clipboard text matches what we stored at copy time, uses the rich
   * typed values instead of deserializing from TSV (avoids lossy round-trip).
   */
  paste(rawData) {
    const {
      cellValue,
      cellInteraction
    } = this._parent;
    const target = cellInteraction.focusedCell;
    if (!target) {
      return;
    }
    const targetPos = this._parent._toIndices(target);
    if (!targetPos) {
      return;
    }
    const isInternal = this._copiedDataString !== '' && this._copiedDataString === rawData;
    const pastedKeys = this._pasteGrid(rawData, targetPos, isInternal, cellValue);
    if (this.isCut && isInternal) {
      this._clearCutSources(pastedKeys, cellValue);
    }
    this.clear();
  }
  _pasteGrid(rawData, targetPos, useRichValues, cellValue) {
    const pastedKeys = new Set();
    const richChanges = [];
    const rawChanges = [];
    const rows = rawData.split(/\r?\n/).filter(r => r.length > 0);
    for (let r = 0; r < rows.length; r++) {
      const cols = rows[r].split('\t');
      for (let c = 0; c < cols.length; c++) {
        const dest = this._parent._toPosition(targetPos.row + r, targetPos.col + c);
        if (!dest) {
          continue;
        }
        const richValue = useRichValues ? this._copiedValues.get(`${r}:${c}`) : undefined;
        if (richValue !== undefined) {
          richChanges.push({
            rowKey: dest.rowKey,
            columnId: dest.columnId,
            value: richValue
          });
        } else {
          rawChanges.push({
            rowKey: dest.rowKey,
            columnId: dest.columnId,
            rawValue: cols[c]
          });
        }
        pastedKeys.add((0, _utils.cellKey)(dest.rowKey, dest.columnId));
      }
    }
    if (richChanges.length > 0) {
      cellValue.applyBulkValues(richChanges);
    }
    if (rawChanges.length > 0) {
      cellValue.applyBulkRawValues(rawChanges);
    }
    return pastedKeys;
  }
  _clearCutSources(pastedKeys, cellValue) {
    const rawChanges = [];
    for (const key of this.copiedCells) {
      if (pastedKeys.has(key)) {
        continue;
      }
      const pos = (0, _utils.parseCellKey)(key);
      if (pos) {
        rawChanges.push({
          rowKey: pos.rowKey,
          columnId: pos.columnId,
          rawValue: ''
        });
      }
    }
    cellValue.applyBulkRawValues(rawChanges);
  }
  clear() {
    this.copiedCells.clear();
    this.isCut = false;
    this._copiedDataString = '';
    this._copiedValues.clear();
  }
  isCellCopied(rowKey, columnId) {
    return this.copiedCells.has((0, _utils.cellKey)(rowKey, columnId));
  }
  getCopiedBorder(rowKey, columnId) {
    if (!this.isCellCopied(rowKey, columnId)) {
      return _utils.noBorder;
    }
    const pos = this._parent._toIndices({
      rowKey,
      columnId
    });
    if (!pos) {
      return _utils.noBorder;
    }
    const isNeighborCopied = (row, col) => {
      const neighbor = this._parent._toPosition(row, col);
      return neighbor !== null && this.copiedCells.has((0, _utils.cellKey)(neighbor.rowKey, neighbor.columnId));
    };
    return {
      top: !isNeighborCopied(pos.row - 1, pos.col),
      bottom: !isNeighborCopied(pos.row + 1, pos.col),
      left: !isNeighborCopied(pos.row, pos.col - 1),
      right: !isNeighborCopied(pos.row, pos.col + 1)
    };
  }
  get hasCopiedCells() {
    return this.copiedCells.size > 0;
  }
  _storeCells() {
    const cells = this._parent.cellInteraction.selectedCellsList;
    if (cells.length === 0) {
      return '';
    }
    const {
      cellValue
    } = this._parent;
    for (const cell of cells) {
      this.copiedCells.add((0, _utils.cellKey)(cell.rowKey, cell.columnId));
    }
    const indices = cells.map(c => this._parent._toIndices(c)).filter(idx => idx !== null);
    if (indices.length === 0) {
      return '';
    }
    const minRow = Math.min(...indices.map(i => i.row));
    const maxRow = Math.max(...indices.map(i => i.row));
    const minCol = Math.min(...indices.map(i => i.col));
    const maxCol = Math.max(...indices.map(i => i.col));
    const data = [];
    for (let r = minRow; r <= maxRow; r++) {
      const row = [];
      for (let c = minCol; c <= maxCol; c++) {
        const pos = this._parent._toPosition(r, c);
        if (pos && this.copiedCells.has((0, _utils.cellKey)(pos.rowKey, pos.columnId))) {
          const serialized = cellValue.serializeCellValue(pos.rowKey, pos.columnId);
          row.push(serialized);
          this._copiedValues.set(`${r - minRow}:${c - minCol}`, cellValue.getCellDisplayValue(pos.rowKey, pos.columnId));
        } else {
          row.push('');
        }
      }
      data.push(row);
    }
    const tsv = data.map(row => row.join('\t')).join('\n');
    this._copiedDataString = tsv;
    return tsv;
  }
}
exports.ClipboardState = ClipboardState;
//# sourceMappingURL=ClipboardState.js.map