"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: Object.getOwnPropertyDescriptor(all, name).get
    });
}
_export(exports, {
    get Formulas () {
        return Formulas;
    },
    get PLUGIN_KEY () {
        return PLUGIN_KEY;
    },
    get PLUGIN_PRIORITY () {
        return PLUGIN_PRIORITY;
    },
    get SETTING_KEYS () {
        return SETTING_KEYS;
    }
});
const _base = require("../base");
const _staticRegister = require("../../utils/staticRegister");
const _console = require("../../helpers/console");
const _number = require("../../helpers/number");
const _object = require("../../helpers/object");
const _mixed = require("../../helpers/mixed");
const _register = require("./engine/register");
const _utils = require("./utils");
const _settings = require("./engine/settings");
const _data = require("../../helpers/data");
const _string = require("../../helpers/string");
const _valueAccessors = require("../../utils/valueAccessors");
const _hooks = require("../../core/hooks");
const _indexSyncer = /*#__PURE__*/ _interop_require_default(require("./indexSyncer"));
function _check_private_redeclaration(obj, privateCollection) {
    if (privateCollection.has(obj)) {
        throw new TypeError("Cannot initialize the same private elements twice on an object");
    }
}
function _class_apply_descriptor_get(receiver, descriptor) {
    if (descriptor.get) {
        return descriptor.get.call(receiver);
    }
    return descriptor.value;
}
function _class_apply_descriptor_set(receiver, descriptor, value) {
    if (descriptor.set) {
        descriptor.set.call(receiver, value);
    } else {
        if (!descriptor.writable) {
            throw new TypeError("attempted to set read only private field");
        }
        descriptor.value = value;
    }
}
function _class_extract_field_descriptor(receiver, privateMap, action) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to " + action + " private field on non-instance");
    }
    return privateMap.get(receiver);
}
function _class_private_field_get(receiver, privateMap) {
    var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
    return _class_apply_descriptor_get(receiver, descriptor);
}
function _class_private_field_init(obj, privateMap, value) {
    _check_private_redeclaration(obj, privateMap);
    privateMap.set(obj, value);
}
function _class_private_field_set(receiver, privateMap, value) {
    var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
    _class_apply_descriptor_set(receiver, descriptor, value);
    return value;
}
function _class_private_method_get(receiver, privateSet, fn) {
    if (!privateSet.has(receiver)) {
        throw new TypeError("attempted to get private field on non-instance");
    }
    return fn;
}
function _class_private_method_init(obj, privateSet) {
    _check_private_redeclaration(obj, privateSet);
    privateSet.add(obj);
}
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
const PLUGIN_KEY = 'formulas';
const SETTING_KEYS = [
    'maxRows',
    'maxColumns',
    'language'
];
const PLUGIN_PRIORITY = 260;
_hooks.Hooks.getSingleton().register('afterNamedExpressionAdded');
_hooks.Hooks.getSingleton().register('afterNamedExpressionRemoved');
_hooks.Hooks.getSingleton().register('afterSheetAdded');
_hooks.Hooks.getSingleton().register('afterSheetRemoved');
_hooks.Hooks.getSingleton().register('afterSheetRenamed');
_hooks.Hooks.getSingleton().register('afterFormulasValuesUpdate');
// This function will be used for detecting changes coming from the `UndoRedo` plugin. This kind of change won't be
// handled by whole body of listeners and therefore won't change undo/redo stack inside engine provided by HyperFormula.
// HyperFormula's `undo` and `redo` methods will do it instead. Please keep in mind that undo/redo stacks inside
// instances of Handsontable and HyperFormula should be synced (number of actions should be the same).
const isBlockedSource = (source)=>source === 'UndoRedo.undo' || source === 'UndoRedo.redo' || source === 'auto';
var /**
   * Flag used to bypass hooks in internal operations.
   *
   * @private
   * @type {boolean}
   */ _internalOperationPending = /*#__PURE__*/ new WeakMap(), /**
   * Flag needed to mark if Handsontable was initialized with no data.
   * (Required to work around the fact, that Handsontable auto-generates sample data, when no data is provided).
   *
   * @type {boolean}
   */ _hotWasInitializedWithEmptyData = /*#__PURE__*/ new WeakMap(), /**
   * The list of the HyperFormula listeners.
   *
   * @type {Array}
   */ _engineListeners = /*#__PURE__*/ new WeakMap(), /**
   * Update sheetName and sheetId properties.
   *
   * @param {string} [sheetName] The new sheet name.
   */ _updateSheetNameAndSheetId = /*#__PURE__*/ new WeakSet(), /**
   * Get the value to be passed to the formula engine.
   * If the value is an object, utilize the valueGetter for that cell, otherwise return the value as is.
   *
   * @param {number} row The physical row index.
   * @param {number} column The physical column index.
   * @param {*} value The value to be passed to the formula engine.
   * @returns {*} The value to be displayed in the cell.
   */ _getValueGetterValue = /*#__PURE__*/ new WeakSet(), /**
   * Get the source data array to be passed to the formula engine.
   * If the value is an object, utilize the valueGetter for that cell, otherwise return the value as is.
   *
   * @param {number} [row] The starting visual row index.
   * @param {number} [column] The starting visual column index.
   * @param {number} [row2] The ending visual row index.
   * @param {number} [column2] The ending visual column index.
   * @returns {Array} The source data array to be passed to the formula engine.
   */ _getProcessedSourceDataArray = /*#__PURE__*/ new WeakSet(), /**
   * The hook allows to translate the formula value to calculated value before it goes to the
   * validator function.
   *
   * @param {*} value The cell value to validate.
   * @param {number} visualRow The visual row index.
   * @param {number|string} prop The visual column index or property name of the column.
   * @returns {*} Returns value to validate.
   */ _onBeforeValidate = /*#__PURE__*/ new WeakSet(), /**
   * `onBeforeAutofill` hook callback.
   *
   * @param {Array[]} fillData The data that was used to fill the `targetRange`. If `beforeAutofill` was used
   * and returned `[[]]`, this will be the same object that was returned from `beforeAutofill`.
   * @param {CellRange} sourceRange The range values will be filled from.
   * @param {CellRange} targetRange The range new values will be filled into.
   * @returns {boolean|*}
   */ _onBeforeAutofill = /*#__PURE__*/ new WeakSet(), /**
   * `beforeLoadData` hook callback.
   *
   * @param {Array} sourceData Array of arrays or array of objects containing data.
   * @param {boolean} initialLoad Flag that determines whether the data has been loaded during the initialization.
   * @param {string} [source] Source of the call.
   */ _onBeforeLoadData = /*#__PURE__*/ new WeakSet(), /**
   * Callback to `afterCellMetaReset` hook which is triggered after setting cell meta.
   */ _onAfterCellMetaReset = /*#__PURE__*/ new WeakSet(), /**
   * `afterLoadData` hook callback.
   *
   * @param {Array} sourceData Array of arrays or array of objects containing data.
   * @param {boolean} initialLoad Flag that determines whether the data has been loaded during the initialization.
   * @param {string} [source] Source of the call.
   */ _onAfterLoadData = /*#__PURE__*/ new WeakSet(), /**
   * `modifyData` hook callback.
   *
   * @param {number} visualRow Visual row index.
   * @param {number} visualColumn Visual column index.
   * @param {object} valueHolder Object which contains original value which can be modified by overwriting `.value`
   *   property.
   * @param {string} ioMode String which indicates for what operation hook is fired (`get` or `set`).
   */ _onModifyData = /*#__PURE__*/ new WeakSet(), /**
   * `modifySourceData` hook callback.
   *
   * @param {number} row Physical row index.
   * @param {number|string} columnOrProp Physical column index or prop.
   * @param {object} valueHolder Object which contains original value which can be modified by overwriting `.value`
   *   property.
   * @param {string} ioMode String which indicates for what operation hook is fired (`get` or `set`).
   */ _onModifySourceData = /*#__PURE__*/ new WeakSet(), /**
   * `onAfterSetDataAtCell` hook callback.
   *
   * @param {Array[]} changes An array of changes in format [[row, prop, oldValue, value], ...].
   * @param {string} [source] String that identifies source of hook call
   *                          ([list of all available sources]{@link https://handsontable.com/docs/javascript-data-grid/events-and-hooks/#handsontable-hooks}).
   */ _onAfterSetDataAtCell = /*#__PURE__*/ new WeakSet(), /**
   * `onAfterSetSourceDataAtCell` hook callback.
   *
   * @param {Array[]} changes An array of changes in format [[row, column, oldValue, value], ...].
   * @param {string} [source] String that identifies source of hook call
   *                          ([list of all available sources]{@link https://handsontable.com/docs/javascript-data-grid/events-and-hooks/#handsontable-hooks}).
   */ _onAfterSetSourceDataAtCell = /*#__PURE__*/ new WeakSet(), /**
   * `beforeCreateRow` hook callback.
   *
   * @param {number} visualRow Represents the visual index of first newly created row in the data source array.
   * @param {number} amount Number of newly created rows in the data source array.
   * @returns {*|boolean} If false is returned the action is canceled.
   */ _onBeforeCreateRow = /*#__PURE__*/ new WeakSet(), /**
   * `beforeCreateCol` hook callback.
   *
   * @param {number} visualColumn Represents the visual index of first newly created column in the data source.
   * @param {number} amount Number of newly created columns in the data source.
   * @returns {*|boolean} If false is returned the action is canceled.
   */ _onBeforeCreateCol = /*#__PURE__*/ new WeakSet(), /**
   * `beforeRemoveRow` hook callback.
   *
   * @param {number} row Visual index of starter row.
   * @param {number} amount Amount of rows to be removed.
   * @param {number[]} physicalRows An array of physical rows removed from the data source.
   * @returns {*|boolean} If false is returned the action is canceled.
   */ _onBeforeRemoveRow = /*#__PURE__*/ new WeakSet(), /**
   * `beforeRemoveCol` hook callback.
   *
   * @param {number} col Visual index of starter column.
   * @param {number} amount Amount of columns to be removed.
   * @param {number[]} physicalColumns An array of physical columns removed from the data source.
   * @returns {*|boolean} If false is returned the action is canceled.
   */ _onBeforeRemoveCol = /*#__PURE__*/ new WeakSet(), /**
   * `afterCreateRow` hook callback.
   *
   * @param {number} visualRow Represents the visual index of first newly created row in the data source array.
   * @param {number} amount Number of newly created rows in the data source array.
   * @param {string} [source] String that identifies source of hook call
   *                          ([list of all available sources]{@link https://handsontable.com/docs/javascript-data-grid/events-and-hooks/#handsontable-hooks}).
   */ _onAfterCreateRow = /*#__PURE__*/ new WeakSet(), /**
   * `afterCreateCol` hook callback.
   *
   * @param {number} visualColumn Represents the visual index of first newly created column in the data source.
   * @param {number} amount Number of newly created columns in the data source.
   * @param {string} [source] String that identifies source of hook call
   *                          ([list of all available sources]{@link https://handsontable.com/docs/javascript-data-grid/events-and-hooks/#handsontable-hooks}).
   */ _onAfterCreateCol = /*#__PURE__*/ new WeakSet(), /**
   * `afterRemoveRow` hook callback.
   *
   * @param {number} row Visual index of starter row.
   * @param {number} amount An amount of removed rows.
   * @param {number[]} physicalRows An array of physical rows removed from the data source.
   * @param {string} [source] String that identifies source of hook call
   *                          ([list of all available sources]{@link https://handsontable.com/docs/javascript-data-grid/events-and-hooks/#handsontable-hooks}).
   */ _onAfterRemoveRow = /*#__PURE__*/ new WeakSet(), /**
   * `afterRemoveCol` hook callback.
   *
   * @param {number} col Visual index of starter column.
   * @param {number} amount An amount of removed columns.
   * @param {number[]} physicalColumns An array of physical columns removed from the data source.
   * @param {string} [source] String that identifies source of hook call
   *                          ([list of all available sources]{@link https://handsontable.com/docs/javascript-data-grid/events-and-hooks/#handsontable-hooks}).
   */ _onAfterRemoveCol = /*#__PURE__*/ new WeakSet(), /**
   * `afterDetachChild` hook callback.
   * Used to sync the data of the rows detached in the Nested Rows plugin with the engine's dataset.
   *
   * @param {object} parent An object representing the parent from which the element was detached.
   * @param {object} element The detached element.
   * @param {number} finalElementRowIndex The final row index of the detached element.
   */ _onAfterDetachChild = /*#__PURE__*/ new WeakSet(), /**
   * Called when a value is updated in the engine.
   *
   * @fires Hooks#afterFormulasValuesUpdate
   * @param {Array} changes The values and location of applied changes.
   */ _onEngineValuesUpdated = /*#__PURE__*/ new WeakSet(), /**
   * Called when a named expression is added to the engine instance.
   *
   * @fires Hooks#afterNamedExpressionAdded
   * @param {string} namedExpressionName The name of the added expression.
   * @param {Array} changes The values and location of applied changes.
   */ _onEngineNamedExpressionsAdded = /*#__PURE__*/ new WeakSet(), /**
   * Called when a named expression is removed from the engine instance.
   *
   * @fires Hooks#afterNamedExpressionRemoved
   * @param {string} namedExpressionName The name of the removed expression.
   * @param {Array} changes The values and location of applied changes.
   */ _onEngineNamedExpressionsRemoved = /*#__PURE__*/ new WeakSet(), /**
   * Called when a new sheet is added to the engine instance.
   *
   * @fires Hooks#afterSheetAdded
   * @param {string} addedSheetDisplayName The name of the added sheet.
   */ _onEngineSheetAdded = /*#__PURE__*/ new WeakSet(), /**
   * Called when a sheet in the engine instance is renamed.
   *
   * @fires Hooks#afterSheetRenamed
   * @param {string} oldDisplayName The old name of the sheet.
   * @param {string} newDisplayName The new name of the sheet.
   */ _onEngineSheetRenamed = /*#__PURE__*/ new WeakSet(), /**
   * Called when a sheet is removed from the engine instance.
   *
   * @fires Hooks#afterSheetRemoved
   * @param {string} removedSheetDisplayName The removed sheet name.
   * @param {Array} changes The values and location of applied changes.
   */ _onEngineSheetRemoved = /*#__PURE__*/ new WeakSet();
class Formulas extends _base.BasePlugin {
    static get PLUGIN_KEY() {
        return PLUGIN_KEY;
    }
    static get PLUGIN_PRIORITY() {
        return PLUGIN_PRIORITY;
    }
    static get SETTING_KEYS() {
        return [
            PLUGIN_KEY,
            ...SETTING_KEYS
        ];
    }
    /**
   * Checks if the plugin is enabled in the handsontable settings. This method is executed in {@link Hooks#beforeInit}
   * hook and if it returns `true` then the {@link Formulas#enablePlugin} method is called.
   *
   * @returns {boolean}
   */ isEnabled() {
        /* eslint-disable no-unneeded-ternary */ return this.hot.getSettings()[PLUGIN_KEY] ? true : false;
    }
    /**
   * Enables the plugin functionality for this Handsontable instance.
   */ enablePlugin() {
        if (this.enabled) {
            return;
        }
        this.engine = (0, _register.setupEngine)(this.hot) ?? this.engine;
        if (!this.engine) {
            (0, _console.warn)('Missing the required `engine` key in the Formulas settings. Please fill it with either an' + ' engine class or an engine instance.');
            return;
        }
        // Useful for disabling -> enabling the plugin using `updateSettings` or the API.
        if (this.sheetName !== null && !this.engine.doesSheetExist(this.sheetName)) {
            const newSheetName = this.addSheet(this.sheetName, _class_private_method_get(this, _getProcessedSourceDataArray, getProcessedSourceDataArray).call(this));
            if (newSheetName !== false) {
                _class_private_method_get(this, _updateSheetNameAndSheetId, updateSheetNameAndSheetId).call(this, newSheetName);
            }
        }
        this.addHook('beforeLoadData', (...args)=>_class_private_method_get(this, _onBeforeLoadData, onBeforeLoadData).call(this, ...args));
        this.addHook('afterLoadData', (...args)=>_class_private_method_get(this, _onAfterLoadData, onAfterLoadData).call(this, ...args));
        // The `updateData` hooks utilize the same logic as the `loadData` hooks.
        this.addHook('beforeUpdateData', (...args)=>_class_private_method_get(this, _onBeforeLoadData, onBeforeLoadData).call(this, ...args));
        this.addHook('afterUpdateData', (...args)=>_class_private_method_get(this, _onAfterLoadData, onAfterLoadData).call(this, ...args));
        this.addHook('modifyData', (...args)=>_class_private_method_get(this, _onModifyData, onModifyData).call(this, ...args));
        this.addHook('modifySourceData', (...args)=>_class_private_method_get(this, _onModifySourceData, onModifySourceData).call(this, ...args));
        this.addHook('beforeValidate', (...args)=>_class_private_method_get(this, _onBeforeValidate, onBeforeValidate).call(this, ...args));
        this.addHook('afterSetSourceDataAtCell', (...args)=>_class_private_method_get(this, _onAfterSetSourceDataAtCell, onAfterSetSourceDataAtCell).call(this, ...args));
        this.addHook('afterSetDataAtCell', (...args)=>_class_private_method_get(this, _onAfterSetDataAtCell, onAfterSetDataAtCell).call(this, ...args));
        this.addHook('afterSetDataAtRowProp', (...args)=>_class_private_method_get(this, _onAfterSetDataAtCell, onAfterSetDataAtCell).call(this, ...args));
        this.addHook('beforeCreateRow', (...args)=>_class_private_method_get(this, _onBeforeCreateRow, onBeforeCreateRow).call(this, ...args));
        this.addHook('beforeCreateCol', (...args)=>_class_private_method_get(this, _onBeforeCreateCol, onBeforeCreateCol).call(this, ...args));
        this.addHook('afterCreateRow', (...args)=>_class_private_method_get(this, _onAfterCreateRow, onAfterCreateRow).call(this, ...args));
        this.addHook('afterCreateCol', (...args)=>_class_private_method_get(this, _onAfterCreateCol, onAfterCreateCol).call(this, ...args));
        this.addHook('beforeRemoveRow', (...args)=>_class_private_method_get(this, _onBeforeRemoveRow, onBeforeRemoveRow).call(this, ...args));
        this.addHook('beforeRemoveCol', (...args)=>_class_private_method_get(this, _onBeforeRemoveCol, onBeforeRemoveCol).call(this, ...args));
        this.addHook('afterRemoveRow', (...args)=>_class_private_method_get(this, _onAfterRemoveRow, onAfterRemoveRow).call(this, ...args));
        this.addHook('afterRemoveCol', (...args)=>_class_private_method_get(this, _onAfterRemoveCol, onAfterRemoveCol).call(this, ...args));
        this.indexSyncer = new _indexSyncer.default(this.hot.rowIndexMapper, this.hot.columnIndexMapper, (postponedAction)=>{
            this.hot.addHookOnce('init', ()=>{
                // Engine is initialized after executing callback to `afterLoadData` hook. Thus, some actions on indexes should
                // be postponed.
                postponedAction();
            });
        });
        this.rowAxisSyncer = this.indexSyncer.getForAxis('row');
        this.columnAxisSyncer = this.indexSyncer.getForAxis('column');
        this.hot.addHook('afterRowSequenceChange', this.rowAxisSyncer.getIndexesChangeSyncMethod());
        this.hot.addHook('afterColumnSequenceChange', this.columnAxisSyncer.getIndexesChangeSyncMethod());
        this.hot.addHook('beforeRowMove', (movedRows, finalIndex, _, movePossible)=>{
            this.rowAxisSyncer.storeMovesInformation(movedRows, finalIndex, movePossible);
        });
        this.hot.addHook('beforeColumnMove', (movedColumns, finalIndex, _, movePossible)=>{
            this.columnAxisSyncer.storeMovesInformation(movedColumns, finalIndex, movePossible);
        });
        this.hot.addHook('afterRowMove', (movedRows, finalIndex, dropIndex, movePossible, orderChanged)=>{
            this.rowAxisSyncer.calculateAndSyncMoves(movePossible, orderChanged);
        });
        this.hot.addHook('afterColumnMove', (movedColumns, finalIndex, dropIndex, movePossible, orderChanged)=>{
            this.columnAxisSyncer.calculateAndSyncMoves(movePossible, orderChanged);
        });
        this.hot.addHook('beforeColumnFreeze', (column, freezePerformed)=>{
            this.columnAxisSyncer.storeMovesInformation([
                column
            ], this.hot.getSettings().fixedColumnsStart, freezePerformed);
        });
        this.hot.addHook('afterColumnFreeze', (_, freezePerformed)=>{
            this.columnAxisSyncer.calculateAndSyncMoves(freezePerformed, freezePerformed);
        });
        this.hot.addHook('beforeColumnUnfreeze', (column, unfreezePerformed)=>{
            this.columnAxisSyncer.storeMovesInformation([
                column
            ], this.hot.getSettings().fixedColumnsStart - 1, unfreezePerformed);
        });
        this.hot.addHook('afterColumnUnfreeze', (_, unfreezePerformed)=>{
            this.columnAxisSyncer.calculateAndSyncMoves(unfreezePerformed, unfreezePerformed);
        });
        // TODO: Actions related to overwriting dates from HOT format to HF default format are done as callback to this
        // hook, because some hooks, such as `afterLoadData` doesn't have information about composed cell properties.
        // Another hooks are triggered to late for setting HF's engine data needed for some actions.
        this.addHook('afterCellMetaReset', (...args)=>_class_private_method_get(this, _onAfterCellMetaReset, onAfterCellMetaReset).call(this, ...args));
        // Handling undo actions on data just using HyperFormula's UndoRedo mechanism
        this.addHook('beforeUndo', ()=>{
            this.indexSyncer.setPerformUndo(true);
            this.engine.undo();
        });
        // Handling redo actions on data just using HyperFormula's UndoRedo mechanism
        this.addHook('beforeRedo', ()=>{
            this.indexSyncer.setPerformRedo(true);
            this.engine.redo();
        });
        this.addHook('afterUndo', ()=>{
            this.indexSyncer.setPerformUndo(false);
        });
        this.addHook('afterUndo', ()=>{
            this.indexSyncer.setPerformRedo(false);
        });
        this.addHook('afterDetachChild', (...args)=>_class_private_method_get(this, _onAfterDetachChild, onAfterDetachChild).call(this, ...args));
        this.addHook('beforeAutofill', (...args)=>_class_private_method_get(this, _onBeforeAutofill, onBeforeAutofill).call(this, ...args));
        _class_private_field_get(this, _engineListeners).forEach(([eventName, listener])=>this.engine.on(eventName, listener));
        super.enablePlugin();
    }
    /**
   * Disables the plugin functionality for this Handsontable instance.
   */ disablePlugin() {
        _class_private_field_get(this, _engineListeners).forEach(([eventName, listener])=>this.engine.off(eventName, listener));
        (0, _register.unregisterEngine)(this.engine, this.hot);
        this.engine = null;
        super.disablePlugin();
    }
    /**
   * Triggered on `updateSettings`.
   *
   * @private
   * @param {object} newSettings New set of settings passed to the `updateSettings` method.
   */ updatePlugin(newSettings) {
        const newEngineSettings = (0, _settings.getEngineSettingsWithOverrides)(this.hot.getSettings());
        if ((0, _settings.haveEngineSettingsChanged)(this.engine.getConfig(), newEngineSettings)) {
            this.engine.updateConfig(newEngineSettings);
        }
        const pluginSettings = this.hot.getSettings()[PLUGIN_KEY];
        if ((0, _mixed.isDefined)(pluginSettings) && (0, _mixed.isDefined)(pluginSettings.sheetName) && pluginSettings.sheetName !== this.sheetName) {
            this.switchSheet(pluginSettings.sheetName);
        }
        // If no data was passed to the `updateSettings` method and no sheet is connected to the instance -> create a
        // new sheet using the currently used data. Otherwise, it will be handled by the `afterLoadData` call.
        if (!newSettings.data && this.sheetName === null) {
            const sheetName = this.hot.getSettings()[PLUGIN_KEY].sheetName;
            if (sheetName && this.engine.doesSheetExist(sheetName)) {
                this.switchSheet(this.sheetName);
            } else {
                const newSheetName = this.addSheet(sheetName ?? undefined, _class_private_method_get(this, _getProcessedSourceDataArray, getProcessedSourceDataArray).call(this));
                _class_private_method_get(this, _updateSheetNameAndSheetId, updateSheetNameAndSheetId).call(this, newSheetName);
            }
        }
        super.updatePlugin(newSettings);
    }
    /**
   * Destroys the plugin instance.
   */ destroy() {
        _class_private_field_get(this, _engineListeners).forEach(([eventName, listener])=>this.engine?.off(eventName, listener));
        _class_private_field_set(this, _engineListeners, null);
        (0, _register.unregisterEngine)(this.engine, this.hot);
        this.engine = null;
        super.destroy();
    }
    /**
   * Add a sheet to the shared HyperFormula instance.
   *
   * @param {string|null} [sheetName] The new sheet name. If not provided (or a null is passed), will be
   * auto-generated by HyperFormula.
   * @param {Array} [sheetData] Data passed to the shared HyperFormula instance. Has to be declared as an array of
   * arrays - array of objects is not supported in this scenario.
   * @returns {boolean|string} `false` if the data format is unusable or it is impossible to add a new sheet to the
   * engine, the created sheet name otherwise.
   */ addSheet(sheetName, sheetData) {
        if ((0, _mixed.isDefined)(sheetData) && !(0, _data.isArrayOfArrays)(sheetData)) {
            (0, _console.warn)('The provided data should be an array of arrays.');
            return false;
        }
        if (sheetName !== undefined && sheetName !== null && this.engine.doesSheetExist(sheetName)) {
            (0, _console.warn)('Sheet with the provided name already exists.');
            return false;
        }
        try {
            const actualSheetName = this.engine.addSheet(sheetName ?? undefined);
            if (sheetData) {
                this.engine.setSheetContent(this.engine.getSheetId(actualSheetName), sheetData);
            }
            return actualSheetName;
        } catch (e) {
            (0, _console.warn)(e.message);
            return false;
        }
    }
    /**
   * Switch the sheet used as data in the Handsontable instance (it loads the data from the shared HyperFormula
   * instance).
   *
   * @param {string} sheetName Sheet name used in the shared HyperFormula instance.
   */ switchSheet(sheetName) {
        if (!this.engine.doesSheetExist(sheetName)) {
            (0, _console.error)(`The sheet named \`${sheetName}\` does not exist, switch aborted.`);
            return;
        }
        _class_private_method_get(this, _updateSheetNameAndSheetId, updateSheetNameAndSheetId).call(this, sheetName);
        const serialized = this.engine.getSheetSerialized(this.sheetId);
        if (serialized.length > 0) {
            this.hot.loadData(serialized, `${(0, _string.toUpperCaseFirst)(PLUGIN_KEY)}.switchSheet`);
        }
    }
    /**
   * Get the cell type under specified visual coordinates.
   *
   * @param {number} row Visual row index.
   * @param {number} column Visual column index.
   * @param {number} [sheet] The target sheet id, defaults to the current sheet.
   * @returns {string} Possible values: 'FORMULA' | 'VALUE' | 'ARRAYFORMULA' | 'EMPTY'.
   */ getCellType(row, column, sheet = this.sheetId) {
        const physicalRow = this.hot.toPhysicalRow(row);
        const physicalColumn = this.hot.toPhysicalColumn(column);
        if (physicalRow !== null && physicalColumn !== null) {
            return this.engine.getCellType({
                sheet,
                row: this.rowAxisSyncer.getHfIndexFromVisualIndex(row),
                col: this.columnAxisSyncer.getHfIndexFromVisualIndex(column)
            });
        } else {
            // Should return `EMPTY` when out of bounds (according to the test cases).
            return 'EMPTY';
        }
    }
    /**
   * Returns `true` if under specified visual coordinates is formula.
   *
   * @param {number} row Visual row index.
   * @param {number} column Visual column index.
   * @param {number} [sheet] The target sheet id, defaults to the current sheet.
   * @returns {boolean}
   */ isFormulaCellType(row, column, sheet = this.sheetId) {
        return this.engine.doesCellHaveFormula({
            sheet,
            row: this.rowAxisSyncer.getHfIndexFromVisualIndex(row),
            col: this.columnAxisSyncer.getHfIndexFromVisualIndex(column)
        });
    }
    /**
   * Renders dependent sheets (handsontable instances) based on the changes - list of the
   * recalculated dependent cells.
   *
   * @private
   * @param {object[]} dependentCells The values and location of applied changes within HF engine.
   * @param {boolean} [renderSelf] `true` if it's supposed to render itself, `false` otherwise.
   */ renderDependentSheets(dependentCells, renderSelf = false) {
        const affectedSheetIds = new Set();
        dependentCells.forEach((change)=>{
            // For the Named expression the address is empty, hence the `sheetId` is undefined.
            const sheetId = change?.address?.sheet;
            if (sheetId !== undefined) {
                if (!affectedSheetIds.has(sheetId)) {
                    affectedSheetIds.add(sheetId);
                }
            }
        });
        (0, _register.getRegisteredHotInstances)(this.engine).forEach((relatedHot, sheetId)=>{
            if ((renderSelf || sheetId !== this.sheetId) && affectedSheetIds.has(sheetId)) {
                relatedHot.render();
                relatedHot.view?.adjustElementsSize();
            }
        });
    }
    /**
   * Validates dependent cells based on the cells that are modified by the change.
   *
   * @private
   * @param {object[]} dependentCells The values and location of applied changes within HF engine.
   * @param {object[]} [changedCells] The values and location of applied changes by developer (through API or UI).
   */ validateDependentCells(dependentCells, changedCells = []) {
        const stringifyAddress = (change)=>{
            const { row, col, sheet } = change?.address ?? {};
            return (0, _mixed.isDefined)(sheet) ? `${sheet}:${row}x${col}` : '';
        };
        const changedCellsSet = new Set(changedCells.map((change)=>stringifyAddress(change)));
        dependentCells.forEach((change)=>{
            const { row, col } = change.address ?? {};
            // Don't try to validate cells outside of the visual part of the table.
            if ((0, _mixed.isDefined)(row) === false || (0, _mixed.isDefined)(col) === false || row >= this.hot.countRows() || col >= this.hot.countCols()) {
                return;
            }
            // For the Named expression the address is empty, hence the `sheetId` is undefined.
            const sheetId = change?.address?.sheet;
            const addressId = stringifyAddress(change);
            // Validate the cells that depend on the calculated formulas. Skip that cells
            // where the user directly changes the values - the Core triggers those validators.
            if (sheetId !== undefined && !changedCellsSet.has(addressId)) {
                const boundHot = (0, _register.getRegisteredHotInstances)(this.engine).get(sheetId);
                // if `sheetId` is not bound to any Handsontable instance, skip the validation process
                if (!boundHot) {
                    return;
                }
                // It will just re-render certain cell when necessary.
                boundHot.validateCell(boundHot.getDataAtCell(row, col), boundHot.getCellMeta(row, col), ()=>{});
            }
        });
    }
    /**
   * Sync a change from the change-related hooks with the engine.
   *
   * @private
   * @param {number} row Visual row index.
   * @param {number} column Visual column index.
   * @param {Handsontable.CellValue} newValue New value.
   * @returns {Array} Array of changes exported from the engine.
   */ syncChangeWithEngine(row, column, newValue) {
        const address = {
            row: this.rowAxisSyncer.getHfIndexFromVisualIndex(row),
            col: this.columnAxisSyncer.getHfIndexFromVisualIndex(column),
            sheet: this.sheetId
        };
        if (!this.engine.isItPossibleToSetCellContents(address)) {
            (0, _console.warn)(`Not possible to set cell data at ${JSON.stringify(address)}`);
            return;
        }
        const cellMeta = this.hot.getCellMeta(row, column);
        if ((0, _utils.isDate)(newValue, cellMeta.type)) {
            if ((0, _utils.isDateValid)(newValue, cellMeta.dateFormat)) {
                // Rewriting date in HOT format to HF format.
                newValue = (0, _utils.getDateInHfFormat)(newValue, cellMeta.dateFormat);
            } else if ((0, _utils.isFormula)(newValue) === false) {
                // Escaping value from date parsing using "'" sign (HF feature).
                newValue = `'${newValue}`;
            }
        }
        return this.engine.setCellContents(address, newValue);
    }
    constructor(...args){
        super(...args), _class_private_method_init(this, _updateSheetNameAndSheetId), _class_private_method_init(this, _getValueGetterValue), _class_private_method_init(this, _getProcessedSourceDataArray), _class_private_method_init(this, _onBeforeValidate), _class_private_method_init(this, _onBeforeAutofill), _class_private_method_init(this, _onBeforeLoadData), _class_private_method_init(this, _onAfterCellMetaReset), _class_private_method_init(this, _onAfterLoadData), _class_private_method_init(this, _onModifyData), _class_private_method_init(this, _onModifySourceData), _class_private_method_init(this, _onAfterSetDataAtCell), _class_private_method_init(this, _onAfterSetSourceDataAtCell), _class_private_method_init(this, _onBeforeCreateRow), _class_private_method_init(this, _onBeforeCreateCol), _class_private_method_init(this, _onBeforeRemoveRow), _class_private_method_init(this, _onBeforeRemoveCol), _class_private_method_init(this, _onAfterCreateRow), _class_private_method_init(this, _onAfterCreateCol), _class_private_method_init(this, _onAfterRemoveRow), _class_private_method_init(this, _onAfterRemoveCol), _class_private_method_init(this, _onAfterDetachChild), _class_private_method_init(this, _onEngineValuesUpdated), _class_private_method_init(this, _onEngineNamedExpressionsAdded), _class_private_method_init(this, _onEngineNamedExpressionsRemoved), _class_private_method_init(this, _onEngineSheetAdded), _class_private_method_init(this, _onEngineSheetRenamed), _class_private_method_init(this, _onEngineSheetRemoved), _class_private_field_init(this, _internalOperationPending, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _hotWasInitializedWithEmptyData, {
            writable: true,
            value: void 0
        }), _class_private_field_init(this, _engineListeners, {
            writable: true,
            value: void 0
        }), _class_private_field_set(this, _internalOperationPending, false), _class_private_field_set(this, _hotWasInitializedWithEmptyData, false), _class_private_field_set(this, _engineListeners, [
            [
                'valuesUpdated',
                (...args)=>_class_private_method_get(this, _onEngineValuesUpdated, onEngineValuesUpdated).call(this, ...args)
            ],
            [
                'namedExpressionAdded',
                (...args)=>_class_private_method_get(this, _onEngineNamedExpressionsAdded, onEngineNamedExpressionsAdded).call(this, ...args)
            ],
            [
                'namedExpressionRemoved',
                (...args)=>_class_private_method_get(this, _onEngineNamedExpressionsRemoved, onEngineNamedExpressionsRemoved).call(this, ...args)
            ],
            [
                'sheetAdded',
                (...args)=>_class_private_method_get(this, _onEngineSheetAdded, onEngineSheetAdded).call(this, ...args)
            ],
            [
                'sheetRenamed',
                (...args)=>_class_private_method_get(this, _onEngineSheetRenamed, onEngineSheetRenamed).call(this, ...args)
            ],
            [
                'sheetRemoved',
                (...args)=>_class_private_method_get(this, _onEngineSheetRemoved, onEngineSheetRemoved).call(this, ...args)
            ]
        ]), /**
   * Static register used to set up one global HyperFormula instance.
   * TODO: currently used in tests, might be removed later.
   *
   * @private
   * @type {object}
   */ this.staticRegister = (0, _staticRegister.staticRegister)('formulas'), /**
   * The engine instance that will be used for this instance of Handsontable.
   *
   * @type {HyperFormula|null}
   */ this.engine = null, /**
   * HyperFormula's sheet id.
   *
   * @type {number|null}
   */ this.sheetId = null, /**
   * HyperFormula's sheet name.
   *
   * @type {string|null}
   */ this.sheetName = null, /**
   * Index synchronizer responsible for manipulating with some general options related to indexes synchronization.
   *
   * @type {IndexSyncer|null}
   */ this.indexSyncer = null, /**
   * Index synchronizer responsible for syncing the order of HOT and HF's data for the axis of the rows.
   *
   * @type {AxisSyncer|null}
   */ this.rowAxisSyncer = null, /**
   * Index synchronizer responsible for syncing the order of HOT and HF's data for the axis of the columns.
   *
   * @type {AxisSyncer|null}
   */ this.columnAxisSyncer = null;
    }
}
function updateSheetNameAndSheetId(sheetName) {
    this.sheetName = sheetName;
    this.sheetId = this.engine.getSheetId(this.sheetName);
}
function getValueGetterValue(row, column, value) {
    if ((0, _object.isObject)(value) && value !== null) {
        const visualRow = this.hot.toVisualRow(row);
        const visualColumn = this.hot.toVisualColumn(column);
        value = (0, _valueAccessors.getValueGetterValue)(value, this.hot.getCellMeta(visualRow, visualColumn));
        value = value.toString();
    }
    return (0, _utils.normalizeValueForFormulaEngine)(value);
}
function getProcessedSourceDataArray(row, column, row2, column2) {
    return this.hot.getSourceDataArray(row, column, row2, column2).map((rowObject, rowIndex)=>{
        return rowObject.map((value, columnIndex)=>{
            return _class_private_method_get(this, _getValueGetterValue, getValueGetterValue).call(this, rowIndex, columnIndex, value);
        });
    });
}
function onBeforeValidate(value, visualRow, prop) {
    const visualColumn = this.hot.propToCol(prop);
    if (this.isFormulaCellType(visualRow, visualColumn)) {
        const address = {
            row: this.rowAxisSyncer.getHfIndexFromVisualIndex(visualRow),
            col: this.columnAxisSyncer.getHfIndexFromVisualIndex(visualColumn),
            sheet: this.sheetId
        };
        const cellMeta = this.hot.getCellMeta(visualRow, visualColumn);
        let cellValue = this.engine.getCellValue(address); // Date as an integer (Excel-like date).
        if (cellMeta.type === 'date' && (0, _number.isNumeric)(cellValue)) {
            cellValue = (0, _utils.getDateFromExcelDate)(cellValue, cellMeta.dateFormat);
        }
        // If `cellValue` is an object it is expected to be an error
        return typeof cellValue === 'object' && cellValue !== null ? cellValue.value : cellValue;
    }
    return value;
}
function onBeforeAutofill(fillData, sourceRange, targetRange) {
    const { row: sourceTopStartRow, col: sourceTopStartColumn } = sourceRange.getTopStartCorner();
    const { row: sourceBottomEndRow, col: sourceBottomEndColumn } = sourceRange.getBottomEndCorner();
    const { row: targetTopStartRow, col: targetTopStartColumn } = targetRange.getTopStartCorner();
    const { row: targetBottomEndRow, col: targetBottomEndColumn } = targetRange.getBottomEndCorner();
    const engineSourceRange = {
        start: {
            row: this.rowAxisSyncer.getHfIndexFromVisualIndex(sourceTopStartRow),
            col: this.columnAxisSyncer.getHfIndexFromVisualIndex(sourceTopStartColumn),
            sheet: this.sheetId
        },
        end: {
            row: this.rowAxisSyncer.getHfIndexFromVisualIndex(sourceBottomEndRow),
            col: this.columnAxisSyncer.getHfIndexFromVisualIndex(sourceBottomEndColumn),
            sheet: this.sheetId
        }
    };
    const engineTargetRange = {
        start: {
            row: this.rowAxisSyncer.getHfIndexFromVisualIndex(targetTopStartRow),
            col: this.columnAxisSyncer.getHfIndexFromVisualIndex(targetTopStartColumn),
            sheet: this.sheetId
        },
        end: {
            row: this.rowAxisSyncer.getHfIndexFromVisualIndex(targetBottomEndRow),
            col: this.columnAxisSyncer.getHfIndexFromVisualIndex(targetBottomEndColumn),
            sheet: this.sheetId
        }
    };
    // Blocks the autofill operation if HyperFormula says that at least one of
    // the underlying cell's contents cannot be set.
    if (this.engine.isItPossibleToSetCellContents(engineTargetRange) === false) {
        return false;
    }
    const fillRangeData = this.engine.getFillRangeData(engineSourceRange, engineTargetRange);
    const { row: sourceStartRow, col: sourceStartColumn } = engineSourceRange.start;
    const { row: sourceEndRow, col: sourceEndColumn } = engineSourceRange.end;
    const populationRowLength = sourceEndRow - sourceStartRow + 1;
    const populationColumnLength = sourceEndColumn - sourceStartColumn + 1;
    for(let populatedRowIndex = 0; populatedRowIndex < fillRangeData.length; populatedRowIndex += 1){
        for(let populatedColumnIndex = 0; populatedColumnIndex < fillRangeData[populatedRowIndex].length; populatedColumnIndex += 1){
            const populatedValue = fillRangeData[populatedRowIndex][populatedColumnIndex];
            const sourceRow = sourceStartRow + populatedRowIndex % populationRowLength;
            const sourceColumn = sourceStartColumn + populatedColumnIndex % populationColumnLength;
            const sourceCellMeta = this.hot.getCellMeta(sourceRow, sourceColumn);
            if ((0, _utils.isDate)(populatedValue, sourceCellMeta.type)) {
                if (populatedValue.startsWith('\'')) {
                    // Populating values on HOT side without apostrophe.
                    fillRangeData[populatedRowIndex][populatedColumnIndex] = populatedValue.slice(1);
                } else if (this.isFormulaCellType(sourceRow, sourceColumn, this.sheetId) === false) {
                    // Populating date in proper format, coming from the source cell.
                    fillRangeData[populatedRowIndex][populatedColumnIndex] = (0, _utils.getDateInHotFormat)(populatedValue, sourceCellMeta.dateFormat);
                }
            }
        }
    }
    return fillRangeData;
}
function onBeforeLoadData(sourceData, initialLoad, source = '') {
    if (source.includes((0, _string.toUpperCaseFirst)(PLUGIN_KEY))) {
        return;
    }
    // This flag needs to be defined, because not passing data to HOT results in HOT auto-generating a `null`-filled
    // initial dataset.
    _class_private_field_set(this, _hotWasInitializedWithEmptyData, (0, _mixed.isUndefined)(this.hot.getSettings().data));
}
function onAfterCellMetaReset() {
    if (_class_private_field_get(this, _hotWasInitializedWithEmptyData)) {
        this.switchSheet(this.sheetName);
        return;
    }
    const sourceDataArray = _class_private_method_get(this, _getProcessedSourceDataArray, getProcessedSourceDataArray).call(this);
    sourceDataArray.forEach((rowData, rowIndex)=>{
        rowData.forEach((cellValue, columnIndex)=>{
            const cellMeta = this.hot.getCellMeta(rowIndex, columnIndex, {
                skipMetaExtension: true
            });
            const dateFormat = cellMeta.dateFormat;
            if ((0, _utils.isDate)(cellValue, cellMeta.type)) {
                if ((0, _utils.isDateValid)(cellValue, dateFormat)) {
                    // Rewriting date in HOT format to HF format.
                    sourceDataArray[rowIndex][columnIndex] = (0, _utils.getDateInHfFormat)(cellValue, dateFormat);
                } else if (!cellValue.startsWith('=')) {
                    // Escaping value from date parsing using "'" sign (HF feature).
                    sourceDataArray[rowIndex][columnIndex] = `'${cellValue}`;
                }
            }
        });
    });
    _class_private_field_set(this, _internalOperationPending, true);
    const dependentCells = this.engine.setSheetContent(this.sheetId, sourceDataArray);
    this.indexSyncer.setupSyncEndpoint(this.engine, this.sheetId);
    this.renderDependentSheets(dependentCells);
    _class_private_field_set(this, _internalOperationPending, false);
}
function onAfterLoadData(sourceData, initialLoad, source = '') {
    if (source.includes((0, _string.toUpperCaseFirst)(PLUGIN_KEY))) {
        return;
    }
    const sheetName = (0, _register.setupSheet)(this.engine, this.hot.getSettings()[PLUGIN_KEY].sheetName);
    _class_private_method_get(this, _updateSheetNameAndSheetId, updateSheetNameAndSheetId).call(this, sheetName);
    if (source === 'updateSettings') {
        // For performance reasons, the initialization will be done in afterCellMetaReset hook
        return;
    }
    if (!_class_private_field_get(this, _hotWasInitializedWithEmptyData)) {
        const sourceDataArray = _class_private_method_get(this, _getProcessedSourceDataArray, getProcessedSourceDataArray).call(this);
        if (this.engine.isItPossibleToReplaceSheetContent(this.sheetId, sourceDataArray)) {
            _class_private_field_set(this, _internalOperationPending, true);
            const dependentCells = this.engine.setSheetContent(this.sheetId, sourceDataArray);
            this.indexSyncer.setupSyncEndpoint(this.engine, this.sheetId);
            this.renderDependentSheets(dependentCells);
            _class_private_field_set(this, _internalOperationPending, false);
        }
    } else {
        this.switchSheet(this.sheetName);
    }
}
function onModifyData(visualRow, visualColumn, valueHolder, ioMode) {
    if (ioMode !== 'get' || _class_private_field_get(this, _internalOperationPending) || this.sheetName === null || !this.engine.doesSheetExist(this.sheetName)) {
        return;
    }
    if (visualRow === null || visualColumn === null) {
        return;
    }
    const cellType = this.getCellType(visualRow, visualColumn);
    if (cellType === 'VALUE' || cellType === 'EMPTY') {
        valueHolder.value = (0, _utils.unescapeFormulaExpression)(valueHolder.value);
        return;
    }
    const address = {
        row: this.rowAxisSyncer.getHfIndexFromVisualIndex(visualRow),
        col: this.columnAxisSyncer.getHfIndexFromVisualIndex(visualColumn),
        sheet: this.sheetId
    };
    let cellValue = this.engine.getCellValue(address); // Date as an integer (Excel like date).
    const cellMeta = this.hot.getCellMeta(visualRow, visualColumn, {
        skipMetaExtension: true
    });
    if (cellMeta.type === 'date' && (0, _number.isNumeric)(cellValue)) {
        cellValue = (0, _utils.getDateFromExcelDate)(cellValue, cellMeta.dateFormat);
    }
    // If `cellValue` is an object it is expected to be an error
    valueHolder.value = typeof cellValue === 'object' && cellValue !== null ? cellValue.value : cellValue;
}
function onModifySourceData(row, columnOrProp, valueHolder, ioMode) {
    if (ioMode !== 'get' || _class_private_field_get(this, _internalOperationPending) || this.sheetName === null || !this.engine.doesSheetExist(this.sheetName)) {
        return;
    }
    const visualRow = this.hot.toVisualRow(row);
    const visualColumn = this.hot.propToCol(columnOrProp);
    if (visualRow === null || visualColumn === null) {
        return;
    }
    const cellType = this.getCellType(visualRow, visualColumn);
    if (cellType === 'VALUE' || cellType === 'EMPTY') {
        return;
    }
    const dimensions = this.engine.getSheetDimensions(this.engine.getSheetId(this.sheetName));
    // Don't actually change the source data if HyperFormula is not
    // initialized yet. This is done to allow the `afterLoadData` hook to
    // load the existing source data with `Handsontable#getSourceDataArray`
    // properly.
    if (dimensions.width === 0 && dimensions.height === 0) {
        return;
    }
    const address = {
        row: this.rowAxisSyncer.getHfIndexFromVisualIndex(visualRow),
        col: this.columnAxisSyncer.getHfIndexFromVisualIndex(visualColumn),
        sheet: this.sheetId
    };
    valueHolder.value = this.engine.getCellSerialized(address);
}
function onAfterSetDataAtCell(changes, source) {
    if (isBlockedSource(source) || changes.length === 0) {
        return;
    }
    const outOfBoundsChanges = [];
    const changedCells = [];
    const dependentCells = this.engine.batch(()=>{
        changes.forEach(([visualRow, prop, , newValue])=>{
            const visualColumn = this.hot.propToCol(prop);
            const physicalRow = this.hot.toPhysicalRow(visualRow);
            const physicalColumn = this.hot.toPhysicalColumn(visualColumn);
            const address = {
                row: this.rowAxisSyncer.getHfIndexFromVisualIndex(visualRow),
                col: this.columnAxisSyncer.getHfIndexFromVisualIndex(visualColumn),
                sheet: this.sheetId
            };
            newValue = _class_private_method_get(this, _getValueGetterValue, getValueGetterValue).call(this, physicalRow, physicalColumn, newValue);
            if (physicalRow !== null && physicalColumn !== null) {
                this.syncChangeWithEngine(visualRow, visualColumn, newValue);
            } else {
                outOfBoundsChanges.push([
                    visualRow,
                    visualColumn,
                    newValue
                ]);
            }
            changedCells.push({
                address
            });
        });
    });
    if (outOfBoundsChanges.length) {
        // Workaround for rows/columns being created two times (by HOT and the engine).
        // (unfortunately, this requires an extra re-render)
        this.hot.addHookOnce('afterChange', ()=>{
            const outOfBoundsDependentCells = this.engine.batch(()=>{
                outOfBoundsChanges.forEach(([row, column, newValue])=>{
                    this.syncChangeWithEngine(row, column, newValue);
                });
            });
            this.renderDependentSheets(outOfBoundsDependentCells, true);
        });
    }
    this.renderDependentSheets(dependentCells);
    this.validateDependentCells(dependentCells, changedCells);
}
function onAfterSetSourceDataAtCell(changes, source) {
    if (isBlockedSource(source)) {
        return;
    }
    const dependentCells = [];
    const changedCells = [];
    changes.forEach(([visualRow, prop, , newValue])=>{
        const visualColumn = this.hot.propToCol(prop);
        if (!(0, _number.isNumeric)(visualColumn)) {
            return;
        }
        const address = {
            row: this.rowAxisSyncer.getHfIndexFromVisualIndex(visualRow),
            col: this.columnAxisSyncer.getHfIndexFromVisualIndex(visualColumn),
            sheet: this.sheetId
        };
        if (!this.engine.isItPossibleToSetCellContents(address)) {
            (0, _console.warn)(`Not possible to set source cell data at ${JSON.stringify(address)}`);
            return;
        }
        newValue = (0, _utils.normalizeValueForFormulaEngine)(newValue);
        changedCells.push({
            address
        });
        dependentCells.push(...this.engine.setCellContents(address, newValue));
    });
    this.renderDependentSheets(dependentCells);
    this.validateDependentCells(dependentCells, changedCells);
}
function onBeforeCreateRow(visualRow, amount) {
    let hfRowIndex = this.rowAxisSyncer.getHfIndexFromVisualIndex(visualRow);
    if (visualRow >= this.hot.countRows()) {
        hfRowIndex = visualRow; // Row beyond the table boundaries.
    }
    if (this.sheetId === null || !this.engine.doesSheetExist(this.sheetName) || !this.engine.isItPossibleToAddRows(this.sheetId, [
        hfRowIndex,
        amount
    ])) {
        return false;
    }
}
function onBeforeCreateCol(visualColumn, amount) {
    let hfColumnIndex = this.columnAxisSyncer.getHfIndexFromVisualIndex(visualColumn);
    if (visualColumn >= this.hot.countCols()) {
        hfColumnIndex = visualColumn; // Column beyond the table boundaries.
    }
    if (this.sheetId === null || !this.engine.doesSheetExist(this.sheetName) || !this.engine.isItPossibleToAddColumns(this.sheetId, [
        hfColumnIndex,
        amount
    ])) {
        return false;
    }
}
function onBeforeRemoveRow(row, amount, physicalRows) {
    const hfRows = this.rowAxisSyncer.setRemovedHfIndexes(physicalRows);
    const possible = hfRows.every((hfRow)=>{
        return this.engine.isItPossibleToRemoveRows(this.sheetId, [
            hfRow,
            1
        ]);
    });
    return possible === false ? false : undefined;
}
function onBeforeRemoveCol(col, amount, physicalColumns) {
    const hfColumns = this.columnAxisSyncer.setRemovedHfIndexes(physicalColumns);
    const possible = hfColumns.every((hfColumn)=>{
        return this.engine.isItPossibleToRemoveColumns(this.sheetId, [
            hfColumn,
            1
        ]);
    });
    return possible === false ? false : undefined;
}
function onAfterCreateRow(visualRow, amount, source) {
    if (isBlockedSource(source)) {
        return;
    }
    const changes = this.engine.addRows(this.sheetId, [
        this.rowAxisSyncer.getHfIndexFromVisualIndex(visualRow),
        amount
    ]);
    this.renderDependentSheets(changes);
}
function onAfterCreateCol(visualColumn, amount, source) {
    if (isBlockedSource(source)) {
        return;
    }
    const changes = this.engine.addColumns(this.sheetId, [
        this.columnAxisSyncer.getHfIndexFromVisualIndex(visualColumn),
        amount
    ]);
    this.renderDependentSheets(changes);
}
function onAfterRemoveRow(row, amount, physicalRows, source) {
    if (isBlockedSource(source)) {
        return;
    }
    const descendingHfRows = this.rowAxisSyncer.getRemovedHfIndexes().sort((a, b)=>b - a); // sort numeric values descending
    const changes = this.engine.batch(()=>{
        descendingHfRows.forEach((hfRow)=>{
            this.engine.removeRows(this.sheetId, [
                hfRow,
                1
            ]);
        });
    });
    this.renderDependentSheets(changes);
}
function onAfterRemoveCol(col, amount, physicalColumns, source) {
    if (isBlockedSource(source)) {
        return;
    }
    const descendingHfColumns = this.columnAxisSyncer.getRemovedHfIndexes().sort((a, b)=>b - a); // sort numeric values descending
    const changes = this.engine.batch(()=>{
        descendingHfColumns.forEach((hfColumn)=>{
            this.engine.removeColumns(this.sheetId, [
                hfColumn,
                1
            ]);
        });
    });
    this.renderDependentSheets(changes);
}
function onAfterDetachChild(parent, element, finalElementRowIndex) {
    _class_private_field_set(this, _internalOperationPending, true);
    const rowsData = _class_private_method_get(this, _getProcessedSourceDataArray, getProcessedSourceDataArray).call(this, finalElementRowIndex, 0, finalElementRowIndex + (element.__children?.length || 0), this.hot.countSourceCols());
    _class_private_field_set(this, _internalOperationPending, false);
    rowsData.forEach((row, relativeRowIndex)=>{
        row.forEach((value, colIndex)=>{
            this.engine.setCellContents({
                col: colIndex,
                row: finalElementRowIndex + relativeRowIndex,
                sheet: this.sheetId
            }, [
                [
                    value
                ]
            ]);
        });
    });
}
function onEngineValuesUpdated(changes) {
    this.hot.runHooks('afterFormulasValuesUpdate', changes);
}
function onEngineNamedExpressionsAdded(namedExpressionName, changes) {
    this.hot.runHooks('afterNamedExpressionAdded', namedExpressionName, changes);
}
function onEngineNamedExpressionsRemoved(namedExpressionName, changes) {
    this.hot.runHooks('afterNamedExpressionRemoved', namedExpressionName, changes);
}
function onEngineSheetAdded(addedSheetDisplayName) {
    this.hot.runHooks('afterSheetAdded', addedSheetDisplayName);
}
function onEngineSheetRenamed(oldDisplayName, newDisplayName) {
    _class_private_method_get(this, _updateSheetNameAndSheetId, updateSheetNameAndSheetId).call(this, newDisplayName);
    this.hot.runHooks('afterSheetRenamed', oldDisplayName, newDisplayName);
}
function onEngineSheetRemoved(removedSheetDisplayName, changes) {
    this.hot.runHooks('afterSheetRemoved', removedSheetDisplayName, changes);
}
