"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "StretchCalculator", {
    enumerable: true,
    get: function() {
        return StretchCalculator;
    }
});
const _src = require("../../3rdparty/walkontable/src");
const _element = require("../../helpers/dom/element");
const _all = require("./strategies/all");
const _last = require("./strategies/last");
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);
}
const STRETCH_WIDTH_MAP_NAME = 'stretchColumns';
var /**
   * The Handsontable instance.
   *
   * @type {Core}
   */ _hot = /*#__PURE__*/ new WeakMap(), /**
   * The map that stores the calculated column widths.
   *
   * @type {IndexToValueMap}
   */ _widthsMap = /*#__PURE__*/ new WeakMap(), /**
   * The map that stores the available stretch strategies.
   *
   * @type {Map<string, StretchAllStrategy | StretchLastStrategy>}
   */ _stretchStrategies = /*#__PURE__*/ new WeakMap(), /**
   * The active stretch mode.
   *
   * @type {'all' | 'last' | 'none'}
   */ _activeStrategy = /*#__PURE__*/ new WeakMap(), /**
   * Checks if the vertical scrollbar will appear. Based on the current data and viewport size
   * the method calculates if the vertical scrollbar will appear after the table is rendered.
   * The method is a workaround for the issue in the Walkontable that returns unstable viewport
   * size.
   *
   * @returns {boolean}
   */ _willVerticalScrollAppear = /*#__PURE__*/ new WeakSet(), /**
   * Gets the column width from the Handsontable API without logic related to stretching.
   *
   * @param {number} columnVisualIndex Column visual index.
   * @returns {number}
   */ _getWidthWithoutStretching = /*#__PURE__*/ new WeakSet(), /**
   * Executes the hook that allows to overwrite the column width.
   *
   * @param {number} columnWidth The column width.
   * @param {number} columnVisualIndex Column visual index.
   * @returns {number}
   */ _overwriteColumnWidthFn = /*#__PURE__*/ new WeakSet();
class StretchCalculator {
    /**
   * Sets the active stretch strategy.
   *
   * @param {'all' | 'last' | 'none'} strategyName The stretch strategy to use.
   */ useStrategy(strategyName) {
        _class_private_field_set(this, _activeStrategy, _class_private_field_get(this, _stretchStrategies).has(strategyName) ? strategyName : 'none');
    }
    /**
   * Recalculates the column widths.
   */ refreshStretching() {
        if (_class_private_field_get(this, _activeStrategy) === 'none') {
            _class_private_field_get(this, _widthsMap).clear();
            return;
        }
        _class_private_field_get(this, _hot).batchExecution(()=>{
            _class_private_field_get(this, _widthsMap).clear();
            const stretchStrategy = _class_private_field_get(this, _stretchStrategies).get(_class_private_field_get(this, _activeStrategy));
            const view = _class_private_field_get(this, _hot).view;
            let viewportWidth = view.getViewportWidth();
            if (_class_private_method_get(this, _willVerticalScrollAppear, willVerticalScrollAppear).call(this)) {
                viewportWidth -= (0, _element.getScrollbarWidth)(_class_private_field_get(this, _hot).rootDocument);
            }
            stretchStrategy.prepare({
                viewportWidth
            });
            for(let columnIndex = 0; columnIndex < _class_private_field_get(this, _hot).countCols(); columnIndex++){
                if (!_class_private_field_get(this, _hot).columnIndexMapper.isHidden(_class_private_field_get(this, _hot).toPhysicalColumn(columnIndex))) {
                    stretchStrategy.setColumnBaseWidth(columnIndex, _class_private_method_get(this, _getWidthWithoutStretching, getWidthWithoutStretching).call(this, columnIndex));
                }
            }
            stretchStrategy.calculate();
            stretchStrategy.getWidths().forEach(([columnIndex, width])=>{
                _class_private_field_get(this, _widthsMap).setValueAtIndex(_class_private_field_get(this, _hot).toPhysicalColumn(columnIndex), width);
            });
        }, true);
    }
    /**
   * Gets the calculated column width.
   *
   * @param {number} columnVisualIndex Column visual index.
   * @returns {number | null}
   */ getStretchedWidth(columnVisualIndex) {
        return _class_private_field_get(this, _widthsMap).getValueAtIndex(_class_private_field_get(this, _hot).toPhysicalColumn(columnVisualIndex));
    }
    constructor(hotInstance){
        _class_private_method_init(this, _willVerticalScrollAppear);
        _class_private_method_init(this, _getWidthWithoutStretching);
        _class_private_method_init(this, _overwriteColumnWidthFn);
        _class_private_field_init(this, _hot, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _widthsMap, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _stretchStrategies, {
            writable: true,
            value: void 0
        });
        _class_private_field_init(this, _activeStrategy, {
            writable: true,
            value: void 0
        });
        _class_private_field_set(this, _stretchStrategies, new Map([
            [
                'all',
                new _all.StretchAllStrategy(_class_private_method_get(this, _overwriteColumnWidthFn, overwriteColumnWidthFn).bind(this))
            ],
            [
                'last',
                new _last.StretchLastStrategy(_class_private_method_get(this, _overwriteColumnWidthFn, overwriteColumnWidthFn).bind(this))
            ]
        ]));
        _class_private_field_set(this, _activeStrategy, 'none');
        _class_private_field_set(this, _hot, hotInstance);
        _class_private_field_set(this, _widthsMap, _class_private_field_get(this, _hot).columnIndexMapper.createAndRegisterIndexMap(STRETCH_WIDTH_MAP_NAME, 'physicalIndexToValue'));
    }
}
function willVerticalScrollAppear() {
    const { view, stylesHandler } = _class_private_field_get(this, _hot);
    if (view.isVerticallyScrollableByWindow()) {
        return false;
    }
    const viewportHeight = view.getViewportHeight();
    const totalRows = _class_private_field_get(this, _hot).countRows();
    const defaultRowHeight = stylesHandler.getDefaultRowHeight();
    let totalHeight = 0;
    let hasVerticalScroll = false;
    for(let row = 0; row < totalRows; row++){
        if (_class_private_field_get(this, _hot).rowIndexMapper.isHidden(_class_private_field_get(this, _hot).toPhysicalRow(row))) {
            continue;
        }
        totalHeight += _class_private_field_get(this, _hot).getRowHeight(row) ?? defaultRowHeight;
        if (totalHeight > viewportHeight) {
            hasVerticalScroll = true;
            break;
        }
    }
    return hasVerticalScroll;
}
function getWidthWithoutStretching(columnVisualIndex) {
    return _class_private_field_get(this, _hot).getColWidth(columnVisualIndex, 'StretchColumns') ?? _src.DEFAULT_COLUMN_WIDTH;
}
function overwriteColumnWidthFn(columnWidth, columnVisualIndex) {
    return _class_private_field_get(this, _hot).runHooks('beforeStretchingColumnWidth', columnWidth, columnVisualIndex);
}
