/**
 * DevExtreme (cjs/__internal/grids/grid_core/focus/m_focus.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/
 */
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.focusModule = exports.FocusController = void 0;
var _renderer = _interopRequireDefault(require("../../../../core/renderer"));
var _common = require("../../../../core/utils/common");
var _deferred = require("../../../../core/utils/deferred");
var _iterator = require("../../../../core/utils/iterator");
var _type = require("../../../../core/utils/type");
var _m_editing_utils = require("../editing/m_editing_utils");
var _m_modules = _interopRequireDefault(require("../m_modules"));
var _m_utils = _interopRequireDefault(require("../m_utils"));
var _m_focus_utils = require("./m_focus_utils");

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}

function _inheritsLoose(subClass, superClass) {
    subClass.prototype = Object.create(superClass.prototype);
    subClass.prototype.constructor = subClass;
    _setPrototypeOf(subClass, superClass)
}

function _setPrototypeOf(o, p) {
    _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function(o, p) {
        o.__proto__ = p;
        return o
    };
    return _setPrototypeOf(o, p)
}
const ROW_FOCUSED_CLASS = "dx-row-focused";
const FOCUSED_ROW_SELECTOR = ".dx-row.".concat("dx-row-focused");
const TABLE_POSTFIX_CLASS = "table";
const CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled";
let FocusController = function(_core$ViewController) {
    _inheritsLoose(FocusController, _core$ViewController);

    function FocusController() {
        return _core$ViewController.apply(this, arguments) || this
    }
    var _proto = FocusController.prototype;
    _proto.getKeyboardController = function() {
        return this.getController("keyboardNavigation")
    };
    _proto.getDataController = function() {
        return this.getController("data")
    };
    _proto.init = function() {
        this.component._optionsByReference.focusedRowKey = true
    };
    _proto.optionChanged = function(args) {
        const {
            name: name,
            value: value,
            previousValue: previousValue
        } = args;
        switch (name) {
            case "focusedRowIndex":
                this._focusRowByIndex(value);
                this.getKeyboardController()._fireFocusedRowChanged();
                args.handled = true;
                break;
            case "focusedRowKey":
                if (Array.isArray(value) && JSON.stringify(value) === JSON.stringify(previousValue)) {
                    return
                }
                this._focusRowByKey(value);
                this.getKeyboardController()._fireFocusedRowChanged();
                args.handled = true;
                break;
            case "focusedColumnIndex":
            case "focusedRowEnabled":
            case "autoNavigateToFocusedRow":
                args.handled = true;
                break;
            default:
                _core$ViewController.prototype.optionChanged.call(this, args)
        }
    };
    _proto.publicMethods = function() {
        return ["navigateToRow", "isRowFocused"]
    };
    _proto.isAutoNavigateToFocusedRow = function() {
        return "infinite" !== this.option("scrolling.mode") && this.option("autoNavigateToFocusedRow")
    };
    _proto._focusRowByIndex = function(index, operationTypes) {
        if (!this.option("focusedRowEnabled")) {
            return
        }
        index = void 0 !== index ? index : this.option("focusedRowIndex");
        if (index < 0) {
            if (this.isAutoNavigateToFocusedRow()) {
                this._resetFocusedRow()
            }
        } else {
            this._focusRowByIndexCore(index, operationTypes)
        }
    };
    _proto._focusRowByIndexCore = function(index, operationTypes) {
        const pageSize = this.getDataController().pageSize();
        const setKeyByIndex = () => {
            if (this._isValidFocusedRowIndex(index)) {
                let rowIndex = index - this.getDataController().getRowIndexOffset(true);
                if (!operationTypes || operationTypes.paging && !operationTypes.filtering) {
                    const lastItemIndex = this.getDataController()._getLastItemIndex();
                    rowIndex = Math.min(rowIndex, lastItemIndex)
                }
                const focusedRowKey = this.getDataController().getKeyByRowIndex(rowIndex, true);
                if ((0, _type.isDefined)(focusedRowKey) && !this.isRowFocused(focusedRowKey)) {
                    this.option("focusedRowKey", focusedRowKey)
                }
            }
        };
        if (pageSize >= 0) {
            if (!this._isLocalRowIndex(index)) {
                const pageIndex = Math.floor(index / this.getDataController().pageSize());
                (0, _deferred.when)(this.getDataController().pageIndex(pageIndex), this.getDataController().waitReady()).done(() => {
                    setKeyByIndex()
                })
            } else {
                setKeyByIndex()
            }
        }
    };
    _proto._isLocalRowIndex = function(index) {
        const isVirtualScrolling = this.getKeyboardController()._isVirtualScrolling();
        if (isVirtualScrolling) {
            const pageIndex = Math.floor(index / this.getDataController().pageSize());
            const virtualItems = this.getDataController().virtualItemsCount();
            const virtualItemsBegin = virtualItems ? virtualItems.begin : -1;
            const visibleRowsCount = this.getDataController().getVisibleRows().length + this.getDataController().getRowIndexOffset();
            const visiblePagesCount = Math.ceil(visibleRowsCount / this.getDataController().pageSize());
            return virtualItemsBegin <= index && visiblePagesCount > pageIndex
        }
        return true
    };
    _proto._setFocusedRowKeyByIndex = function(index) {
        if (this._isValidFocusedRowIndex(index)) {
            const rowIndex = Math.min(index - this.getDataController().getRowIndexOffset(), this.getDataController().items().length - 1);
            const focusedRowKey = this.getDataController().getKeyByRowIndex(rowIndex);
            if ((0, _type.isDefined)(focusedRowKey) && !this.isRowFocused(focusedRowKey)) {
                this.option("focusedRowKey", focusedRowKey)
            }
        }
    };
    _proto._focusRowByKey = function(key) {
        if (!(0, _type.isDefined)(key)) {
            this._resetFocusedRow()
        } else {
            this._navigateToRow(key, true)
        }
    };
    _proto._resetFocusedRow = function() {
        const focusedRowKey = this.option("focusedRowKey");
        const isFocusedRowKeyDefined = (0, _type.isDefined)(focusedRowKey);
        if (!isFocusedRowKeyDefined && this.option("focusedRowIndex") < 0) {
            return
        }
        if (isFocusedRowKeyDefined) {
            this.option("focusedRowKey", null)
        }
        this.getKeyboardController().setFocusedRowIndex(-1);
        this.option("focusedRowIndex", -1);
        this.getDataController().updateItems({
            changeType: "updateFocusedRow",
            focusedRowKey: null
        });
        this.getKeyboardController()._fireFocusedRowChanged()
    };
    _proto._isValidFocusedRowIndex = function(rowIndex) {
        const row = this.getDataController().getVisibleRows()[rowIndex];
        return !row || "data" === row.rowType || "group" === row.rowType
    };
    _proto.navigateToRow = function(key) {
        if (!this.isAutoNavigateToFocusedRow()) {
            this.option("focusedRowIndex", -1)
        }
        return this._navigateToRow(key)
    };
    _proto._navigateToRow = function(key, needFocusRow) {
        const that = this;
        const isAutoNavigate = that.isAutoNavigateToFocusedRow();
        const d = new _deferred.Deferred;
        if (void 0 === key || !this.getDataController().dataSource()) {
            return d.reject().promise()
        }
        const rowIndexByKey = that.getFocusedRowIndexByKey(key);
        if (!isAutoNavigate && needFocusRow || rowIndexByKey >= 0) {
            that._navigateTo(key, d, needFocusRow)
        } else {
            this.getDataController().getPageIndexByKey(key).done(pageIndex => {
                if (pageIndex < 0) {
                    d.resolve(-1);
                    return
                }
                if (pageIndex === this.getDataController().pageIndex()) {
                    this.getDataController().reload().done(() => {
                        if (that.isRowFocused(key) && this.getDataController().getRowIndexByKey(key) >= 0) {
                            d.resolve(that.getFocusedRowIndexByKey(key))
                        } else {
                            that._navigateTo(key, d, needFocusRow)
                        }
                    }).fail(d.reject)
                } else {
                    this.getDataController().pageIndex(pageIndex).done(() => {
                        that._navigateTo(key, d, needFocusRow)
                    }).fail(d.reject)
                }
            }).fail(d.reject)
        }
        return d.promise()
    };
    _proto._navigateTo = function(key, deferred, needFocusRow) {
        const visibleRowIndex = this.getDataController().getRowIndexByKey(key);
        const isVirtualRowRenderingMode = _m_utils.default.isVirtualRowRendering(this);
        const isAutoNavigate = this.isAutoNavigateToFocusedRow();
        if (isAutoNavigate && isVirtualRowRenderingMode && visibleRowIndex < 0) {
            this._navigateToVirtualRow(key, deferred, needFocusRow)
        } else {
            this._navigateToVisibleRow(key, deferred, needFocusRow)
        }
    };
    _proto._navigateToVisibleRow = function(key, deferred, needFocusRow) {
        if (needFocusRow) {
            this._triggerUpdateFocusedRow(key, deferred)
        } else {
            const focusedRowIndex = this.getFocusedRowIndexByKey(key);
            this.getView("rowsView").scrollToRowElement(key, deferred).done(() => {
                deferred.resolve(focusedRowIndex)
            })
        }
    };
    _proto._navigateToVirtualRow = function(key, deferred, needFocusRow) {
        const rowsScrollController = this.getDataController()._rowsScrollController;
        const rowIndex = _m_utils.default.getIndexByKey(key, this.getDataController().items(true));
        const scrollable = this.getView("rowsView").getScrollable();
        if (rowsScrollController && scrollable && rowIndex >= 0) {
            const focusedRowIndex = rowIndex + this.getDataController().getRowIndexOffset(true);
            const offset = rowsScrollController.getItemOffset(focusedRowIndex);
            const triggerUpdateFocusedRow = () => {
                if (this.getDataController().totalCount() && !this.getDataController().items().length) {
                    return
                }
                this.component.off("contentReady", triggerUpdateFocusedRow);
                if (needFocusRow) {
                    this._triggerUpdateFocusedRow(key, deferred)
                } else {
                    deferred.resolve(focusedRowIndex)
                }
            };
            this.component.on("contentReady", triggerUpdateFocusedRow);
            this.getView("rowsView").scrollTopPosition(offset)
        } else {
            deferred.resolve(-1)
        }
    };
    _proto._triggerUpdateFocusedRow = function(key, deferred) {
        const focusedRowIndex = this.getFocusedRowIndexByKey(key);
        if (this._isValidFocusedRowIndex(focusedRowIndex)) {
            let d;
            if (this.option("focusedRowEnabled")) {
                this.getDataController().updateItems({
                    changeType: "updateFocusedRow",
                    focusedRowKey: key
                })
            } else {
                d = this.getView("rowsView").scrollToRowElement(key)
            }(0, _deferred.when)(d).done(() => {
                this.getKeyboardController().setFocusedRowIndex(focusedRowIndex);
                deferred && deferred.resolve(focusedRowIndex)
            })
        } else {
            deferred && deferred.resolve(-1)
        }
    };
    _proto.getFocusedRowIndexByKey = function(key) {
        const loadedRowIndex = this.getDataController().getRowIndexByKey(key, true);
        return loadedRowIndex >= 0 ? loadedRowIndex + this.getDataController().getRowIndexOffset(true) : -1
    };
    _proto._focusRowByKeyOrIndex = function() {
        const focusedRowKey = this.option("focusedRowKey");
        let currentFocusedRowIndex = this.option("focusedRowIndex");
        if ((0, _type.isDefined)(focusedRowKey)) {
            const visibleRowIndex = this.getDataController().getRowIndexByKey(focusedRowKey);
            if (visibleRowIndex >= 0) {
                if (this.getKeyboardController()._isVirtualScrolling()) {
                    currentFocusedRowIndex = visibleRowIndex + this.getDataController().getRowIndexOffset()
                }
                this.getKeyboardController().setFocusedRowIndex(currentFocusedRowIndex);
                this._triggerUpdateFocusedRow(focusedRowKey)
            } else {
                this._navigateToRow(focusedRowKey, true).done(focusedRowIndex => {
                    if (currentFocusedRowIndex >= 0 && focusedRowIndex < 0) {
                        this._focusRowByIndex()
                    } else if (currentFocusedRowIndex < 0 && focusedRowIndex >= 0) {
                        this.getKeyboardController().setFocusedRowIndex(focusedRowIndex)
                    }
                })
            }
        } else if (currentFocusedRowIndex >= 0) {
            this._focusRowByIndex(currentFocusedRowIndex)
        }
    };
    _proto.isRowFocused = function(key) {
        const focusedRowKey = this.option("focusedRowKey");
        if ((0, _type.isDefined)(focusedRowKey)) {
            return (0, _common.equalByValue)(key, this.option("focusedRowKey"))
        }
        return
    };
    _proto.updateFocusedRow = function(e) {
        var _a;
        const that = this;
        const focusedRowIndex = null !== (_a = e.focusedRowIndex) && void 0 !== _a ? _a : that.getDataController().getRowIndexByKey(e.focusedRowKey);
        const rowsView = that.getView("rowsView");
        let $tableElement;
        let $mainRow;
        (0, _iterator.each)(rowsView.getTableElements(), (index, element) => {
            const isMainTable = 0 === index;
            $tableElement = (0, _renderer.default)(element);
            that._clearPreviousFocusedRow($tableElement, focusedRowIndex);
            const $row = that._prepareFocusedRow({
                changedItem: that.getDataController().getVisibleRows()[focusedRowIndex],
                $tableElement: $tableElement,
                focusedRowIndex: focusedRowIndex
            });
            if (isMainTable) {
                $mainRow = $row
            }
        });
        if (!e.preventScroll && $mainRow) {
            rowsView.scrollToElementVertically($mainRow)
        }
    };
    _proto._clearPreviousFocusedRow = function($tableElement, focusedRowIndex) {
        const $prevRowFocusedElement = $tableElement.find(FOCUSED_ROW_SELECTOR).filter((_, focusedRow) => {
            const $focusedRowTable = (0, _renderer.default)(focusedRow).closest(".".concat(this.addWidgetPrefix("table")));
            return $tableElement.is($focusedRowTable)
        });
        $prevRowFocusedElement.removeClass("dx-row-focused").removeClass("dx-cell-focus-disabled").removeAttr("tabindex");
        $prevRowFocusedElement.children("td").removeAttr("tabindex");
        if (0 !== focusedRowIndex) {
            const $firstRow = (0, _renderer.default)(this.getView("rowsView").getRowElement(0));
            $firstRow.removeClass("dx-cell-focus-disabled").removeAttr("tabIndex")
        }
    };
    _proto._prepareFocusedRow = function(options) {
        let $row;
        const {
            changedItem: changedItem
        } = options;
        if (changedItem && ("data" === changedItem.rowType || "group" === changedItem.rowType)) {
            const {
                focusedRowIndex: focusedRowIndex
            } = options;
            const {
                $tableElement: $tableElement
            } = options;
            const tabIndex = this.option("tabindex") || 0;
            const rowsView = this.getView("rowsView");
            $row = (0, _renderer.default)(rowsView._getRowElements($tableElement).eq(focusedRowIndex));
            $row.addClass("dx-row-focused").attr("tabindex", tabIndex)
        }
        return $row
    };
    return FocusController
}(_m_modules.default.ViewController);
exports.FocusController = FocusController;
const keyboardNavigation = Base => function(_Base) {
    _inheritsLoose(FocusKeyboardNavigationExtender, _Base);

    function FocusKeyboardNavigationExtender() {
        return _Base.apply(this, arguments) || this
    }
    var _proto2 = FocusKeyboardNavigationExtender.prototype;
    _proto2.init = function() {
        const rowIndex = this.option("focusedRowIndex");
        const columnIndex = this.option("focusedColumnIndex");
        this.createAction("onFocusedRowChanging", {
            excludeValidators: ["disabled", "readOnly"]
        });
        this.createAction("onFocusedRowChanged", {
            excludeValidators: ["disabled", "readOnly"]
        });
        this.createAction("onFocusedCellChanging", {
            excludeValidators: ["disabled", "readOnly"]
        });
        this.createAction("onFocusedCellChanged", {
            excludeValidators: ["disabled", "readOnly"]
        });
        _Base.prototype.init.call(this);
        this.setRowFocusType();
        this._focusedCellPosition = {};
        if ((0, _type.isDefined)(rowIndex) && rowIndex >= 0) {
            this._focusedCellPosition.rowIndex = rowIndex
        }
        if ((0, _type.isDefined)(columnIndex) && columnIndex >= 0) {
            this._focusedCellPosition.columnIndex = columnIndex
        }
    };
    _proto2.setFocusedRowIndex = function(rowIndex) {
        _Base.prototype.setFocusedRowIndex.call(this, rowIndex);
        this.option("focusedRowIndex", rowIndex)
    };
    _proto2.setFocusedColumnIndex = function(columnIndex) {
        _Base.prototype.setFocusedColumnIndex.call(this, columnIndex);
        this.option("focusedColumnIndex", columnIndex)
    };
    _proto2._escapeKeyHandler = function(eventArgs, isEditing) {
        if (isEditing || !this.option("focusedRowEnabled")) {
            return _Base.prototype._escapeKeyHandler.call(this, eventArgs, isEditing)
        }
        if (this.isCellFocusType()) {
            this.setRowFocusType();
            this._focus(this._getCellElementFromTarget(eventArgs.originalEvent.target), true);
            return true
        }
        return false
    };
    _proto2._updateFocusedCellPosition = function($cell, direction) {
        const position = _Base.prototype._updateFocusedCellPosition.call(this, $cell, direction);
        if (position && position.columnIndex >= 0) {
            this._fireFocusedCellChanged($cell)
        }
        return position
    };
    return FocusKeyboardNavigationExtender
}(Base);
const editorFactory = Base => function(_Base2) {
    _inheritsLoose(FocusEditorFactoryExtender, _Base2);

    function FocusEditorFactoryExtender() {
        return _Base2.apply(this, arguments) || this
    }
    var _proto3 = FocusEditorFactoryExtender.prototype;
    _proto3.renderFocusOverlay = function($element, isHideBorder) {
        var _a;
        const focusedRowEnabled = this.option("focusedRowEnabled");
        let $cell;
        if (!focusedRowEnabled || !(null === (_a = this._keyboardNavigationController) || void 0 === _a ? void 0 : _a.isRowFocusType()) || this._editingController.isEditing()) {
            _Base2.prototype.renderFocusOverlay.call(this, $element, isHideBorder)
        } else if (focusedRowEnabled) {
            const isRowElement = "row" === this._keyboardNavigationController._getElementType($element);
            if (isRowElement && !$element.hasClass("dx-row-focused")) {
                $cell = this._keyboardNavigationController.getFirstValidCellInRow($element);
                this._keyboardNavigationController.focus($cell)
            }
        }
    };
    return FocusEditorFactoryExtender
}(Base);
const columns = Base => function(_Base3) {
    _inheritsLoose(FocusColumnsExtender, _Base3);

    function FocusColumnsExtender() {
        return _Base3.apply(this, arguments) || this
    }
    var _proto4 = FocusColumnsExtender.prototype;
    _proto4.getSortDataSourceParameters = function(_, sortByKey) {
        let result = _Base3.prototype.getSortDataSourceParameters.apply(this, arguments);
        const dataSource = this._dataController._dataSource;
        const store = this._dataController.store();
        let key = store && store.key();
        const remoteOperations = dataSource && dataSource.remoteOperations() || {};
        const isLocalOperations = Object.keys(remoteOperations).every(operationName => !remoteOperations[operationName]);
        if (key && (this.option("focusedRowEnabled") && false !== this._focusController.isAutoNavigateToFocusedRow() || sortByKey)) {
            key = Array.isArray(key) ? key : [key];
            const notSortedKeys = key.filter(key => !this.columnOption(key, "sortOrder"));
            if (notSortedKeys.length) {
                result = result || [];
                if (isLocalOperations) {
                    result.push({
                        selector: dataSource.getDataIndexGetter(),
                        desc: false
                    })
                } else {
                    notSortedKeys.forEach(notSortedKey => result.push({
                        selector: notSortedKey,
                        desc: false
                    }))
                }
            }
        }
        return result
    };
    return FocusColumnsExtender
}(Base);
const data = Base => function(_Base4) {
    _inheritsLoose(FocusDataControllerExtender, _Base4);

    function FocusDataControllerExtender() {
        return _Base4.apply(this, arguments) || this
    }
    var _proto5 = FocusDataControllerExtender.prototype;
    _proto5._applyChange = function(change) {
        if (change && "updateFocusedRow" === change.changeType) {
            return
        }
        return _Base4.prototype._applyChange.apply(this, arguments)
    };
    _proto5._fireChanged = function(e) {
        _Base4.prototype._fireChanged.call(this, e);
        if (this.option("focusedRowEnabled") && this._dataSource) {
            const isPartialUpdate = "update" === e.changeType && e.repaintChangesOnly;
            const isPartialUpdateWithDeleting = isPartialUpdate && e.changeTypes && e.changeTypes.indexOf("remove") >= 0;
            if ("refresh" === e.changeType && e.items.length || isPartialUpdateWithDeleting) {
                this._updatePageIndexes();
                this._updateFocusedRow(e)
            } else if ("append" === e.changeType || "prepend" === e.changeType) {
                this._updatePageIndexes()
            } else if ("update" === e.changeType && e.repaintChangesOnly) {
                this._updateFocusedRow(e)
            }
        }
    };
    _proto5._updatePageIndexes = function() {
        const prevRenderingPageIndex = this._lastRenderingPageIndex || 0;
        const renderingPageIndex = this._rowsScrollController ? this._rowsScrollController.pageIndex() : 0;
        this._lastRenderingPageIndex = renderingPageIndex;
        this._isPagingByRendering = renderingPageIndex !== prevRenderingPageIndex
    };
    _proto5.isPagingByRendering = function() {
        return this._isPagingByRendering
    };
    _proto5._updateFocusedRow = function(e) {
        const operationTypes = e.operationTypes || {};
        const {
            reload: reload,
            fullReload: fullReload,
            pageIndex: pageIndex,
            paging: paging
        } = operationTypes;
        const isVirtualScrolling = this._keyboardNavigationController._isVirtualScrolling();
        const pagingWithoutVirtualScrolling = paging && !isVirtualScrolling;
        const focusedRowKey = this.option("focusedRowKey");
        const isAutoNavigate = this._focusController.isAutoNavigateToFocusedRow();
        const isReload = reload && false === pageIndex;
        if (isReload && !fullReload && (0, _type.isDefined)(focusedRowKey)) {
            this._focusController._navigateToRow(focusedRowKey, true).done(focusedRowIndex => {
                if (focusedRowIndex < 0) {
                    this._focusController._focusRowByIndex(void 0, operationTypes)
                }
            })
        } else if (pagingWithoutVirtualScrolling && isAutoNavigate) {
            const rowIndexByKey = this.getRowIndexByKey(focusedRowKey);
            const focusedRowIndex = this.option("focusedRowIndex");
            const isValidRowIndexByKey = rowIndexByKey >= 0;
            const isValidFocusedRowIndex = focusedRowIndex >= 0;
            const isSameRowIndex = focusedRowIndex === rowIndexByKey;
            if (isValidFocusedRowIndex && (isSameRowIndex || !isValidRowIndexByKey)) {
                this._focusController._focusRowByIndex(focusedRowIndex, operationTypes)
            }
        } else if (pagingWithoutVirtualScrolling && !isAutoNavigate && this.getRowIndexByKey(focusedRowKey) < 0) {
            this.option("focusedRowIndex", -1)
        } else if (operationTypes.fullReload) {
            this._focusController._focusRowByKeyOrIndex()
        }
    };
    _proto5.getPageIndexByKey = function(key) {
        const that = this;
        const d = new _deferred.Deferred;
        that.getGlobalRowIndexByKey(key).done(globalIndex => {
            d.resolve(globalIndex >= 0 ? Math.floor(globalIndex / that.pageSize()) : -1)
        }).fail(d.reject);
        return d.promise()
    };
    _proto5.getGlobalRowIndexByKey = function(key) {
        if (this._dataSource.group()) {
            return this._calculateGlobalRowIndexByGroupedData(key)
        }
        return this._calculateGlobalRowIndexByFlatData(key)
    };
    _proto5._calculateGlobalRowIndexByFlatData = function(key, groupFilter, useGroup) {
        const that = this;
        const deferred = new _deferred.Deferred;
        const dataSource = that._dataSource;
        if (Array.isArray(key) || (0, _m_editing_utils.isNewRowTempKey)(key)) {
            return deferred.resolve(-1).promise()
        }
        let filter = that._generateFilterByKey(key);
        dataSource.load({
            filter: that._concatWithCombinedFilter(filter),
            skip: 0,
            take: 1
        }).done(data => {
            if (data.length > 0) {
                filter = that._generateOperationFilterByKey(key, data[0], useGroup);
                dataSource.load({
                    filter: that._concatWithCombinedFilter(filter, groupFilter),
                    skip: 0,
                    take: 1,
                    requireTotalCount: true
                }).done((_, extra) => {
                    deferred.resolve(extra.totalCount)
                })
            } else {
                deferred.resolve(-1)
            }
        });
        return deferred.promise()
    };
    _proto5._concatWithCombinedFilter = function(filter, groupFilter) {
        const combinedFilter = this.getCombinedFilter();
        return _m_utils.default.combineFilters([filter, combinedFilter, groupFilter])
    };
    _proto5._generateBooleanFilter = function(selector, value, sortInfo) {
        const {
            desc: desc
        } = sortInfo;
        switch (true) {
            case false === value && desc:
                return [selector, "=", true];
            case false === value && !desc:
                return [selector, "=", null];
            case true === value && !desc:
            case !(0, _type.isBoolean)(value) && desc:
                return [selector, "<>", value];
            default:
                return
        }
    };
    _proto5._generateOperationFilterByKey = function(key, rowData, useGroup) {
        const that = this;
        const dateSerializationFormat = that.option("dateSerializationFormat");
        const isRemoteFiltering = that._dataSource.remoteOperations().filtering;
        const isRemoteSorting = that._dataSource.remoteOperations().sorting;
        let filter = that._generateFilterByKey(key, "<");
        let sort = that._columnsController.getSortDataSourceParameters(!isRemoteFiltering, true);
        if (useGroup) {
            const group = that._columnsController.getGroupDataSourceParameters(!isRemoteFiltering);
            if (group) {
                sort = sort ? group.concat(sort) : group
            }
        }
        if (sort) {
            sort.slice().reverse().forEach(sortInfo => {
                const {
                    selector: selector,
                    desc: desc,
                    compare: compare
                } = sortInfo;
                const {
                    getter: getter,
                    rawValue: rawValue,
                    safeValue: safeValue
                } = _m_focus_utils.UiGridCoreFocusUtils.getSortFilterValue(sortInfo, rowData, {
                    isRemoteFiltering: isRemoteFiltering,
                    dateSerializationFormat: dateSerializationFormat,
                    getSelector: selector => that._columnsController.columnOption(selector, "selector")
                });
                filter = [
                    [selector, "=", safeValue], "and", filter
                ];
                if (null === rawValue || (0, _type.isBoolean)(rawValue)) {
                    const booleanFilter = that._generateBooleanFilter(selector, safeValue, desc);
                    if (booleanFilter) {
                        filter = [booleanFilter, "or", filter]
                    }
                } else {
                    const filterOperation = desc ? ">" : "<";
                    let sortFilter;
                    if (compare && !isRemoteSorting) {
                        sortFilter = data => {
                            if ("<" === filterOperation) {
                                return compare(rawValue, getter(data)) >= 1
                            }
                            return compare(rawValue, getter(data)) <= -1
                        }
                    } else {
                        sortFilter = [selector, filterOperation, safeValue];
                        if (!desc) {
                            sortFilter = [sortFilter, "or", [selector, "=", null]]
                        }
                    }
                    filter = [sortFilter, "or", filter]
                }
            })
        }
        return filter
    };
    _proto5._generateFilterByKey = function(key, operation) {
        const dataSourceKey = this._dataSource.key();
        let filter = [];
        if (!operation) {
            operation = "="
        }
        if (Array.isArray(dataSourceKey)) {
            for (let i = 0; i < dataSourceKey.length; ++i) {
                const keyPart = key[dataSourceKey[i]];
                if (keyPart) {
                    if (filter.length > 0) {
                        filter.push("and")
                    }
                    filter.push([dataSourceKey[i], operation, keyPart])
                }
            }
        } else {
            filter = [dataSourceKey, operation, key]
        }
        return filter
    };
    _proto5._getLastItemIndex = function() {
        return this.items(true).length - 1
    };
    return FocusDataControllerExtender
}(Base);
const editing = Base => function(_Base5) {
    _inheritsLoose(FocusEditingControllerExtender, _Base5);

    function FocusEditingControllerExtender() {
        return _Base5.apply(this, arguments) || this
    }
    var _proto6 = FocusEditingControllerExtender.prototype;
    _proto6._deleteRowCore = function(rowIndex) {
        const deferred = _Base5.prototype._deleteRowCore.apply(this, arguments);
        const rowKey = this._dataController.getKeyByRowIndex(rowIndex);
        deferred.done(() => {
            const rowIndex = this._dataController.getRowIndexByKey(rowKey);
            const visibleRows = this._dataController.getVisibleRows();
            if (-1 === rowIndex && !visibleRows.length) {
                this._focusController._resetFocusedRow()
            }
        })
    };
    return FocusEditingControllerExtender
}(Base);
const rowsView = Base => function(_Base6) {
    _inheritsLoose(RowsViewFocusController, _Base6);

    function RowsViewFocusController() {
        return _Base6.apply(this, arguments) || this
    }
    var _proto7 = RowsViewFocusController.prototype;
    _proto7._createRow = function(row) {
        const $row = _Base6.prototype._createRow.apply(this, arguments);
        if (this.option("focusedRowEnabled") && row) {
            if (this._focusController.isRowFocused(row.key)) {
                $row.addClass("dx-row-focused")
            }
        }
        return $row
    };
    _proto7._checkRowKeys = function(options) {
        _Base6.prototype._checkRowKeys.apply(this, arguments);
        if (this.option("focusedRowEnabled") && this.option("dataSource")) {
            const store = this._dataController.store();
            if (store && !store.key()) {
                this._dataController.fireError("E1042", "Row focusing")
            }
        }
    };
    _proto7._update = function(change) {
        if ("updateFocusedRow" === change.changeType) {
            if (this.option("focusedRowEnabled")) {
                this._focusController.updateFocusedRow(change)
            }
        } else {
            _Base6.prototype._update.call(this, change)
        }
    };
    _proto7.updateFocusElementTabIndex = function($cellElements, preventScroll) {
        if (this.option("focusedRowEnabled")) {
            this._setFocusedRowElementTabIndex(preventScroll)
        } else {
            _Base6.prototype.updateFocusElementTabIndex.call(this, $cellElements)
        }
    };
    _proto7._setFocusedRowElementTabIndex = function(preventScroll) {
        var _a;
        const focusedRowKey = this.option("focusedRowKey");
        const tabIndex = null !== (_a = this.option("tabIndex")) && void 0 !== _a ? _a : 0;
        const columnsController = this._columnsController;
        let rowIndex = this._dataController.getRowIndexByKey(focusedRowKey);
        let columnIndex = this.option("focusedColumnIndex");
        const $row = this._findRowElementForTabIndex();
        const dataSource = this._dataController.dataSource();
        const operationTypes = null === dataSource || void 0 === dataSource ? void 0 : dataSource.operationTypes();
        const isPaging = !operationTypes || operationTypes.paging;
        if (!(0, _type.isDefined)(this._scrollToFocusOnResize)) {
            this._scrollToFocusOnResize = () => {
                this.scrollToElementVertically(this._findRowElementForTabIndex());
                this.resizeCompleted.remove(this._scrollToFocusOnResize)
            }
        }
        $row.attr("tabIndex", tabIndex);
        const rowIndexFromOption = this.option("focusedRowIndex") - this._dataController.getRowIndexOffset(true);
        if (!isPaging && rowIndex < 0 && rowIndexFromOption >= 0) {
            this._focusController.updateFocusedRow({
                focusedRowIndex: rowIndexFromOption,
                preventScroll: preventScroll
            })
        }
        if (rowIndex >= 0 && !preventScroll) {
            if (columnIndex < 0) {
                columnIndex = 0
            }
            rowIndex += this._dataController.getRowIndexOffset();
            columnIndex += columnsController.getColumnIndexOffset();
            this._keyboardNavigationController.setFocusedCellPosition(rowIndex, columnIndex);
            if (this._focusController.isAutoNavigateToFocusedRow()) {
                if (!isPaging && !this._dataController.isPagingByRendering()) {
                    this.resizeCompleted.remove(this._scrollToFocusOnResize);
                    this.resizeCompleted.add(this._scrollToFocusOnResize)
                }
            }
        }
    };
    _proto7._findRowElementForTabIndex = function() {
        const focusedRowKey = this.option("focusedRowKey");
        const rowIndex = this._dataController.getRowIndexByKey(focusedRowKey);
        return (0, _renderer.default)(this.getRowElement(rowIndex >= 0 ? rowIndex : 0))
    };
    _proto7.scrollToRowElement = function(key) {
        const rowIndex = this._dataController.getRowIndexByKey(key);
        const $row = (0, _renderer.default)(this.getRow(rowIndex));
        return this.scrollToElementVertically($row)
    };
    _proto7.scrollToElementVertically = function($row) {
        const scrollable = this.getScrollable();
        if (scrollable && $row.length) {
            const position = scrollable.getScrollElementPosition($row, "vertical");
            return this.scrollTopPosition(position)
        }
        return (new _deferred.Deferred).resolve()
    };
    _proto7.scrollTopPosition = function(scrollTop) {
        const d = new _deferred.Deferred;
        const scrollable = this.getScrollable();
        if (scrollable) {
            const currentScrollTop = scrollable.scrollTop();
            const scrollHandler = () => {
                scrollable.off("scroll", scrollHandler);
                d.resolve()
            };
            if (scrollTop !== currentScrollTop) {
                scrollable.on("scroll", scrollHandler);
                this._dataController.resetFilterApplying();
                scrollable.scrollTo({
                    top: scrollTop
                });
                return d.promise()
            }
        }
        return d.resolve()
    };
    return RowsViewFocusController
}(Base);
const focusModule = {
    defaultOptions: () => ({
        focusedRowEnabled: false,
        autoNavigateToFocusedRow: true,
        focusedRowKey: null,
        focusedRowIndex: -1,
        focusedColumnIndex: -1
    }),
    controllers: {
        focus: FocusController
    },
    extenders: {
        controllers: {
            keyboardNavigation: keyboardNavigation,
            editorFactory: editorFactory,
            columns: columns,
            data: data,
            editing: editing
        },
        views: {
            rowsView: rowsView
        }
    }
};
exports.focusModule = focusModule;
