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;
}
import { toUpperCaseFirst } from '../../../helpers/string.mjs';
import { getMoves } from '../../../helpers/moves.mjs';
var /**
   * The axis for which the actions are performed.
   *
   * @private
   * @type {'row'|'column'}
   */ _axis = /*#__PURE__*/ new WeakMap(), /**
   * Reference to index mapper.
   *
   * @private
   * @type {IndexMapper}
   */ _indexMapper = /*#__PURE__*/ new WeakMap(), /**
   * The index synchronizer for both axis (is storing some more general information).
   *
   * @private
   * @type {IndexSyncer}
   */ _indexSyncer = /*#__PURE__*/ new WeakMap(), /**
   * Sequence of physical indexes stored for watching changes and calculating some transformations.
   *
   * @private
   * @type {Array<number>}
   */ _indexesSequence = /*#__PURE__*/ new WeakMap(), /**
   * List of moved HF indexes, stored before performing move on HOT to calculate transformation needed on HF's engine.
   *
   * @private
   * @type {Array<number>}
   */ _movedIndexes = /*#__PURE__*/ new WeakMap(), /**
   * Final HF's place where to move indexes, stored before performing move on HOT to calculate transformation needed on HF's engine.
   *
   * @private
   * @type {number|undefined}
   */ _finalIndex = /*#__PURE__*/ new WeakMap(), /**
   * List of removed HF indexes, stored before performing removal on HOT to calculate transformation needed on HF's engine.
   *
   * @private
   * @type {Array<number>}
   */ _removedIndexes = /*#__PURE__*/ new WeakMap();
/**
 * @private
 * @class IndexSyncer
 * @description
 *
 * Indexes synchronizer responsible for providing logic for particular axis. It respects an idea to represent trimmed
 * elements in HF's engine to perform formulas calculations on them. It also provides method for translation from visual
 * row/column indexes to HF's row/column indexes.
 */ class AxisSyncer {
    /**
   * Sets removed HF indexes (it should be done right before performing move on HOT).
   *
   * @param {Array<number>} removedIndexes List of removed physical indexes.
   * @returns {Array<number>} List of removed visual indexes.
   */ setRemovedHfIndexes(removedIndexes) {
        _class_private_field_set(this, _removedIndexes, removedIndexes.map((physicalIndex)=>{
            const visualIndex = _class_private_field_get(this, _indexMapper).getVisualFromPhysicalIndex(physicalIndex);
            return this.getHfIndexFromVisualIndex(visualIndex);
        }));
        return _class_private_field_get(this, _removedIndexes);
    }
    /**
   * Gets removed HF indexes (right before performing removal on HOT).
   *
   * @returns {Array<number>} List of removed HF indexes.
   */ getRemovedHfIndexes() {
        return _class_private_field_get(this, _removedIndexes);
    }
    /**
   * Gets corresponding HyperFormula index for particular visual index. It's respecting the idea that HF's engine
   * is fed also with trimmed indexes (business requirements for formula result calculation also for trimmed elements).
   *
   * @param {number} visualIndex Visual index.
   * @returns {number}
   */ getHfIndexFromVisualIndex(visualIndex) {
        const indexesSequence = _class_private_field_get(this, _indexMapper).getIndexesSequence();
        const notTrimmedIndexes = _class_private_field_get(this, _indexMapper).getNotTrimmedIndexes();
        // Optimization:
        // notTrimmedIndexes is a subset of indexesSequence,
        // so for every x indexesSequence.indexOf(x) is always >= notTrimmedIndexes.indexOf(x)
        return indexesSequence.indexOf(notTrimmedIndexes[visualIndex], visualIndex);
    }
    /**
   * Synchronizes moves done on HOT to HF engine (based on previously calculated positions).
   *
   * @private
   * @param {Array<{from: number, to: number}>} moves Calculated HF's move positions.
   */ syncMoves(moves) {
        const NUMBER_OF_MOVED_INDEXES = 1;
        const SYNC_MOVE_METHOD_NAME = `move${toUpperCaseFirst(_class_private_field_get(this, _axis))}s`;
        _class_private_field_get(this, _indexSyncer).getEngine().batch(()=>{
            moves.forEach((move)=>{
                const moveToTheSamePosition = move.from !== move.to;
                // Moving from left to right (or top to bottom) to a line (drop index) right after already moved element.
                const anotherMoveWithoutEffect = move.from + 1 !== move.to;
                if (moveToTheSamePosition && anotherMoveWithoutEffect) {
                    _class_private_field_get(this, _indexSyncer).getEngine()[SYNC_MOVE_METHOD_NAME](_class_private_field_get(this, _indexSyncer).getSheetId(), move.from, NUMBER_OF_MOVED_INDEXES, move.to);
                }
            });
        });
    }
    /**
   * Stores information about performed HOT moves for purpose of calculating where to move HF elements.
   *
   * @param {Array<number>} movedVisualIndexes Sequence of moved visual indexes for certain axis.
   * @param {number} visualFinalIndex Final visual place where to move HOT indexes.
   * @param {boolean} movePossible Indicates if it's possible to move HOT indexes to the desired position.
   */ storeMovesInformation(movedVisualIndexes, visualFinalIndex, movePossible) {
        if (movePossible === false) {
            return;
        }
        _class_private_field_set(this, _movedIndexes, movedVisualIndexes.map((index)=>this.getHfIndexFromVisualIndex(index)));
        _class_private_field_set(this, _finalIndex, this.getHfIndexFromVisualIndex(visualFinalIndex));
    }
    /**
   * Calculating where to move HF elements and performing already calculated moves.
   *
   * @param {boolean} movePossible Indicates if it was possible to move HOT indexes to the desired position.
   * @param {boolean} orderChanged Indicates if order of HOT indexes was changed by move.
   */ calculateAndSyncMoves(movePossible, orderChanged) {
        if (_class_private_field_get(this, _indexSyncer).isPerformingUndoRedo()) {
            return;
        }
        if (movePossible === false || orderChanged === false) {
            return;
        }
        const calculatedMoves = getMoves(_class_private_field_get(this, _movedIndexes), _class_private_field_get(this, _finalIndex), _class_private_field_get(this, _indexMapper).getNumberOfIndexes());
        if (_class_private_field_get(this, _indexSyncer).getSheetId() === null) {
            _class_private_field_get(this, _indexSyncer).getPostponeAction(()=>this.syncMoves(calculatedMoves));
        } else {
            this.syncMoves(calculatedMoves);
        }
    }
    /**
   * Gets callback for hook triggered after performing change of indexes order.
   *
   * @returns {Function}
   */ getIndexesChangeSyncMethod() {
        const SYNC_ORDER_CHANGE_METHOD_NAME = `set${toUpperCaseFirst(_class_private_field_get(this, _axis))}Order`;
        return (source)=>{
            if (_class_private_field_get(this, _indexSyncer).isPerformingUndoRedo()) {
                return;
            }
            const newSequence = _class_private_field_get(this, _indexMapper).getIndexesSequence();
            if (source === 'update' && newSequence.length > 0) {
                const relativeTransformation = _class_private_field_get(this, _indexesSequence).map((index)=>newSequence.indexOf(index));
                const sheetDimensions = _class_private_field_get(this, _indexSyncer).getEngine().getSheetDimensions(_class_private_field_get(this, _indexSyncer).getSheetId());
                let sizeForAxis;
                if (_class_private_field_get(this, _axis) === 'row') {
                    sizeForAxis = sheetDimensions.height;
                } else {
                    sizeForAxis = sheetDimensions.width;
                }
                const numberOfReorganisedIndexes = relativeTransformation.length;
                // Sheet dimension can be changed by HF's engine for purpose of calculating values. It extends dependency
                // graph to calculate values outside of a defined dataset. This part of code could be removed after resolving
                // feature request from HF issue board (handsontable/hyperformula#1179).
                for(let i = numberOfReorganisedIndexes; i < sizeForAxis; i += 1){
                    relativeTransformation.push(i);
                }
                _class_private_field_get(this, _indexSyncer).getEngine()[SYNC_ORDER_CHANGE_METHOD_NAME](_class_private_field_get(this, _indexSyncer).getSheetId(), relativeTransformation);
            }
            _class_private_field_set(this, _indexesSequence, newSequence);
        };
    }
    /**
   * Initialize the AxisSyncer.
   */ init() {
        _class_private_field_set(this, _indexesSequence, _class_private_field_get(this, _indexMapper).getIndexesSequence());
    }
    constructor(axis, indexMapper, indexSyncer){
        _class_private_field_init(this, _axis, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _indexMapper, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _indexSyncer, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _indexesSequence, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _movedIndexes, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _finalIndex, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _removedIndexes, {
            writable: true,
            value: void 0
        });
        _class_private_field_set(this, _indexesSequence, []);
        _class_private_field_set(this, _movedIndexes, []);
        _class_private_field_set(this, _removedIndexes, []);
        _class_private_field_set(this, _axis, axis);
        _class_private_field_set(this, _indexMapper, indexMapper);
        _class_private_field_set(this, _indexSyncer, indexSyncer);
    }
}
export default AxisSyncer;
