/**
 * DevExtreme (bundles/__internal/grids/tree_list/selection/m_selection.js)
 * Version: 23.1.8 (build 24063-0109)
 * Build date: Sun Mar 03 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
var _renderer = _interopRequireDefault(require("../../../../core/renderer"));
var _common = require("../../../../core/utils/common");
var _extend = require("../../../../core/utils/extend");
var _type = require("../../../../core/utils/type");
var _m_selection = require("../../../grids/grid_core/selection/m_selection");
var _m_core = _interopRequireDefault(require("../m_core"));

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)
}
var TREELIST_SELECT_ALL_CLASS = "dx-treelist-select-all";
var SELECT_CHECKBOX_CLASS = "dx-select-checkbox";
var nodeExists = function(array, currentKey) {
    return !!array.filter((function(key) {
        return key === currentKey
    })).length
};
var data = function(Base) {
    return function(_dataSelectionExtende) {
        _inheritsLoose(DataSelectionTreeListExtender, _dataSelectionExtende);

        function DataSelectionTreeListExtender() {
            return _dataSelectionExtende.apply(this, arguments) || this
        }
        var _proto = DataSelectionTreeListExtender.prototype;
        _proto._handleDataChanged = function(e) {
            var selectionController = this.getController("selection");
            var isRecursiveSelection = selectionController.isRecursiveSelection();
            if (isRecursiveSelection && (!e || "updateSelectionState" !== e.changeType)) {
                selectionController.updateSelectionState({
                    selectedItemKeys: this.option("selectedRowKeys")
                })
            }
            _dataSelectionExtende.prototype._handleDataChanged.apply(this, arguments)
        };
        _proto.loadDescendants = function() {
            var that = this;
            var d = _dataSelectionExtende.prototype.loadDescendants.apply(that, arguments);
            var selectionController = that.getController("selection");
            var isRecursiveSelection = selectionController.isRecursiveSelection();
            if (isRecursiveSelection) {
                d.done((function() {
                    selectionController.updateSelectionState({
                        selectedItemKeys: that.option("selectedRowKeys")
                    })
                }))
            }
            return d
        };
        return DataSelectionTreeListExtender
    }((0, _m_selection.dataSelectionExtenderMixin)(Base))
};
var selection = function(Base) {
    return function(_Base) {
        _inheritsLoose(SelectionControllerTreeListExtender, _Base);

        function SelectionControllerTreeListExtender() {
            var _this;
            _this = _Base.apply(this, arguments) || this;
            _this._updateSelectColumn = _common.noop;
            return _this
        }
        var _proto2 = SelectionControllerTreeListExtender.prototype;
        _proto2.init = function() {
            _Base.prototype.init.apply(this, arguments);
            this._selectionStateByKey = {}
        };
        _proto2._getSelectionConfig = function() {
            var _arguments = arguments,
                _this2 = this;
            var config = _Base.prototype._getSelectionConfig.apply(this, arguments);
            var plainItems = config.plainItems;
            config.plainItems = function(cached) {
                var result;
                if (cached) {
                    result = _this2._dataController.getCachedStoreData()
                }
                result || (result = plainItems.apply(_this2, _arguments).map((function(item) {
                    return item.data
                })));
                return result || []
            };
            config.isItemSelected = function(item) {
                var key = _this2._dataController.keyOf(item);
                return _this2.isRowSelected(key)
            };
            config.isSelectableItem = function(item) {
                return !!item
            };
            config.getItemData = function(item) {
                return item
            };
            config.allowLoadByRange = void 0;
            return config
        };
        _proto2.renderSelectCheckBoxContainer = function($container, model) {
            var rowsView = this.component.getView("rowsView");
            var $checkbox = rowsView._renderSelectCheckBox($container, {
                value: model.row.isSelected,
                row: model.row,
                column: model.column
            });
            rowsView._attachCheckBoxClickEvent($checkbox)
        };
        _proto2._getSelectAllNodeKeys = function() {
            var component = this.component;
            var root = component.getRootNode();
            var cache = {};
            var keys = [];
            var isRecursiveSelection = this.isRecursiveSelection();
            root && _m_core.default.foreachNodes(root.children, (function(node) {
                if (void 0 !== node.key && (node.visible || isRecursiveSelection)) {
                    keys.push(node.key)
                }
                if (!node.visible) {
                    return true
                }
                return isRecursiveSelection ? false : component.isRowExpanded(node.key, cache)
            }));
            return keys
        };
        _proto2.isSelectAll = function() {
            var selectedRowKeys = this.option("selectedRowKeys") || [];
            if (0 === selectedRowKeys.length) {
                return false
            }
            var component = this.component;
            var visibleKeys = this._getSelectAllNodeKeys();
            var isRecursiveSelection = this.isRecursiveSelection();
            var hasIndeterminateState = false;
            var selectedVisibleKeys = visibleKeys.filter((function(key) {
                var isRowSelected = component.isRowSelected(key, isRecursiveSelection);
                if (void 0 === isRowSelected) {
                    hasIndeterminateState = true
                }
                return isRowSelected
            }));
            if (!selectedVisibleKeys.length) {
                return hasIndeterminateState ? void 0 : false
            }
            if (selectedVisibleKeys.length === visibleKeys.length) {
                return true
            }
            return
        };
        _proto2.selectAll = function() {
            var _this3 = this;
            var visibleKeys = this._getSelectAllNodeKeys().filter((function(key) {
                return !_this3.isRowSelected(key)
            }));
            this.focusedItemIndex(-1);
            return this.selectRows(visibleKeys, true)
        };
        _proto2.deselectAll = function() {
            var visibleKeys = this._getSelectAllNodeKeys();
            this.focusedItemIndex(-1);
            return this.deselectRows(visibleKeys)
        };
        _proto2.selectedItemKeys = function(value, preserve, isDeselect, isSelectAll) {
            var that = this;
            var selectedRowKeys = that.option("selectedRowKeys");
            var isRecursiveSelection = this.isRecursiveSelection();
            var normalizedArgs = isRecursiveSelection && that._normalizeSelectionArgs({
                keys: (0, _type.isDefined)(value) ? value : []
            }, preserve, !isDeselect);
            if (normalizedArgs && !(0, _common.equalByValue)(normalizedArgs.selectedRowKeys, selectedRowKeys)) {
                that._isSelectionNormalizing = true;
                return _Base.prototype.selectedItemKeys.call(this, normalizedArgs.selectedRowKeys, false, false, false).always((function() {
                    that._isSelectionNormalizing = false
                })).done((function(items) {
                    normalizedArgs.selectedRowsData = items;
                    that._fireSelectionChanged(normalizedArgs)
                }))
            }
            return _Base.prototype.selectedItemKeys.call(this, value, preserve, isDeselect, isSelectAll)
        };
        _proto2.changeItemSelection = function(itemIndex, keyboardKeys) {
            var _this4 = this;
            var isRecursiveSelection = this.isRecursiveSelection();
            var callBase = _Base.prototype.changeItemSelection.bind(this);
            if (isRecursiveSelection && !keyboardKeys.shift) {
                var key = this._dataController.getKeyByRowIndex(itemIndex);
                return this.selectedItemKeys(key, true, this.isRowSelected(key)).done((function() {
                    _this4.isRowSelected(key) && callBase(itemIndex, keyboardKeys, true)
                }))
            }
            return _Base.prototype.changeItemSelection.apply(this, arguments)
        };
        _proto2._updateParentSelectionState = function(node, isSelected) {
            var that = this;
            var state = isSelected;
            var parentNode = node.parent;
            if (parentNode) {
                if (parentNode.children.length > 1) {
                    if (false === isSelected) {
                        var hasSelectedState = parentNode.children.some((function(childNode) {
                            return that._selectionStateByKey[childNode.key]
                        }));
                        state = hasSelectedState ? void 0 : false
                    } else if (true === isSelected) {
                        var hasNonSelectedState = parentNode.children.some((function(childNode) {
                            return !that._selectionStateByKey[childNode.key]
                        }));
                        state = hasNonSelectedState ? void 0 : true
                    }
                }
                this._selectionStateByKey[parentNode.key] = state;
                if (parentNode.parent && parentNode.parent.level >= 0) {
                    this._updateParentSelectionState(parentNode, state)
                }
            }
        };
        _proto2._updateChildrenSelectionState = function(node, isSelected) {
            var that = this;
            var children = node.children;
            children && children.forEach((function(childNode) {
                that._selectionStateByKey[childNode.key] = isSelected;
                if (childNode.children.length > 0) {
                    that._updateChildrenSelectionState(childNode, isSelected)
                }
            }))
        };
        _proto2._updateSelectionStateCore = function(keys, isSelected) {
            var dataController = this._dataController;
            for (var i = 0; i < keys.length; i++) {
                this._selectionStateByKey[keys[i]] = isSelected;
                var node = dataController.getNodeByKey(keys[i]);
                if (node) {
                    this._updateParentSelectionState(node, isSelected);
                    this._updateChildrenSelectionState(node, isSelected)
                }
            }
        };
        _proto2._getSelectedParentKeys = function(key, selectedItemKeys, useCash) {
            var selectedParentNode;
            var node = this._dataController.getNodeByKey(key);
            var parentNode = node && node.parent;
            var result = [];
            while (parentNode && parentNode.level >= 0) {
                result.unshift(parentNode.key);
                var isSelected = useCash ? !nodeExists(selectedItemKeys, parentNode.key) && this.isRowSelected(parentNode.key) : selectedItemKeys.indexOf(parentNode.key) >= 0;
                if (isSelected) {
                    selectedParentNode = parentNode;
                    result = this._getSelectedParentKeys(selectedParentNode.key, selectedItemKeys, useCash).concat(result);
                    break
                } else if (useCash) {
                    break
                }
                parentNode = parentNode.parent
            }
            return selectedParentNode && result || []
        };
        _proto2._getSelectedChildKeys = function(key, keysToIgnore) {
            var _this5 = this;
            var childKeys = [];
            var node = this._dataController.getNodeByKey(key);
            node && _m_core.default.foreachNodes(node.children, (function(childNode) {
                var ignoreKeyIndex = keysToIgnore.indexOf(childNode.key);
                if (ignoreKeyIndex < 0) {
                    childKeys.push(childNode.key)
                }
                return ignoreKeyIndex > 0 || ignoreKeyIndex < 0 && void 0 === _this5._selectionStateByKey[childNode.key]
            }));
            return childKeys
        };
        _proto2._normalizeParentKeys = function(key, args) {
            var keysToIgnore = [key];
            var parentNodeKeys = this._getSelectedParentKeys(key, args.selectedRowKeys);
            if (parentNodeKeys.length) {
                keysToIgnore = keysToIgnore.concat(parentNodeKeys);
                keysToIgnore.forEach((function(key) {
                    var index = args.selectedRowKeys.indexOf(key);
                    if (index >= 0) {
                        args.selectedRowKeys.splice(index, 1)
                    }
                }));
                var childKeys = this._getSelectedChildKeys(parentNodeKeys[0], keysToIgnore);
                args.selectedRowKeys = args.selectedRowKeys.concat(childKeys)
            }
        };
        _proto2._normalizeChildrenKeys = function(key, args) {
            var _this6 = this;
            var node = this._dataController.getNodeByKey(key);
            node && node.children.forEach((function(childNode) {
                var index = args.selectedRowKeys.indexOf(childNode.key);
                if (index >= 0) {
                    args.selectedRowKeys.splice(index, 1)
                }
                _this6._normalizeChildrenKeys(childNode.key, args)
            }))
        };
        _proto2._normalizeSelectedRowKeysCore = function(keys, args, preserve, isSelect) {
            var that = this;
            keys.forEach((function(key) {
                if (preserve && that.isRowSelected(key) === isSelect) {
                    return
                }
                that._normalizeChildrenKeys(key, args);
                var index = args.selectedRowKeys.indexOf(key);
                if (isSelect) {
                    if (index < 0) {
                        args.selectedRowKeys.push(key)
                    }
                    args.currentSelectedRowKeys.push(key)
                } else {
                    if (index >= 0) {
                        args.selectedRowKeys.splice(index, 1)
                    }
                    args.currentDeselectedRowKeys.push(key);
                    that._normalizeParentKeys(key, args)
                }
            }))
        };
        _proto2._normalizeSelectionArgs = function(args, preserve, isSelect) {
            var result;
            var keys = Array.isArray(args.keys) ? args.keys : [args.keys];
            var selectedRowKeys = this.option("selectedRowKeys") || [];
            if (keys.length) {
                result = {
                    currentSelectedRowKeys: [],
                    currentDeselectedRowKeys: [],
                    selectedRowKeys: preserve ? selectedRowKeys.slice(0) : []
                };
                this._normalizeSelectedRowKeysCore(keys, result, preserve, isSelect)
            }
            return result
        };
        _proto2._updateSelectedItems = function(args) {
            this.updateSelectionState(args);
            _Base.prototype._updateSelectedItems.call(this, args)
        };
        _proto2._fireSelectionChanged = function() {
            if (!this._isSelectionNormalizing) {
                _Base.prototype._fireSelectionChanged.apply(this, arguments)
            }
        };
        _proto2._isModeLeavesOnly = function(mode) {
            return "leavesOnly" === mode
        };
        _proto2._removeDuplicatedKeys = function(keys) {
            var result = [];
            var processedKeys = {};
            keys.forEach((function(key) {
                if (!processedKeys[key]) {
                    processedKeys[key] = true;
                    result.push(key)
                }
            }));
            return result
        };
        _proto2._getAllChildKeys = function(key) {
            var childKeys = [];
            var node = this._dataController.getNodeByKey(key);
            node && _m_core.default.foreachNodes(node.children, (function(childNode) {
                childKeys.push(childNode.key)
            }), true);
            return childKeys
        };
        _proto2._getAllSelectedRowKeys = function(keys) {
            var _this7 = this;
            var result = [];
            keys.forEach((function(key) {
                var parentKeys = _this7._getSelectedParentKeys(key, [], true);
                var childKeys = _this7._getAllChildKeys(key);
                result.push.apply(result, parentKeys.concat([key], childKeys))
            }));
            result = this._removeDuplicatedKeys(result);
            return result
        };
        _proto2._getParentSelectedRowKeys = function(keys) {
            var that = this;
            var result = [];
            keys.forEach((function(key) {
                var parentKeys = that._getSelectedParentKeys(key, keys);
                !parentKeys.length && result.push(key)
            }));
            return result
        };
        _proto2._getLeafSelectedRowKeys = function(keys) {
            var result = [];
            var dataController = this._dataController;
            keys.forEach((function(key) {
                var node = dataController.getNodeByKey(key);
                node && !node.hasChildren && result.push(key)
            }));
            return result
        };
        _proto2.isRecursiveSelection = function() {
            var selectionMode = this.option("selection.mode");
            var isRecursive = this.option("selection.recursive");
            return "multiple" === selectionMode && isRecursive
        };
        _proto2.updateSelectionState = function(options) {
            var removedItemKeys = options.removedItemKeys || [];
            var selectedItemKeys = options.selectedItemKeys || [];
            if (this.isRecursiveSelection()) {
                this._updateSelectionStateCore(removedItemKeys, false);
                this._updateSelectionStateCore(selectedItemKeys, true)
            }
        };
        _proto2.isRowSelected = function(key, isRecursiveSelection) {
            var result = _Base.prototype.isRowSelected.apply(this, arguments);
            isRecursiveSelection = null !== isRecursiveSelection && void 0 !== isRecursiveSelection ? isRecursiveSelection : this.isRecursiveSelection();
            if (!result && isRecursiveSelection) {
                if (key in this._selectionStateByKey) {
                    return this._selectionStateByKey[key]
                }
                return false
            }
            return result
        };
        _proto2.getSelectedRowKeys = function(mode) {
            var that = this;
            if (!that._dataController) {
                return []
            }
            var selectedRowKeys = _Base.prototype.getSelectedRowKeys.apply(that, arguments);
            if (mode) {
                if (this.isRecursiveSelection()) {
                    selectedRowKeys = this._getAllSelectedRowKeys(selectedRowKeys)
                }
                if ("all" !== mode) {
                    if ("excludeRecursive" === mode) {
                        selectedRowKeys = that._getParentSelectedRowKeys(selectedRowKeys)
                    } else if (that._isModeLeavesOnly(mode)) {
                        selectedRowKeys = that._getLeafSelectedRowKeys(selectedRowKeys)
                    }
                }
            }
            return selectedRowKeys
        };
        _proto2.getSelectedRowsData = function(mode) {
            var dataController = this._dataController;
            var selectedKeys = this.getSelectedRowKeys(mode) || [];
            var selectedRowsData = [];
            selectedKeys.forEach((function(key) {
                var node = dataController.getNodeByKey(key);
                node && selectedRowsData.push(node.data)
            }));
            return selectedRowsData
        };
        _proto2.refresh = function() {
            this._selectionStateByKey = {};
            return _Base.prototype.refresh.apply(this, arguments)
        };
        return SelectionControllerTreeListExtender
    }(Base)
};
var columnHeadersView = function(Base) {
    return function(_columnHeadersSelecti) {
        _inheritsLoose(ColumnHeaderViewSelectionTreeListExtender, _columnHeadersSelecti);

        function ColumnHeaderViewSelectionTreeListExtender() {
            return _columnHeadersSelecti.apply(this, arguments) || this
        }
        var _proto3 = ColumnHeaderViewSelectionTreeListExtender.prototype;
        _proto3._processTemplate = function(template, options) {
            var that = this;
            var resultTemplate;
            var renderingTemplate = _columnHeadersSelecti.prototype._processTemplate.call(this, template, options);
            var firstDataColumnIndex = that._columnsController.getFirstDataColumnIndex();
            if (renderingTemplate && "header" === options.rowType && options.column.index === firstDataColumnIndex) {
                resultTemplate = {
                    render: function(options) {
                        if ("multiple" === that.option("selection.mode")) {
                            that.renderSelectAll(options.container, options.model)
                        }
                        renderingTemplate.render(options)
                    }
                }
            } else {
                resultTemplate = renderingTemplate
            }
            return resultTemplate
        };
        _proto3.renderSelectAll = function($cell, options) {
            $cell.addClass(TREELIST_SELECT_ALL_CLASS);
            this._renderSelectAllCheckBox($cell)
        };
        _proto3._isSortableElement = function($target) {
            return _columnHeadersSelecti.prototype._isSortableElement.call(this, $target) && !$target.closest(".".concat(SELECT_CHECKBOX_CLASS)).length
        };
        return ColumnHeaderViewSelectionTreeListExtender
    }((0, _m_selection.columnHeadersSelectionExtenderMixin)(Base))
};
var rowsView = function(Base) {
    return function(_rowsViewSelectionExt) {
        _inheritsLoose(RowsViewSelectionTreeListExtender, _rowsViewSelectionExt);

        function RowsViewSelectionTreeListExtender() {
            return _rowsViewSelectionExt.apply(this, arguments) || this
        }
        var _proto4 = RowsViewSelectionTreeListExtender.prototype;
        _proto4._renderIcons = function($iconContainer, options) {
            _rowsViewSelectionExt.prototype._renderIcons.apply(this, arguments);
            if (!options.row.isNewRow && "multiple" === this.option("selection.mode")) {
                this.getController("selection").renderSelectCheckBoxContainer($iconContainer, options)
            }
            return $iconContainer
        };
        _proto4._rowClick = function(e) {
            var $targetElement = (0, _renderer.default)(e.event.target);
            if (this.isExpandIcon($targetElement)) {
                _rowsViewSelectionExt.prototype._rowClickForTreeList.apply(this, arguments)
            } else {
                _rowsViewSelectionExt.prototype._rowClick.apply(this, arguments)
            }
        };
        return RowsViewSelectionTreeListExtender
    }((0, _m_selection.rowsViewSelectionExtenderMixin)(Base))
};
_m_core.default.registerModule("selection", (0, _extend.extend)(true, {}, _m_selection.selectionModule, {
    defaultOptions: function() {
        return (0, _extend.extend)(true, _m_selection.selectionModule.defaultOptions(), {
            selection: {
                showCheckBoxesMode: "always",
                recursive: false
            }
        })
    },
    extenders: {
        controllers: {
            data: data,
            selection: selection
        },
        views: {
            columnHeadersView: columnHeadersView,
            rowsView: rowsView
        }
    }
}));
