"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.CellValueState = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _mobx = require("mobx");
var _cellTypes = require("../../components/EditableTable/cellTypes");
var _utils = require("./utils");
const builtInCellTypeMap = new Map(_cellTypes.builtInCellTypes.map(ct => [ct.type, ct]));
class CellValueState {
  constructor(parent, extraCellTypes = new Map()) {
    /** Pending invalid cell values, keyed by `${itemId}:${colId}`. */
    (0, _defineProperty2.default)(this, "_pendingCells", new Map());
    (0, _defineProperty2.default)(this, "_parent", void 0);
    (0, _defineProperty2.default)(this, "_extraCellTypes", void 0);
    (0, _defineProperty2.default)(this, "_cellTypeMap", builtInCellTypeMap);
    this._parent = parent;
    this._extraCellTypes = extraCellTypes;
    (0, _mobx.makeObservable)(this, {
      _pendingCells: _mobx.observable,
      clearCells: _mobx.action,
      toggleCell: _mobx.action,
      commitHandler: _mobx.action,
      applyBulkRawValues: _mobx.action,
      applyBulkValues: _mobx.action
    });
  }
  _buildCellTypeMap() {
    const map = new Map();
    for (const col of this._parent._allColumns) {
      if (col.cellType === 'custom' && col.typeConfig && typeof col.typeConfig === 'object' && 'ViewComponent' in col.typeConfig) {
        map.set(col.id, {
          type: 'custom',
          ...col.typeConfig
        });
      } else {
        map.set(col.id, builtInCellTypeMap.get(col.cellType) ?? this._extraCellTypes.get(col.cellType) ?? _cellTypes.textCellType);
      }
    }
    this._cellTypeMap = map;
  }
  resolveCellTypeByColumnId(columnId) {
    return this._cellTypeMap.get(columnId) ?? _cellTypes.textCellType;
  }
  getCellDisplayValue(rowKey, columnId) {
    const pending = this._getPendingCell(rowKey, columnId);
    if (pending) {
      return pending.value;
    }
    const column = this._parent._columnMap.get(columnId);
    const keyedItem = this._parent._getKeyedItem(rowKey);
    return column && keyedItem ? column.getValue(keyedItem.item) : undefined;
  }
  getCellValidation(rowKey, columnId) {
    const pending = this._getPendingCell(rowKey, columnId);
    if (pending) {
      return {
        valid: false,
        errors: pending.errors
      };
    }
    return _utils.validResult;
  }
  isCellEditable(rowKey, columnId) {
    const column = this._parent._columnMap.get(columnId);
    if (!column) {
      return false;
    }
    const resolved = this.resolveCellTypeByColumnId(column.id);
    if (resolved.editable === false || !resolved.EditComponent) {
      return false;
    }
    if (!column.setValue) {
      return false;
    }
    if (typeof column.editable === 'function') {
      const keyedItem = this._parent._getKeyedItem(rowKey);
      return keyedItem ? column.editable(keyedItem.item) : false;
    }
    return column.editable !== false;
  }

  /** Serialize a cell value to a string (for clipboard copy/cut). */
  serializeCellValue(rowKey, columnId) {
    const column = this._parent._columnMap.get(columnId);
    const keyedItem = this._parent._getKeyedItem(rowKey);
    if (!column || !keyedItem) {
      return '';
    }
    const resolved = this.resolveCellTypeByColumnId(column.id);
    const pending = this._getPendingCell(rowKey, columnId);
    const value = pending ? pending.value : column.getValue(keyedItem.item);
    return resolved.serialize ? resolved.serialize(value) : String(value ?? '');
  }

  /** Clear selected cells (Delete/Backspace). Respects cellType.clearable. */
  clearCells(cells) {
    const changes = [];
    for (const cell of cells) {
      const column = this._parent._columnMap.get(cell.columnId);
      if (!(column != null && column.setValue)) {
        continue;
      }
      const resolved = this.resolveCellTypeByColumnId(column.id);
      if (resolved.clearable === false) {
        continue;
      }
      const pendingKey = this._pendingCellKey(cell.rowKey, cell.columnId);
      if (pendingKey) {
        this._pendingCells.delete(pendingKey);
      }
      const value = resolved.deserialize ? resolved.deserialize('') : '';
      changes.push({
        rowKey: cell.rowKey,
        columnId: cell.columnId,
        value
      });
    }
    if (changes.length > 0) {
      this.applyBulkValues(changes);
    }
  }
  toggleCell(rowKey, columnId) {
    const column = this._parent._columnMap.get(columnId);
    const keyedItem = this._parent._getKeyedItem(rowKey);
    if (!(column != null && column.setValue) || !keyedItem) {
      return;
    }
    const resolved = this.resolveCellTypeByColumnId(column.id);
    if (!resolved.toggleValue) {
      return;
    }
    const value = column.getValue(keyedItem.item);
    const newValue = resolved.toggleValue(value);
    const updatedItem = column.setValue(keyedItem.item, newValue);
    this._parent.mutation.updateItems([updatedItem]);
  }

  /** Commit handler — used as callback for CellInteractionState. */
  commitHandler(editingValue, cell) {
    if (editingValue !== undefined) {
      const resolved = this.resolveCellTypeByColumnId(cell.columnId);
      const normalized = resolved.normalizeOnCommit ? resolved.normalizeOnCommit(editingValue) : editingValue;
      this._applyValue(cell.rowKey, cell.columnId, normalized);
    }
  }
  _getPendingCell(rowKey, columnId) {
    const key = this._pendingCellKey(rowKey, columnId);
    return key ? this._pendingCells.get(key) : undefined;
  }
  _pendingCellKey(rowKey, columnId) {
    const keyedItem = this._parent._getKeyedItem(rowKey);
    const column = this._parent._columnMap.get(columnId);
    if (!keyedItem || !column) {
      return undefined;
    }
    return `${keyedItem.key}:${column.id}`;
  }

  /**
   * Deserialize a raw string to a typed value. Returns an error message
   * if the conversion fails
   */
  tryDeserialize(columnId, rawValue) {
    const column = this._parent._columnMap.get(columnId);
    if (!column) {
      return {
        value: rawValue
      };
    }
    const resolved = this.resolveCellTypeByColumnId(column.id);
    if (!resolved.deserialize) {
      return {
        value: rawValue
      };
    }
    try {
      return {
        value: resolved.deserialize(rawValue)
      };
    } catch {
      return {
        value: rawValue,
        error: 'Value is not compatible'
      };
    }
  }

  /**
   * Deserialize and apply multiple raw string values in bulk.
   * Handles conversion failures by storing them as pending cells.
   */
  applyBulkRawValues(rawChanges) {
    const changes = [];
    for (const {
      rowKey,
      columnId,
      rawValue
    } of rawChanges) {
      const {
        value,
        error
      } = this.tryDeserialize(columnId, rawValue);
      if (error) {
        const pendingKey = this._pendingCellKey(rowKey, columnId);
        if (pendingKey) {
          this._pendingCells.set(pendingKey, {
            value,
            errors: [error]
          });
        }
      } else {
        changes.push({
          rowKey,
          columnId,
          value
        });
      }
    }
    this.applyBulkValues(changes);
  }

  /**
   * Apply multiple cell values in bulk. Validates per cell, accumulates
   * changes per row, and submits all modified items in a single update.
   */
  applyBulkValues(changes) {
    const rowItems = new Map();
    for (const {
      rowKey,
      columnId,
      value
    } of changes) {
      const column = this._parent._columnMap.get(columnId);
      const keyedItem = this._parent._getKeyedItem(rowKey);
      if (!(column != null && column.setValue) || !keyedItem) {
        continue;
      }
      const resolved = this.resolveCellTypeByColumnId(column.id);
      const result = (0, _utils.runCellValidation)(value, column.validation, resolved.validate);
      const pendingKey = this._pendingCellKey(rowKey, columnId);
      if (result.valid) {
        if (pendingKey) {
          this._pendingCells.delete(pendingKey);
        }
        const currentItem = rowItems.get(rowKey) ?? keyedItem.item;
        rowItems.set(rowKey, column.setValue(currentItem, value));
      } else if (pendingKey) {
        this._pendingCells.set(pendingKey, {
          value,
          errors: result.errors ?? []
        });
      }
    }
    this._parent.mutation.updateItems(Array.from(rowItems.values()));
  }
  _applyValue(rowKey, columnId, value) {
    const column = this._parent._columnMap.get(columnId);
    const keyedItem = this._parent._getKeyedItem(rowKey);
    if (!(column != null && column.setValue) || !keyedItem) {
      return;
    }
    const resolved = this.resolveCellTypeByColumnId(column.id);
    const result = (0, _utils.runCellValidation)(value, column.validation, resolved.validate);
    const pendingKey = this._pendingCellKey(rowKey, columnId);
    if (result.valid) {
      if (pendingKey) {
        this._pendingCells.delete(pendingKey);
      }
      const updatedItem = column.setValue(keyedItem.item, value);
      this._parent.mutation.updateItems([updatedItem]);
    } else if (pendingKey) {
      this._pendingCells.set(pendingKey, {
        value,
        errors: result.errors ?? []
      });
    }
  }
}
exports.CellValueState = CellValueState;
//# sourceMappingURL=CellValueState.js.map