/**
 * DevExtreme (esm/__internal/grids/grid_core/views/m_rows_view.js)
 * Version: 23.2.6 (build 24140-0112)
 * Build date: Sun May 19 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
import _extends from "@babel/runtime/helpers/esm/extends";
import $ from "../../../../core/renderer";
import browser from "../../../../core/utils/browser";
import {
    deferRender,
    deferUpdate
} from "../../../../core/utils/common";
import {
    compileGetter
} from "../../../../core/utils/data";
import {
    extend
} from "../../../../core/utils/extend";
import {
    each
} from "../../../../core/utils/iterator";
import {
    getBoundingRect,
    getDefaultAlignment
} from "../../../../core/utils/position";
import {
    getHeight,
    getOuterHeight,
    getWidth
} from "../../../../core/utils/size";
import {
    isEmpty
} from "../../../../core/utils/string";
import {
    setHeight
} from "../../../../core/utils/style";
import {
    isDefined,
    isNumeric,
    isString
} from "../../../../core/utils/type";
import {
    getWindow,
    hasWindow
} from "../../../../core/utils/window";
import eventsEngine from "../../../../events/core/events_engine";
import {
    removeEvent
} from "../../../../events/remove";
import messageLocalization from "../../../../localization/message";
import Scrollable from "../../../../ui/scroll_view/ui.scrollable";
import gridCoreUtils from "../m_utils";
import {
    ColumnsView
} from "./m_columns_view";
var ROWS_VIEW_CLASS = "rowsview";
var CONTENT_CLASS = "content";
var NOWRAP_CLASS = "nowrap";
var GROUP_ROW_CLASS = "dx-group-row";
var GROUP_CELL_CLASS = "dx-group-cell";
var DATA_ROW_CLASS = "dx-data-row";
var FREE_SPACE_CLASS = "dx-freespace-row";
var ROW_LINES_CLASS = "dx-row-lines";
var COLUMN_LINES_CLASS = "dx-column-lines";
var ROW_ALTERNATION_CLASS = "dx-row-alt";
var LAST_ROW_BORDER = "dx-last-row-border";
var EMPTY_CLASS = "dx-empty";
var ROW_INSERTED_ANIMATION_CLASS = "row-inserted-animation";
var LOADPANEL_HIDE_TIMEOUT = 200;

function getMaxHorizontalScrollOffset(scrollable) {
    return scrollable ? Math.round(scrollable.scrollWidth() - scrollable.clientWidth()) : 0
}

function isGroupRow(_ref) {
    var {
        rowType: rowType,
        column: column
    } = _ref;
    return "group" === rowType && isDefined(column.groupIndex) && !column.showWhenGrouped && !column.command
}

function setWatcher(_ref2) {
    var {
        element: element,
        watch: watch,
        getter: getter,
        callBack: callBack
    } = _ref2;
    if (watch) {
        var dispose = watch(getter, callBack);
        eventsEngine.on(element, removeEvent, dispose)
    }
}
var defaultCellTemplate = function($container, options) {
    var isDataTextEmpty = isEmpty(options.text) && "data" === options.rowType;
    var {
        text: text
    } = options;
    var container = $container.get(0);
    if (isDataTextEmpty) {
        gridCoreUtils.setEmptyText($container)
    } else if (options.column.encodeHtml) {
        container.textContent = text
    } else {
        container.innerHTML = text
    }
};
var getScrollableBottomPadding = function(that) {
    var scrollable = that.getScrollable();
    return scrollable ? Math.ceil(parseFloat($(scrollable.content()).css("paddingBottom"))) : 0
};
export class RowsView extends ColumnsView {
    init() {
        super.init();
        this._editingController = this.getController("editing");
        this._resizingController = this.getController("resizing");
        this._columnsResizerController = this.getController("columnsResizer");
        this._focusController = this.getController("focus");
        this._keyboardNavigationController = this.getController("keyboardNavigation");
        this._validatingController = this.getController("validating");
        this._errorHandlingController = this.getController("errorHandling");
        this._columnHeadersView = this.getView("columnHeadersView");
        this._rowHeight = 0;
        this._scrollTop = 0;
        this._scrollLeft = -1;
        this._scrollRight = 0;
        this._hasHeight = void 0;
        this._contentChanges = [];
        this._dataController.loadingChanged.add((isLoading, messageText) => {
            this.setLoading(isLoading, messageText)
        });
        this._dataController.dataSourceChanged.add(() => {
            if (this._scrollLeft >= 0 && !this._dataController.isLoading()) {
                this._handleScroll({
                    component: this.getScrollable(),
                    forceUpdateScrollPosition: true,
                    scrollOffset: {
                        top: this._scrollTop,
                        left: this._scrollLeft
                    }
                })
            }
        })
    }
    _getDefaultTemplate(column) {
        switch (column.command) {
            case "empty":
                return function(container) {
                    container.html("&nbsp;")
                };
            default:
                return defaultCellTemplate
        }
    }
    _getDefaultGroupTemplate(column) {
        var summaryTexts = this.option("summary.texts");
        return function($container, options) {
            var {
                data: data
            } = options;
            var text = "".concat(options.column.caption, ": ").concat(options.text);
            var container = $container.get(0);
            if (options.summaryItems && options.summaryItems.length) {
                text += " ".concat(gridCoreUtils.getGroupRowSummaryText(options.summaryItems, summaryTexts))
            }
            if (data) {
                if (options.groupContinuedMessage && options.groupContinuesMessage) {
                    text += " (".concat(options.groupContinuedMessage, ". ").concat(options.groupContinuesMessage, ")")
                } else if (options.groupContinuesMessage) {
                    text += " (".concat(options.groupContinuesMessage, ")")
                } else if (options.groupContinuedMessage) {
                    text += " (".concat(options.groupContinuedMessage, ")")
                }
            }
            if (column.encodeHtml) {
                container.textContent = text
            } else {
                container.innerHTML = text
            }
        }
    }
    _update(change) {}
    _updateCell($cell, options) {
        if (isGroupRow(options)) {
            $cell.addClass(GROUP_CELL_CLASS)
        }
        super._updateCell.apply(this, arguments)
    }
    _getCellTemplate(options) {
        var {
            column: column
        } = options;
        var template;
        if (isGroupRow(options)) {
            template = column.groupCellTemplate || {
                allowRenderToDetachedContainer: true,
                render: this._getDefaultGroupTemplate(column)
            }
        } else if (("data" === options.rowType || column.command) && column.cellTemplate) {
            template = column.cellTemplate
        } else {
            template = {
                allowRenderToDetachedContainer: true,
                render: this._getDefaultTemplate(column)
            }
        }
        return template
    }
    _createRow(row, tag) {
        var $row = super._createRow.apply(this, arguments);
        if (row) {
            var isGroup = "group" === row.rowType;
            var isDataRow = "data" === row.rowType;
            isDataRow && $row.addClass(DATA_ROW_CLASS);
            isDataRow && this.option("showRowLines") && $row.addClass(ROW_LINES_CLASS);
            this.option("showColumnLines") && $row.addClass(COLUMN_LINES_CLASS);
            if (false === row.visible) {
                $row.hide()
            }
            if (isGroup) {
                $row.addClass(GROUP_ROW_CLASS);
                this.setAriaExpandedAttribute($row, row)
            }
        }
        return $row
    }
    _rowPrepared($row, rowOptions, row) {
        if ("data" === rowOptions.rowType) {
            if (this.option("rowAlternationEnabled")) {
                this._isAltRow(row) && $row.addClass(ROW_ALTERNATION_CLASS);
                setWatcher({
                    element: $row.get(0),
                    watch: rowOptions.watch,
                    getter: () => this._isAltRow(row),
                    callBack: value => {
                        $row.toggleClass(ROW_ALTERNATION_CLASS, value)
                    }
                })
            }
            this._setAriaRowIndex(rowOptions, $row);
            setWatcher({
                element: $row.get(0),
                watch: rowOptions.watch,
                getter: () => rowOptions.rowIndex,
                callBack: () => this._setAriaRowIndex(rowOptions, $row)
            })
        }
        super._rowPrepared.apply(this, arguments)
    }
    _setAriaRowIndex(row, $row) {
        if (!$row.is("tr")) {
            return
        }
        var {
            component: component
        } = this;
        var isPagerMode = "standard" === component.option("scrolling.mode") && !gridCoreUtils.isVirtualRowRendering(component);
        var rowIndex = row.rowIndex + 1;
        if (isPagerMode) {
            rowIndex = component.pageIndex() * component.pageSize() + rowIndex
        } else {
            rowIndex += this._dataController.getRowIndexOffset()
        }
        this.setAria("rowindex", rowIndex, $row)
    }
    setAriaExpandedAttribute($row, row) {
        var description = row.isExpanded ? this.localize("dxDataGrid-ariaExpandedRow") : this.localize("dxDataGrid-ariaCollapsedRow");
        this.setAria("roledescription", description, $row)
    }
    _afterRowPrepared(e) {
        var arg = e.args[0];
        var dataController = this._dataController;
        var row = dataController.getVisibleRows()[arg.rowIndex];
        var watch = this.option("integrationOptions.watchMethod");
        if (!arg.data || "data" !== arg.rowType || arg.isNewRow || !this.option("twoWayBindingEnabled") || !watch || !row) {
            return
        }
        var dispose = watch(() => dataController.generateDataValues(arg.data, arg.columns), () => {
            dataController.repaintRows([row.rowIndex], this.option("repaintChangesOnly"))
        }, {
            deep: true,
            skipImmediate: true
        });
        eventsEngine.on(arg.rowElement, removeEvent, dispose)
    }
    _renderScrollable(force) {
        var $element = this.element();
        if (!$element.children().length) {
            $element.append("<div>")
        }
        if (force || !this._loadPanel) {
            this._renderLoadPanel($element, $element.parent(), this._dataController.isLocalStore())
        }
        if ((force || !this.getScrollable()) && this._dataController.isLoaded()) {
            var columns = this.getColumns();
            var allColumnsHasWidth = true;
            for (var i = 0; i < columns.length; i++) {
                if (!columns[i].width && !columns[i].minWidth) {
                    allColumnsHasWidth = false;
                    break
                }
            }
            if (this.option("columnAutoWidth") || this._hasHeight || allColumnsHasWidth || this._columnsController._isColumnFixing()) {
                this._renderScrollableCore($element)
            }
        }
    }
    _handleScroll(e) {
        var rtlEnabled = this.option("rtlEnabled");
        var isNativeScrolling = e.component.option("useNative");
        this._scrollTop = e.scrollOffset.top;
        this._scrollLeft = e.scrollOffset.left;
        var scrollLeft = e.scrollOffset.left;
        if (rtlEnabled) {
            this._scrollRight = getMaxHorizontalScrollOffset(e.component) - this._scrollLeft;
            if (isNativeScrolling) {
                scrollLeft = -this._scrollRight
            }
            if (!this.isScrollbarVisible(true)) {
                this._scrollLeft = -1
            }
        }
        this.scrollChanged.fire(_extends(_extends({}, e.scrollOffset), {
            left: scrollLeft
        }), this.name)
    }
    _renderScrollableCore($element) {
        var dxScrollableOptions = this._createScrollableOptions();
        var scrollHandler = this._handleScroll.bind(this);
        dxScrollableOptions.onScroll = scrollHandler;
        this._scrollable = this._createComponent($element, Scrollable, dxScrollableOptions);
        this._scrollableContainer = this._scrollable && $(this._scrollable.container())
    }
    _renderLoadPanel() {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
            args[_key] = arguments[_key]
        }
        return gridCoreUtils.renderLoadPanel.apply(this, arguments)
    }
    _renderContent(contentElement, tableElement, isFixedTableRendering) {
        contentElement.empty().append(tableElement);
        return this._findContentElement()
    }
    _updateContent(newTableElement, change, isFixedTableRendering) {
        this._contentChanges.push({
            newTableElement: newTableElement,
            change: change,
            isFixedTableRendering: isFixedTableRendering
        });
        return this.waitAsyncTemplates().done(() => {
            var contentChanges = this._contentChanges;
            this._contentChanges = [];
            contentChanges.forEach(_ref3 => {
                var {
                    newTableElement: newTableElement,
                    change: change,
                    isFixedTableRendering: isFixedTableRendering
                } = _ref3;
                var tableElement = this.getTableElement(isFixedTableRendering);
                var contentElement = this._findContentElement(isFixedTableRendering);
                var changeType = null === change || void 0 === change ? void 0 : change.changeType;
                var executors = [];
                var highlightChanges = this.option("highlightChanges");
                var rowInsertedClass = this.addWidgetPrefix(ROW_INSERTED_ANIMATION_CLASS);
                switch (changeType) {
                    case "update":
                        each(change.rowIndices, (index, rowIndex) => {
                            var _a;
                            var $newRowElement = this._getRowElements(newTableElement).eq(index);
                            var dataChangeType = null === (_a = change.changeTypes) || void 0 === _a ? void 0 : _a[index];
                            var item = change.items && change.items[index];
                            executors.push(() => {
                                var _a;
                                var $rowElements = this._getRowElements(tableElement);
                                var $rowElement = $rowElements.eq(rowIndex);
                                switch (dataChangeType) {
                                    case "update":
                                        if (item) {
                                            var columnIndices = null === (_a = change.columnIndices) || void 0 === _a ? void 0 : _a[index];
                                            if (isDefined(item.visible) && item.visible !== $rowElement.is(":visible")) {
                                                $rowElement.toggle(item.visible)
                                            } else if (columnIndices) {
                                                this._updateCells($rowElement, $newRowElement, columnIndices)
                                            } else {
                                                $rowElement.replaceWith($newRowElement)
                                            }
                                        }
                                        break;
                                    case "insert":
                                        if (!$rowElements.length) {
                                            if (tableElement) {
                                                var target = $newRowElement.is("tbody") ? tableElement : tableElement.children("tbody");
                                                $newRowElement.prependTo(target)
                                            }
                                        } else if ($rowElement.length) {
                                            $newRowElement.insertBefore($rowElement)
                                        } else {
                                            $newRowElement.insertAfter($rowElements.last())
                                        }
                                        if (highlightChanges && change.isLiveUpdate) {
                                            $newRowElement.addClass(rowInsertedClass)
                                        }
                                        break;
                                    case "remove":
                                        $rowElement.remove()
                                }
                            })
                        });
                        each(executors, (function() {
                            this()
                        }));
                        newTableElement.remove();
                        break;
                    default:
                        this.setTableElement(newTableElement, isFixedTableRendering);
                        contentElement.addClass(this.addWidgetPrefix(CONTENT_CLASS));
                        this._setGridRole(contentElement);
                        this._renderContent(contentElement, newTableElement, isFixedTableRendering)
                }
            })
        }).fail(() => {
            this._contentChanges = []
        })
    }
    _getGridRoleName() {
        return "grid"
    }
    _setGridRole($element) {
        var _a;
        var hasData = !(null === (_a = this._dataController) || void 0 === _a ? void 0 : _a.isEmpty());
        var gridRoleName = this._getGridRoleName();
        if ((null === $element || void 0 === $element ? void 0 : $element.length) && hasData) {
            this.setAria("role", gridRoleName, $element)
        }
    }
    _createEmptyRow(className, isFixed, height) {
        var $cell;
        var $row = this._createRow();
        var columns = isFixed ? this.getFixedColumns() : this.getColumns();
        $row.addClass(className).toggleClass(COLUMN_LINES_CLASS, this.option("showColumnLines"));
        for (var i = 0; i < columns.length; i++) {
            $cell = this._createCell({
                column: columns[i],
                rowType: "freeSpace",
                columnIndex: i,
                columns: columns
            });
            isNumeric(height) && $cell.css("height", height);
            $row.append($cell)
        }
        this.setAria("role", "presentation", $row);
        return $row
    }
    getFixedColumns() {
        throw new Error("Method not implemented.")
    }
    _appendEmptyRow($table, $emptyRow, location) {
        var $tBodies = this._getBodies($table);
        var isTableContainer = !$tBodies.length || $emptyRow.is("tbody");
        var $container = isTableContainer ? $table : $tBodies;
        if ("top" === location) {
            $container.first().prepend($emptyRow);
            if (isTableContainer) {
                var $colgroup = $container.children("colgroup");
                $container.prepend($colgroup)
            }
        } else {
            $container.last().append($emptyRow)
        }
    }
    _renderFreeSpaceRow($tableElement, change) {
        var $freeSpaceRowElement = this._createEmptyRow(FREE_SPACE_CLASS);
        $freeSpaceRowElement = this._wrapRowIfNeed($tableElement, $freeSpaceRowElement, "refresh" === (null === change || void 0 === change ? void 0 : change.changeType));
        this._appendEmptyRow($tableElement, $freeSpaceRowElement)
    }
    _checkRowKeys(options) {
        var that = this;
        var rows = that._getRows(options);
        var keyExpr = that._dataController.store() && that._dataController.store().key();
        keyExpr && rows.some(row => {
            if ("data" === row.rowType && void 0 === row.key) {
                that._dataController.fireError("E1046", keyExpr);
                return true
            }
            return
        })
    }
    _needUpdateRowHeight(itemsCount) {
        return itemsCount > 0 && !this._rowHeight
    }
    _getRowsHeight($tableElement) {
        $tableElement = $tableElement || this._tableElement;
        var $rowElements = $tableElement.children("tbody").children().not(".dx-virtual-row").not(".".concat(FREE_SPACE_CLASS));
        return $rowElements.toArray().reduce((sum, row) => sum + getBoundingRect(row).height, 0)
    }
    _updateRowHeight() {
        var $tableElement = this.getTableElement();
        var itemsCount = this._dataController.items().length;
        if ($tableElement && this._needUpdateRowHeight(itemsCount)) {
            var rowsHeight = this._getRowsHeight($tableElement);
            this._rowHeight = rowsHeight / itemsCount
        }
    }
    _findContentElement(isFixedTableRendering) {
        var $content = this.element();
        var scrollable = this.getScrollable();
        if ($content) {
            if (scrollable) {
                $content = $(scrollable.content())
            }
            return $content.children().first()
        }
    }
    _getRowElements(tableElement) {
        var $rows = super._getRowElements(tableElement);
        return $rows && $rows.not(".".concat(FREE_SPACE_CLASS))
    }
    _getFreeSpaceRowElements($table) {
        var tableElements = $table || this.getTableElements();
        return tableElements && tableElements.children("tbody").children(".".concat(FREE_SPACE_CLASS))
    }
    _getNoDataText() {
        return this.option("noDataText")
    }
    _rowClick(e) {
        var item = this._dataController.items()[e.rowIndex] || {};
        this.executeAction("onRowClick", extend({
            evaluate(expr) {
                var getter = compileGetter(expr);
                return getter(item.data)
            }
        }, e, item))
    }
    _rowDblClick(e) {
        var item = this._dataController.items()[e.rowIndex] || {};
        this.executeAction("onRowDblClick", extend({}, e, item))
    }
    _getColumnsCountBeforeGroups(columns) {
        for (var i = 0; i < columns.length; i++) {
            if ("groupExpand" === columns[i].type) {
                return i
            }
        }
        return 0
    }
    _getGroupCellOptions(options) {
        var columnsCountBeforeGroups = this._getColumnsCountBeforeGroups(options.columns);
        var columnIndex = (options.row.groupIndex || 0) + columnsCountBeforeGroups;
        return {
            columnIndex: columnIndex,
            colspan: options.columns.length - columnIndex - 1
        }
    }
    _needWrapRow() {
        return super._needWrapRow.apply(this, arguments) || !!this.option("dataRowTemplate")
    }
    _renderCells($row, options) {
        if ("group" === options.row.rowType) {
            this._renderGroupedCells($row, options)
        } else if (options.row.values) {
            super._renderCells($row, options)
        }
    }
    _renderGroupedCells($row, options) {
        var {
            row: row
        } = options;
        var expandColumn;
        var {
            columns: columns
        } = options;
        var {
            rowIndex: rowIndex
        } = row;
        var isExpanded;
        var groupCellOptions = this._getGroupCellOptions(options);
        for (var i = 0; i <= groupCellOptions.columnIndex; i++) {
            if (i === groupCellOptions.columnIndex && columns[i].allowCollapsing && "infinite" !== options.scrollingMode) {
                isExpanded = !!row.isExpanded;
                expandColumn = columns[i]
            } else {
                isExpanded = null;
                expandColumn = {
                    command: "expand",
                    cssClass: columns[i].cssClass
                }
            }
            if (this._needRenderCell(i, options.columnIndices)) {
                this._renderCell($row, {
                    value: isExpanded,
                    row: row,
                    rowIndex: rowIndex,
                    column: expandColumn,
                    columnIndex: i,
                    columnIndices: options.columnIndices,
                    change: options.change
                })
            }
        }
        var groupColumnAlignment = getDefaultAlignment(this.option("rtlEnabled"));
        var groupColumn = extend({}, columns[groupCellOptions.columnIndex], {
            command: null,
            type: null,
            cssClass: null,
            width: null,
            showWhenGrouped: false,
            alignment: groupColumnAlignment
        });
        if (groupCellOptions.colspan > 1) {
            groupColumn.colspan = groupCellOptions.colspan
        }
        if (this._needRenderCell(groupCellOptions.columnIndex + 1, options.columnIndices)) {
            this._renderCell($row, {
                value: row.values[row.groupIndex],
                row: row,
                rowIndex: rowIndex,
                column: groupColumn,
                columnIndex: groupCellOptions.columnIndex + 1,
                columnIndices: options.columnIndices,
                change: options.change
            })
        }
    }
    _renderRows($table, options) {
        var scrollingMode = this.option("scrolling.mode");
        super._renderRows($table, extend({
            scrollingMode: scrollingMode
        }, options));
        this._checkRowKeys(options.change);
        this._renderFreeSpaceRow($table, options.change);
        if (!this._hasHeight) {
            this.updateFreeSpaceRowHeight($table)
        }
    }
    _renderDataRowByTemplate($table, options, dataRowTemplate) {
        var {
            row: row
        } = options;
        var rowOptions = extend({
            columns: options.columns
        }, row);
        var $tbody = this._createRow(row, "tbody");
        $tbody.appendTo($table);
        this.renderTemplate($tbody, dataRowTemplate, rowOptions, true, options.change);
        this._rowPrepared($tbody, rowOptions, options.row)
    }
    _renderRow($table, options) {
        var {
            row: row
        } = options;
        var {
            rowTemplate: rowTemplate
        } = this.option();
        var dataRowTemplate = this.option("dataRowTemplate");
        if ("data" === row.rowType && dataRowTemplate) {
            this._renderDataRowByTemplate($table, options, dataRowTemplate)
        } else if (("data" === row.rowType || "group" === row.rowType) && !isDefined(row.groupIndex) && rowTemplate) {
            this.renderTemplate($table, rowTemplate, extend({
                columns: options.columns
            }, row), true)
        } else {
            super._renderRow($table, options)
        }
    }
    _renderTable(options) {
        var that = this;
        var $table = super._renderTable(options);
        if (!isDefined(that.getTableElement())) {
            that.setTableElement($table);
            that._renderScrollable(true);
            that.resizeCompleted.add((function resizeCompletedHandler() {
                var scrollableInstance = that.getScrollable();
                if (scrollableInstance && that.element().closest(getWindow().document).length) {
                    that.resizeCompleted.remove(resizeCompletedHandler);
                    scrollableInstance._visibilityChanged(true)
                }
            }))
        } else {
            that._renderScrollable()
        }
        return $table
    }
    _createTable() {
        var $table = super._createTable.apply(this, arguments);
        if (this.option().rowTemplate || this.option().dataRowTemplate) {
            $table.appendTo(this.component.$element())
        }
        return $table
    }
    _renderCore(change) {
        var $element = this.element();
        $element.addClass(this.addWidgetPrefix(ROWS_VIEW_CLASS)).toggleClass(this.addWidgetPrefix(NOWRAP_CLASS), !this.option("wordWrapEnabled"));
        $element.toggleClass(EMPTY_CLASS, this._dataController.isEmpty());
        this.setAria("role", "presentation", $element);
        var $table = this._renderTable({
            change: change
        });
        var deferred = this._updateContent($table, change);
        super._renderCore(change);
        this._lastColumnWidths = null;
        return deferred
    }
    _getRows(change) {
        return change && change.items || this._dataController.items()
    }
    _getCellOptions(options) {
        var {
            column: column
        } = options;
        var {
            row: row
        } = options;
        var {
            data: data
        } = row;
        var summaryCells = row && row.summaryCells;
        var {
            value: value
        } = options;
        var displayValue = gridCoreUtils.getDisplayValue(column, value, data, row.rowType);
        var parameters = super._getCellOptions(options);
        parameters.value = value;
        parameters.oldValue = options.oldValue;
        parameters.displayValue = displayValue;
        parameters.row = row;
        parameters.key = row.key;
        parameters.data = data;
        parameters.rowType = row.rowType;
        parameters.values = row.values;
        parameters.text = !column.command ? gridCoreUtils.formatValue(displayValue, column) : "";
        parameters.rowIndex = row.rowIndex;
        parameters.summaryItems = summaryCells && summaryCells[options.columnIndex];
        parameters.resized = column.resizedCallbacks;
        if (isDefined(column.groupIndex) && !column.command) {
            var groupingTextsOptions = this.option("grouping.texts");
            var scrollingMode = this.option("scrolling.mode");
            if ("virtual" !== scrollingMode && "infinite" !== scrollingMode) {
                parameters.groupContinuesMessage = data && data.isContinuationOnNextPage && groupingTextsOptions && groupingTextsOptions.groupContinuesMessage;
                parameters.groupContinuedMessage = data && data.isContinuation && groupingTextsOptions && groupingTextsOptions.groupContinuedMessage
            }
        }
        return parameters
    }
    _setRowsOpacityCore($rows, visibleColumns, columnIndex, value) {
        var columnsController = this._columnsController;
        var columns = columnsController.getColumns();
        var column = columns && columns[columnIndex];
        var columnID = column && column.isBand && column.index;
        each($rows, (rowIndex, row) => {
            if (!$(row).hasClass(GROUP_ROW_CLASS)) {
                for (var i = 0; i < visibleColumns.length; i++) {
                    if (isNumeric(columnID) && columnsController.isParentBandColumn(visibleColumns[i].index, columnID) || visibleColumns[i].index === columnIndex) {
                        $rows.eq(rowIndex).children().eq(i).css({
                            opacity: value
                        });
                        if (!isNumeric(columnID)) {
                            break
                        }
                    }
                }
            }
        })
    }
    _getDevicePixelRatio() {
        return getWindow().devicePixelRatio
    }
    renderNoDataText() {
        return gridCoreUtils.renderNoDataText.apply(this, arguments)
    }
    getCellOptions(rowIndex, columnIdentifier) {
        var rowOptions = this._dataController.items()[rowIndex];
        var cellOptions;
        var column;
        if (rowOptions) {
            if (isString(columnIdentifier)) {
                column = this._columnsController.columnOption(columnIdentifier)
            } else {
                column = this._columnsController.getVisibleColumns()[columnIdentifier]
            }
            if (column) {
                cellOptions = this._getCellOptions({
                    value: column.calculateCellValue(rowOptions.data),
                    rowIndex: rowOptions.rowIndex,
                    row: rowOptions,
                    column: column
                })
            }
        }
        return cellOptions
    }
    getRow(index) {
        if (index >= 0) {
            var rows = this._getRowElements();
            if (rows.length > index) {
                return $(rows[index])
            }
        }
        return
    }
    updateFreeSpaceRowHeight($table) {
        var dataController = this._dataController;
        var itemCount = dataController.items(true).length;
        var contentElement = this._findContentElement();
        var freeSpaceRowElements = this._getFreeSpaceRowElements($table);
        if (freeSpaceRowElements && contentElement && dataController.totalCount() >= 0) {
            var isFreeSpaceRowVisible = false;
            if (itemCount > 0) {
                if (!this._hasHeight) {
                    var freeSpaceRowCount = dataController.pageSize() - itemCount;
                    var scrollingMode = this.option("scrolling.mode");
                    if (freeSpaceRowCount > 0 && dataController.pageCount() > 1 && "virtual" !== scrollingMode && "infinite" !== scrollingMode) {
                        setHeight(freeSpaceRowElements, freeSpaceRowCount * this._rowHeight);
                        isFreeSpaceRowVisible = true
                    }
                    if (!isFreeSpaceRowVisible && $table) {
                        setHeight(freeSpaceRowElements, 0)
                    } else {
                        freeSpaceRowElements.toggle(isFreeSpaceRowVisible)
                    }
                    this._updateLastRowBorder(isFreeSpaceRowVisible)
                } else {
                    freeSpaceRowElements.hide();
                    deferUpdate(() => {
                        var scrollbarWidth = this.getScrollbarWidth(true);
                        var elementHeightWithoutScrollbar = getHeight(this.element()) - scrollbarWidth;
                        var contentHeight = getOuterHeight(contentElement);
                        var showFreeSpaceRow = elementHeightWithoutScrollbar - contentHeight > 0;
                        var rowsHeight = this._getRowsHeight(contentElement.children().first());
                        var $tableElement = $table || this.getTableElements();
                        var borderTopWidth = Math.ceil(parseFloat($tableElement.css("borderTopWidth")));
                        var heightCorrection = this._getHeightCorrection();
                        var resultHeight = elementHeightWithoutScrollbar - rowsHeight - borderTopWidth - heightCorrection;
                        if (showFreeSpaceRow) {
                            deferRender(() => {
                                freeSpaceRowElements.css("height", resultHeight);
                                isFreeSpaceRowVisible = true;
                                freeSpaceRowElements.show()
                            })
                        }
                        deferRender(() => this._updateLastRowBorder(isFreeSpaceRowVisible))
                    })
                }
            } else {
                freeSpaceRowElements.css("height", 0);
                freeSpaceRowElements.show();
                this._updateLastRowBorder(true)
            }
        }
    }
    _getHeightCorrection() {
        var isZoomedWebkit = browser.webkit && this._getDevicePixelRatio() >= 2;
        var isChromeLatest = browser.chrome && browser.version >= 91;
        var hasExtraBorderTop = browser.mozilla && browser.version >= 70 && !this.option("showRowLines");
        return isZoomedWebkit || hasExtraBorderTop || isChromeLatest ? 1 : 0
    }
    _columnOptionChanged(e) {
        var {
            optionNames: optionNames
        } = e;
        if (e.changeTypes.grouping) {
            return
        }
        if (optionNames.width || optionNames.visibleWidth) {
            super._columnOptionChanged(e);
            this._fireColumnResizedCallbacks()
        }
    }
    getScrollable() {
        return this._scrollable
    }
    _handleDataChanged(change) {
        switch (change.changeType) {
            case "refresh":
            case "prepend":
            case "append":
            case "update":
                this.render(null, change);
                break;
            default:
                this._update(change)
        }
    }
    publicMethods() {
        return ["isScrollbarVisible", "getTopVisibleRowData", "getScrollbarWidth", "getCellElement", "getRowElement", "getScrollable"]
    }
    contentWidth() {
        return getWidth(this.element()) - this.getScrollbarWidth()
    }
    getScrollbarWidth(isHorizontal) {
        var scrollableContainer = this._scrollableContainer && this._scrollableContainer.get(0);
        var scrollbarWidth = 0;
        if (scrollableContainer) {
            if (!isHorizontal) {
                scrollbarWidth = scrollableContainer.clientWidth ? scrollableContainer.offsetWidth - scrollableContainer.clientWidth : 0
            } else {
                scrollbarWidth = scrollableContainer.clientHeight ? scrollableContainer.offsetHeight - scrollableContainer.clientHeight : 0;
                scrollbarWidth += getScrollableBottomPadding(this)
            }
        }
        return scrollbarWidth > 0 ? scrollbarWidth : 0
    }
    _fireColumnResizedCallbacks() {
        var lastColumnWidths = this._lastColumnWidths || [];
        var columnWidths = [];
        var columns = this.getColumns();
        for (var i = 0; i < columns.length; i++) {
            columnWidths[i] = columns[i].visibleWidth;
            if (columns[i].resizedCallbacks && !isDefined(columns[i].groupIndex) && lastColumnWidths[i] !== columnWidths[i]) {
                columns[i].resizedCallbacks.fire(columnWidths[i])
            }
        }
        this._lastColumnWidths = columnWidths
    }
    _updateLastRowBorder(isFreeSpaceRowVisible) {
        if (this.option("showBorders") && !isFreeSpaceRowVisible) {
            this.element().addClass(LAST_ROW_BORDER)
        } else {
            this.element().removeClass(LAST_ROW_BORDER)
        }
    }
    _updateScrollable() {
        var scrollable = Scrollable.getInstance(this.element());
        if (scrollable) {
            scrollable.update();
            if (scrollable.option("useNative") || !(null === scrollable || void 0 === scrollable ? void 0 : scrollable.isRenovated())) {
                this._updateHorizontalScrollPosition()
            }
        }
    }
    _updateHorizontalScrollPosition() {
        var scrollable = this.getScrollable();
        var scrollLeft = scrollable && scrollable.scrollOffset().left;
        var rtlEnabled = this.option("rtlEnabled");
        if (rtlEnabled) {
            var maxHorizontalScrollOffset = getMaxHorizontalScrollOffset(scrollable);
            var scrollRight = maxHorizontalScrollOffset - scrollLeft;
            if (scrollRight !== this._scrollRight) {
                this._scrollLeft = maxHorizontalScrollOffset - this._scrollRight
            }
        }
        if (this._scrollLeft >= 0 && scrollLeft !== this._scrollLeft) {
            scrollable.scrollTo({
                x: this._scrollLeft
            })
        }
    }
    _resizeCore() {
        var that = this;
        that._fireColumnResizedCallbacks();
        that._updateRowHeight();
        deferRender(() => {
            that._renderScrollable();
            that.renderNoDataText();
            that.updateFreeSpaceRowHeight();
            deferUpdate(() => {
                that._updateScrollable()
            })
        })
    }
    scrollTo(location) {
        var $element = this.element();
        var dxScrollable = $element && Scrollable.getInstance($element);
        if (dxScrollable) {
            dxScrollable.scrollTo(location)
        }
    }
    height(height) {
        var $element = this.element();
        if (0 === arguments.length) {
            return $element ? getOuterHeight($element, true) : 0
        }
        if (isDefined(height) && $element) {
            this.hasHeight("auto" !== height);
            setHeight($element, height)
        }
    }
    hasHeight(hasHeight) {
        if (0 === arguments.length) {
            return !!this._hasHeight
        }
        this._hasHeight = hasHeight;
        return
    }
    setLoading(isLoading, messageText) {
        var loadPanel = this._loadPanel;
        var dataController = this._dataController;
        var loadPanelOptions = this.option("loadPanel") || {};
        var animation = dataController.isLoaded() ? loadPanelOptions.animation : null;
        var $element = this.element();
        if (!hasWindow()) {
            return
        }
        if (!loadPanel && void 0 !== messageText && dataController.isLocalStore() && "auto" === loadPanelOptions.enabled && $element) {
            this._renderLoadPanel($element, $element.parent());
            loadPanel = this._loadPanel
        }
        if (loadPanel) {
            var visibilityOptions = {
                message: messageText || loadPanelOptions.text,
                animation: animation,
                visible: isLoading
            };
            if (isLoading) {
                visibilityOptions.position = gridCoreUtils.calculateLoadPanelPosition($element)
            }
            clearTimeout(this._hideLoadingTimeoutID);
            if (loadPanel.option("visible") && !isLoading) {
                this._hideLoadingTimeoutID = setTimeout(() => {
                    loadPanel.option(visibilityOptions)
                }, LOADPANEL_HIDE_TIMEOUT)
            } else {
                loadPanel.option(visibilityOptions)
            }
        }
    }
    setRowsOpacity(columnIndex, value) {
        var $rows = this._getRowElements().not(".".concat(GROUP_ROW_CLASS)) || [];
        this._setRowsOpacityCore($rows, this.getColumns(), columnIndex, value)
    }
    _getCellElementsCore(rowIndex) {
        var $cells = super._getCellElementsCore.apply(this, arguments);
        if ($cells) {
            var groupCellIndex = $cells.filter(".".concat(GROUP_CELL_CLASS)).index();
            if (groupCellIndex >= 0 && $cells.length > groupCellIndex + 1) {
                return $cells.slice(0, groupCellIndex + 1)
            }
        }
        return $cells
    }
    _getBoundaryVisibleItemIndex(isTop, isFloor) {
        var itemIndex = 0;
        var prevOffset = 0;
        var offset = 0;
        var viewportBoundary = this._scrollTop;
        var $contentElement = this._findContentElement();
        var contentElementOffsetTop = $contentElement && $contentElement.offset().top;
        var items = this._dataController.items();
        var tableElement = this.getTableElement();
        if (items.length && tableElement) {
            var rowElements = this._getRowElements(tableElement).filter(":visible");
            if (!isTop) {
                var height = getOuterHeight(this._hasHeight ? this.element() : getWindow());
                viewportBoundary += height
            }
            for (itemIndex = 0; itemIndex < items.length; itemIndex++) {
                prevOffset = offset;
                var $rowElement = $(rowElements).eq(itemIndex);
                if ($rowElement.length) {
                    offset = $rowElement.offset();
                    offset = (isTop ? offset.top : offset.top + getOuterHeight($rowElement)) - contentElementOffsetTop;
                    if (offset > viewportBoundary) {
                        if (itemIndex) {
                            if (isFloor || 2 * viewportBoundary < Math.round(offset + prevOffset)) {
                                itemIndex--
                            }
                        }
                        break
                    }
                }
            }
            if (itemIndex && itemIndex === items.length) {
                itemIndex--
            }
        }
        return itemIndex
    }
    getTopVisibleItemIndex(isFloor) {
        return this._getBoundaryVisibleItemIndex(true, isFloor)
    }
    getBottomVisibleItemIndex(isFloor) {
        return this._getBoundaryVisibleItemIndex(false, isFloor)
    }
    getTopVisibleRowData() {
        var itemIndex = this.getTopVisibleItemIndex();
        var items = this._dataController.items();
        if (items[itemIndex]) {
            return items[itemIndex].data
        }
        return
    }
    _scrollToElement($element, offset) {
        var scrollable = this.getScrollable();
        scrollable && scrollable.scrollToElement($element, offset)
    }
    optionChanged(args) {
        super.optionChanged(args);
        switch (args.name) {
            case "wordWrapEnabled":
            case "showColumnLines":
            case "showRowLines":
            case "rowAlternationEnabled":
            case "rowTemplate":
            case "dataRowTemplate":
            case "twoWayBindingEnabled":
                this._invalidate(true, true);
                args.handled = true;
                break;
            case "scrolling":
                this._rowHeight = null;
                this._tableElement = null;
                args.handled = true;
                break;
            case "rtlEnabled":
                this._rowHeight = null;
                this._tableElement = null;
                break;
            case "loadPanel":
                this._tableElement = null;
                this._invalidate(true, "loadPanel.enabled" !== args.fullName);
                args.handled = true;
                break;
            case "noDataText":
                this.renderNoDataText();
                args.handled = true
        }
    }
    setAriaOwns(headerTableId, footerTableId, isFixed) {
        var _a;
        var $contentElement = this._findContentElement();
        var $tableElement = this.getTableElement();
        if (null === $tableElement || void 0 === $tableElement ? void 0 : $tableElement.length) {
            this.setAria("owns", "".concat(null !== headerTableId && void 0 !== headerTableId ? headerTableId : "", " ").concat(null !== (_a = $tableElement.attr("id")) && void 0 !== _a ? _a : "", " ").concat(null !== footerTableId && void 0 !== footerTableId ? footerTableId : "").trim(), $contentElement)
        }
    }
    dispose() {
        super.dispose();
        clearTimeout(this._hideLoadingTimeoutID);
        this._scrollable && this._scrollable.dispose()
    }
    setScrollerSpacing(vScrollbarWidth, hScrollbarWidth) {}
    _restoreErrorRow(contentTable) {}
    isElementInside($element) {
        var $rowsViewElement = $element.closest(".".concat(this.addWidgetPrefix(ROWS_VIEW_CLASS)));
        return $rowsViewElement.is(this.element())
    }
}
export var rowsModule = {
    defaultOptions: () => ({
        hoverStateEnabled: false,
        scrolling: {
            useNative: "auto"
        },
        loadPanel: {
            enabled: "auto",
            text: messageLocalization.format("Loading"),
            width: 200,
            height: 90,
            showIndicator: true,
            indicatorSrc: "",
            showPane: true
        },
        dataRowTemplate: null,
        columnAutoWidth: false,
        noDataText: messageLocalization.format("dxDataGrid-noDataText"),
        wordWrapEnabled: false,
        showColumnLines: true,
        showRowLines: false,
        rowAlternationEnabled: false,
        activeStateEnabled: false,
        twoWayBindingEnabled: true
    }),
    views: {
        rowsView: RowsView
    }
};
