"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "default", {
    enumerable: true,
    get: function() {
        return CellMeta;
    }
});
const _utils = require("../utils");
const _lazyFactoryMap = /*#__PURE__*/ _interop_require_default(require("../lazyFactoryMap"));
const _object = require("../../../helpers/object");
const _mixed = require("../../../helpers/mixed");
const _number = require("../../../helpers/number");
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
class CellMeta {
    /**
   * Updates cell meta object by merging settings with the current state.
   *
   * @param {number} physicalRow The physical row index which points what cell meta object is updated.
   * @param {number} physicalColumn The physical column index which points what cell meta object is updated.
   * @param {object} settings An object to merge with.
   */ updateMeta(physicalRow, physicalColumn, settings) {
        const meta = this.getMeta(physicalRow, physicalColumn);
        (0, _object.extend)(meta, settings);
        (0, _utils.extendByMetaType)(meta, settings);
    }
    /**
   * Creates one or more rows at specific position.
   *
   * @param {number} physicalRow The physical row index which points from what position the row is added.
   * @param {number} amount An amount of rows to add.
   */ createRow(physicalRow, amount) {
        this.metas.insert(physicalRow, amount);
    }
    /**
   * Creates one or more columns at specific position.
   *
   * @param {number} physicalColumn The physical column index which points from what position the column is added.
   * @param {number} amount An amount of columns to add.
   */ createColumn(physicalColumn, amount) {
        for(let i = 0; i < this.metas.size(); i++){
            this.metas.obtain(i).insert(physicalColumn, amount);
        }
    }
    /**
   * Removes one or more rows from the collection.
   *
   * @param {number} physicalRow The physical row index which points from what position the row is removed.
   * @param {number} amount An amount of rows to remove.
   */ removeRow(physicalRow, amount) {
        this.metas.remove(physicalRow, amount);
    }
    /**
   * Removes one or more columns from the collection.
   *
   * @param {number} physicalColumn The physical column index which points from what position the column is removed.
   * @param {number} amount An amount of columns to remove.
   */ removeColumn(physicalColumn, amount) {
        for(let i = 0; i < this.metas.size(); i++){
            this.metas.obtain(i).remove(physicalColumn, amount);
        }
    }
    /**
   * Gets settings object for this layer.
   *
   * @param {number} physicalRow The physical row index.
   * @param {number} physicalColumn The physical column index.
   * @param {string} [key] If the key exists its value will be returned, otherwise the whole cell meta object.
   * @returns {object}
   */ getMeta(physicalRow, physicalColumn, key) {
        const cellMeta = this.metas.obtain(physicalRow).obtain(physicalColumn);
        if (key === undefined) {
            return cellMeta;
        }
        return cellMeta[key];
    }
    /**
   * Sets settings object for this layer defined by "key" property.
   *
   * @param {number} physicalRow The physical row index.
   * @param {number} physicalColumn The physical column index.
   * @param {string} key The property name to set.
   * @param {*} value Value to save.
   */ setMeta(physicalRow, physicalColumn, key, value) {
        const cellMeta = this.metas.obtain(physicalRow).obtain(physicalColumn);
        cellMeta._automaticallyAssignedMetaProps?.delete(key);
        cellMeta[key] = value;
    }
    /**
   * Removes a property defined by the "key" argument from the cell meta object.
   *
   * @param {number} physicalRow The physical row index.
   * @param {number} physicalColumn The physical column index.
   * @param {string} key The property name to remove.
   */ removeMeta(physicalRow, physicalColumn, key) {
        const cellMeta = this.metas.obtain(physicalRow).obtain(physicalColumn);
        delete cellMeta[key];
    }
    /**
   * Returns all cell meta objects that were created during the Handsontable operation. As cell meta
   * objects are created lazy, the length of the returned collection depends on how and when the
   * table has asked for access to that meta objects.
   *
   * @returns {object[]}
   */ getMetas() {
        const metas = [];
        const rows = Array.from(this.metas.values());
        for(let row = 0; row < rows.length; row++){
            // Getting a meta for already added row (new row already exist - it has been added using `createRow` method).
            // However, is not ready until the first `getMeta` call (lazy loading).
            if ((0, _mixed.isDefined)(rows[row])) {
                metas.push(...rows[row].values());
            }
        }
        return metas;
    }
    /**
   * Returns all cell meta objects that were created during the Handsontable operation but for
   * specific row index.
   *
   * @param {number} physicalRow The physical row index.
   * @returns {object[]}
   */ getMetasAtRow(physicalRow) {
        (0, _utils.assert)(()=>(0, _number.isUnsignedNumber)(physicalRow), 'Expecting an unsigned number.');
        const rowsMeta = new Map(this.metas);
        if (!rowsMeta.has(physicalRow)) {
            return [];
        }
        return Array.from(rowsMeta.get(physicalRow)).sort(([a], [b])=>a - b).map(([, meta])=>meta);
    }
    /**
   * Clears all saved cell meta objects.
   */ clearCache() {
        this.metas.clear();
    }
    /**
   * Creates and returns new structure for cell meta objects stored in columnar axis.
   *
   * @private
   * @returns {object}
   */ _createRow() {
        return new _lazyFactoryMap.default((physicalColumn)=>this._createMeta(physicalColumn));
    }
    /**
   * Creates and returns new cell meta object with properties inherited from the column meta layer.
   *
   * @private
   * @param {number} physicalColumn The physical column index.
   * @returns {object}
   */ _createMeta(physicalColumn) {
        const ColumnMeta = this.columnMeta.getMetaConstructor(physicalColumn);
        return new ColumnMeta();
    }
    constructor(columnMeta){
        /**
   * Holder for cell meta objects, organized as a grid of LazyFactoryMap of LazyFactoryMaps.
   * The access to the cell meta object is done through access to the row defined by the physical
   * row index and then by accessing the second LazyFactory Map under the physical column index.
   *
   * @type {LazyFactoryMap<number, LazyFactoryMap<number, object>>}
   */ this.metas = new _lazyFactoryMap.default(()=>this._createRow());
        this.columnMeta = columnMeta;
    }
}
