/**
 * DevExtreme (esm/__internal/ui/list/m_list.base.js)
 * Version: 23.2.9 (build 24294-0112)
 * Build date: Sun Oct 20 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
import fx from "../../../animation/fx";
import devices from "../../../core/devices";
import {
    getPublicElement
} from "../../../core/element";
import Guid from "../../../core/guid";
import $ from "../../../core/renderer";
import {
    BindableTemplate
} from "../../../core/templates/bindable_template";
import {
    ensureDefined,
    noop
} from "../../../core/utils/common";
import {
    compileGetter
} from "../../../core/utils/data";
import {
    Deferred
} from "../../../core/utils/deferred";
import {
    extend
} from "../../../core/utils/extend";
import {
    getImageContainer
} from "../../../core/utils/icon";
import {
    each
} from "../../../core/utils/iterator";
import {
    getHeight,
    getOuterHeight,
    setHeight
} from "../../../core/utils/size";
import {
    nativeScrolling
} from "../../../core/utils/support";
import {
    isDefined,
    isPlainObject
} from "../../../core/utils/type";
import {
    hasWindow
} from "../../../core/utils/window";
import {
    name as clickEventName
} from "../../../events/click";
import eventsEngine from "../../../events/core/events_engine";
import {
    end as swipeEventEnd
} from "../../../events/swipe";
import {
    addNamespace
} from "../../../events/utils/index";
import messageLocalization from "../../../localization/message";
import {
    getElementMargin
} from "../../../renovation/ui/scroll_view/utils/get_element_style";
import Button from "../../../ui/button";
import CollectionWidget from "../../../ui/collection/ui.collection_widget.live_update";
import ScrollView from "../../../ui/scroll_view";
import {
    current,
    isMaterial,
    isMaterialBased
} from "../../../ui/themes";
import {
    render
} from "../../../ui/widget/utils.ink_ripple";
import {
    deviceDependentOptions
} from "../../ui/scroll_view/m_scrollable.device";
import DataConverterMixin from "../../ui/shared/m_grouped_data_converter_mixin";
import ListItem from "./m_item";
var LIST_CLASS = "dx-list";
var LIST_ITEMS_CLASS = "dx-list-items";
var LIST_ITEM_CLASS = "dx-list-item";
var LIST_ITEM_SELECTOR = ".".concat(LIST_ITEM_CLASS);
var LIST_ITEM_ICON_CONTAINER_CLASS = "dx-list-item-icon-container";
var LIST_ITEM_ICON_CLASS = "dx-list-item-icon";
var LIST_GROUP_CLASS = "dx-list-group";
var LIST_GROUP_HEADER_CLASS = "dx-list-group-header";
var LIST_GROUP_BODY_CLASS = "dx-list-group-body";
var LIST_COLLAPSIBLE_GROUPS_CLASS = "dx-list-collapsible-groups";
var LIST_GROUP_COLLAPSED_CLASS = "dx-list-group-collapsed";
var LIST_GROUP_HEADER_INDICATOR_CLASS = "dx-list-group-header-indicator";
var LIST_HAS_NEXT_CLASS = "dx-has-next";
var LIST_NEXT_BUTTON_CLASS = "dx-list-next-button";
var WRAP_ITEM_TEXT_CLASS = "dx-wrap-item-text";
var SELECT_ALL_ITEM_SELECTOR = ".dx-list-select-all";
var LIST_ITEM_DATA_KEY = "dxListItemData";
var LIST_FEEDBACK_SHOW_TIMEOUT = 70;
var groupItemsGetter = compileGetter("items");
var _scrollView;
export var ListBase = CollectionWidget.inherit({
    _activeStateUnit: [LIST_ITEM_SELECTOR, SELECT_ALL_ITEM_SELECTOR].join(","),
    _supportedKeys() {
        var that = this;
        var moveFocusPerPage = function(direction) {
            var $item = getEdgeVisibleItem(direction);
            var isFocusedItem = $item.is(that.option("focusedElement"));
            if (isFocusedItem) {
                ! function($item, direction) {
                    var resultPosition = $item.position().top;
                    if ("prev" === direction) {
                        resultPosition = $item.position().top - getHeight(that.$element()) + getOuterHeight($item)
                    }
                    that.scrollTo(resultPosition)
                }($item, direction);
                $item = getEdgeVisibleItem(direction)
            }
            that.option("focusedElement", getPublicElement($item));
            that.scrollToItem($item)
        };

        function getEdgeVisibleItem(direction) {
            var scrollTop = that.scrollTop();
            var containerHeight = getHeight(that.$element());
            var $item = $(that.option("focusedElement"));
            var isItemVisible = true;
            if (!$item.length) {
                return $()
            }
            while (isItemVisible) {
                var $nextItem = $item[direction]();
                if (!$nextItem.length) {
                    break
                }
                var nextItemLocation = $nextItem.position().top + getOuterHeight($nextItem) / 2;
                isItemVisible = nextItemLocation < containerHeight + scrollTop && nextItemLocation > scrollTop;
                if (isItemVisible) {
                    $item = $nextItem
                }
            }
            return $item
        }
        return extend(this.callBase(), {
            leftArrow: noop,
            rightArrow: noop,
            pageUp() {
                moveFocusPerPage("prev");
                return false
            },
            pageDown() {
                moveFocusPerPage("next");
                return false
            }
        })
    },
    _getDefaultOptions() {
        return extend(this.callBase(), {
            hoverStateEnabled: true,
            pullRefreshEnabled: false,
            scrollingEnabled: true,
            selectByClick: true,
            showScrollbar: "onScroll",
            useNativeScrolling: true,
            bounceEnabled: true,
            scrollByContent: true,
            scrollByThumb: false,
            pullingDownText: messageLocalization.format("dxList-pullingDownText"),
            pulledDownText: messageLocalization.format("dxList-pulledDownText"),
            refreshingText: messageLocalization.format("dxList-refreshingText"),
            pageLoadingText: messageLocalization.format("dxList-pageLoadingText"),
            onScroll: null,
            onPullRefresh: null,
            onPageLoading: null,
            pageLoadMode: "scrollBottom",
            nextButtonText: messageLocalization.format("dxList-nextButtonText"),
            onItemSwipe: null,
            grouped: false,
            onGroupRendered: null,
            collapsibleGroups: false,
            groupTemplate: "group",
            indicateLoading: true,
            activeStateEnabled: true,
            _itemAttributes: {
                role: "option"
            },
            useInkRipple: false,
            wrapItemText: false,
            _swipeEnabled: true,
            showChevronExpr: data => data ? data.showChevron : void 0,
            badgeExpr: data => data ? data.badge : void 0
        })
    },
    _defaultOptionsRules() {
        var themeName = current();
        return this.callBase().concat(deviceDependentOptions(), [{
            device: () => !nativeScrolling,
            options: {
                useNativeScrolling: false
            }
        }, {
            device: device => !nativeScrolling && !devices.isSimulator() && "desktop" === devices.real().deviceType && "generic" === device.platform,
            options: {
                showScrollbar: "onHover",
                pageLoadMode: "nextButton"
            }
        }, {
            device: () => "desktop" === devices.real().deviceType && !devices.isSimulator(),
            options: {
                focusStateEnabled: true
            }
        }, {
            device: () => isMaterial(themeName),
            options: {
                useInkRipple: true
            }
        }, {
            device: () => isMaterialBased(themeName),
            options: {
                pullingDownText: "",
                pulledDownText: "",
                refreshingText: "",
                pageLoadingText: ""
            }
        }])
    },
    _visibilityChanged(visible) {
        if (visible) {
            this._updateLoadingState(true)
        }
    },
    _itemClass: () => LIST_ITEM_CLASS,
    _itemDataKey: () => LIST_ITEM_DATA_KEY,
    _itemContainer() {
        return this._$container
    },
    _getItemsContainer() {
        return this._$listContainer
    },
    _cleanItemContainer() {
        this.callBase();
        var listContainer = this._getItemsContainer();
        $(listContainer).empty();
        listContainer.appendTo(this._$container)
    },
    _saveSelectionChangeEvent(e) {
        this._selectionChangeEventInstance = e
    },
    _getSelectionChangeEvent() {
        return this._selectionChangeEventInstance
    },
    _refreshItemElements() {
        if (!this.option("grouped")) {
            this._itemElementsCache = this._getItemsContainer().children(this._itemSelector())
        } else {
            this._itemElementsCache = this._getItemsContainer().children(".".concat(LIST_GROUP_CLASS)).children(".".concat(LIST_GROUP_BODY_CLASS)).children(this._itemSelector())
        }
    },
    _modifyByChanges() {
        this.callBase.apply(this, arguments);
        this._refreshItemElements();
        this._updateLoadingState(true)
    },
    reorderItem(itemElement, toItemElement) {
        var promise = this.callBase(itemElement, toItemElement);
        return promise.done((function() {
            this._refreshItemElements()
        }))
    },
    deleteItem(itemElement) {
        var promise = this.callBase(itemElement);
        return promise.done((function() {
            this._refreshItemElements()
        }))
    },
    _itemElements() {
        return this._itemElementsCache
    },
    _itemSelectHandler(e) {
        if ("single" === this.option("selectionMode") && this.isItemSelected(e.currentTarget)) {
            return
        }
        return this.callBase(e)
    },
    _allowDynamicItemsAppend: () => true,
    _init() {
        this.callBase();
        this._dataController.resetDataSourcePageIndex();
        this._$container = this.$element();
        this._$listContainer = $("<div>").addClass(LIST_ITEMS_CLASS);
        this._initScrollView();
        this._feedbackShowTimeout = LIST_FEEDBACK_SHOW_TIMEOUT;
        this._createGroupRenderAction()
    },
    _scrollBottomMode() {
        return "scrollBottom" === this.option("pageLoadMode")
    },
    _nextButtonMode() {
        return "nextButton" === this.option("pageLoadMode")
    },
    _dataSourceOptions() {
        var scrollBottom = this._scrollBottomMode();
        var nextButton = this._nextButtonMode();
        return extend(this.callBase(), {
            paginate: ensureDefined(scrollBottom || nextButton, true)
        })
    },
    _getGroupedOption() {
        return this.option("grouped")
    },
    _getGroupContainerByIndex(groupIndex) {
        return this._getItemsContainer().find(".".concat(LIST_GROUP_CLASS)).eq(groupIndex).find(".".concat(LIST_GROUP_BODY_CLASS))
    },
    _dataSourceFromUrlLoadMode: () => "raw",
    _initScrollView() {
        var scrollingEnabled = this.option("scrollingEnabled");
        var pullRefreshEnabled = scrollingEnabled && this.option("pullRefreshEnabled");
        var autoPagingEnabled = scrollingEnabled && this._scrollBottomMode() && !!this._dataController.getDataSource();
        this._scrollView = this._createComponent(this.$element(), getScrollView(), {
            height: this.option("height"),
            width: this.option("width"),
            disabled: this.option("disabled") || !scrollingEnabled,
            onScroll: this._scrollHandler.bind(this),
            onPullDown: pullRefreshEnabled ? this._pullDownHandler.bind(this) : null,
            onReachBottom: autoPagingEnabled ? this._scrollBottomHandler.bind(this) : null,
            showScrollbar: this.option("showScrollbar"),
            useNative: this.option("useNativeScrolling"),
            bounceEnabled: this.option("bounceEnabled"),
            scrollByContent: this.option("scrollByContent"),
            scrollByThumb: this.option("scrollByThumb"),
            pullingDownText: this.option("pullingDownText"),
            pulledDownText: this.option("pulledDownText"),
            refreshingText: this.option("refreshingText"),
            reachBottomText: this.option("pageLoadingText"),
            useKeyboard: false
        });
        this._$container = $(this._scrollView.content());
        this._$listContainer.appendTo(this._$container);
        this._toggleWrapItemText(this.option("wrapItemText"));
        this._createScrollViewActions()
    },
    _toggleWrapItemText(value) {
        this._$listContainer.toggleClass(WRAP_ITEM_TEXT_CLASS, value)
    },
    _createScrollViewActions() {
        this._scrollAction = this._createActionByOption("onScroll");
        this._pullRefreshAction = this._createActionByOption("onPullRefresh");
        this._pageLoadingAction = this._createActionByOption("onPageLoading")
    },
    _scrollHandler(e) {
        this._scrollAction && this._scrollAction(e)
    },
    _initTemplates() {
        this._templateManager.addDefaultTemplates({
            group: new BindableTemplate(($container, data) => {
                if (isPlainObject(data)) {
                    if (data.key) {
                        $container.text(data.key)
                    }
                } else {
                    $container.text(String(data))
                }
            }, ["key"], this.option("integrationOptions.watchMethod"))
        });
        this.callBase()
    },
    _prepareDefaultItemTemplate(data, $container) {
        this.callBase(data, $container);
        if (data.icon) {
            var $icon = getImageContainer(data.icon).addClass(LIST_ITEM_ICON_CLASS);
            var $iconContainer = $("<div>").addClass(LIST_ITEM_ICON_CONTAINER_CLASS);
            $iconContainer.append($icon);
            $container.prepend($iconContainer)
        }
    },
    _getBindableFields: () => ["text", "html", "icon"],
    _updateLoadingState(tryLoadMore) {
        var dataController = this._dataController;
        var shouldLoadNextPage = this._scrollBottomMode() && tryLoadMore && !dataController.isLoading() && !this._isLastPage();
        if (this._shouldContinueLoading(shouldLoadNextPage)) {
            this._infiniteDataLoading()
        } else {
            this._scrollView.release(!shouldLoadNextPage && !dataController.isLoading());
            this._toggleNextButton(this._shouldRenderNextButton() && !this._isLastPage());
            this._loadIndicationSuppressed(false)
        }
    },
    _shouldRenderNextButton() {
        return this._nextButtonMode() && this._dataController.isLoaded()
    },
    _isDataSourceFirstLoadCompleted(newValue) {
        if (isDefined(newValue)) {
            this._isFirstLoadCompleted = newValue
        }
        return this._isFirstLoadCompleted
    },
    _dataSourceLoadingChangedHandler(isLoading) {
        if (this._loadIndicationSuppressed()) {
            return
        }
        if (isLoading && this.option("indicateLoading")) {
            this._showLoadingIndicatorTimer = setTimeout(() => {
                var _a;
                var isEmpty = !this._itemElements().length;
                var shouldIndicateLoading = !isEmpty || this._isDataSourceFirstLoadCompleted();
                if (shouldIndicateLoading) {
                    null === (_a = this._scrollView) || void 0 === _a ? void 0 : _a.startLoading()
                }
            })
        } else {
            clearTimeout(this._showLoadingIndicatorTimer);
            this._scrollView && this._scrollView.finishLoading()
        }
        if (!isLoading) {
            this._isDataSourceFirstLoadCompleted(false)
        }
    },
    _dataSourceChangedHandler() {
        if (!this._shouldAppendItems() && hasWindow()) {
            this._scrollView && this._scrollView.scrollTo(0)
        }
        this.callBase.apply(this, arguments);
        this._isDataSourceFirstLoadCompleted(true)
    },
    _refreshContent() {
        this._prepareContent();
        this._fireContentReadyAction()
    },
    _hideLoadingIfLoadIndicationOff() {
        if (!this.option("indicateLoading")) {
            this._dataSourceLoadingChangedHandler(false)
        }
    },
    _loadIndicationSuppressed(value) {
        if (!arguments.length) {
            return this._isLoadIndicationSuppressed
        }
        this._isLoadIndicationSuppressed = value
    },
    _scrollViewIsFull() {
        var scrollView = this._scrollView;
        return !scrollView || getHeight(scrollView.content()) > getHeight(scrollView.container())
    },
    _pullDownHandler(e) {
        this._pullRefreshAction(e);
        var dataController = this._dataController;
        if (dataController.getDataSource() && !dataController.isLoading()) {
            this._clearSelectedItems();
            dataController.pageIndex(0);
            dataController.reload()
        } else {
            this._updateLoadingState()
        }
    },
    _shouldContinueLoading(shouldLoadNextPage) {
        var _a, _b;
        var isBottomReached = getHeight(this._scrollView.content()) - getHeight(this._scrollView.container()) < (null !== (_b = null === (_a = this._scrollView.scrollOffset()) || void 0 === _a ? void 0 : _a.top) && void 0 !== _b ? _b : 0);
        return shouldLoadNextPage && (!this._scrollViewIsFull() || isBottomReached)
    },
    _infiniteDataLoading() {
        var isElementVisible = this.$element().is(":visible");
        if (isElementVisible) {
            clearTimeout(this._loadNextPageTimer);
            this._loadNextPageTimer = setTimeout(() => {
                this._loadNextPage()
            })
        }
    },
    _scrollBottomHandler(e) {
        this._pageLoadingAction(e);
        var dataController = this._dataController;
        if (!dataController.isLoading() && !this._isLastPage()) {
            this._loadNextPage()
        } else {
            this._updateLoadingState()
        }
    },
    _renderItems(items) {
        if (this.option("grouped")) {
            each(items, this._renderGroup.bind(this));
            this._attachGroupCollapseEvent();
            this._renderEmptyMessage();
            if (isMaterial()) {
                this.attachGroupHeaderInkRippleEvents()
            }
        } else {
            this.callBase.apply(this, arguments)
        }
        this._refreshItemElements();
        this._updateLoadingState(true)
    },
    _attachGroupCollapseEvent() {
        var eventName = addNamespace(clickEventName, this.NAME);
        var selector = ".".concat(LIST_GROUP_HEADER_CLASS);
        var $element = this.$element();
        var collapsibleGroups = this.option("collapsibleGroups");
        $element.toggleClass(LIST_COLLAPSIBLE_GROUPS_CLASS, collapsibleGroups);
        eventsEngine.off($element, eventName, selector);
        if (collapsibleGroups) {
            eventsEngine.on($element, eventName, selector, e => {
                this._createAction(e => {
                    var $group = $(e.event.currentTarget).parent();
                    this._collapseGroupHandler($group);
                    if (this.option("focusStateEnabled")) {
                        this.option("focusedElement", getPublicElement($group.find(".".concat(LIST_ITEM_CLASS)).eq(0)))
                    }
                }, {
                    validatingTargetName: "element"
                })({
                    event: e
                })
            })
        }
    },
    _collapseGroupHandler($group, toggle) {
        var deferred = Deferred();
        if ($group.hasClass(LIST_GROUP_COLLAPSED_CLASS) === toggle) {
            return deferred.resolve()
        }
        var $groupBody = $group.children(".".concat(LIST_GROUP_BODY_CLASS));
        var startHeight = getOuterHeight($groupBody);
        var endHeight = 0;
        if (0 === startHeight) {
            setHeight($groupBody, "auto");
            endHeight = getOuterHeight($groupBody)
        }
        $group.toggleClass(LIST_GROUP_COLLAPSED_CLASS, toggle);
        fx.animate($groupBody, {
            type: "custom",
            from: {
                height: startHeight
            },
            to: {
                height: endHeight
            },
            duration: 200,
            complete: function() {
                this.updateDimensions();
                this._updateLoadingState(true);
                deferred.resolve()
            }.bind(this)
        });
        return deferred.promise()
    },
    _dataSourceLoadErrorHandler() {
        this._forgetNextPageLoading();
        if (this._initialized) {
            this._renderEmptyMessage();
            this._updateLoadingState()
        }
    },
    _initMarkup() {
        this._itemElementsCache = $();
        this.$element().addClass(LIST_CLASS);
        this.callBase();
        this.option("useInkRipple") && this._renderInkRipple();
        this.setAria({
            role: "group",
            roledescription: "list"
        }, this.$element());
        this.setAria({
            role: "group"
        }, this._focusTarget());
        this._setListAria()
    },
    _setListAria() {
        var {
            items: items
        } = this.option();
        var listArea = (null === items || void 0 === items ? void 0 : items.length) ? {
            role: "listbox",
            label: "Items"
        } : {
            role: void 0,
            label: void 0
        };
        this.setAria(listArea, this._$listContainer)
    },
    _focusTarget() {
        return this._itemContainer()
    },
    _renderInkRipple() {
        this._inkRipple = render()
    },
    _toggleActiveState($element, value, e) {
        this.callBase.apply(this, arguments);
        var that = this;
        if (!this._inkRipple) {
            return
        }
        var config = {
            element: $element,
            event: e
        };
        if (value) {
            if (isMaterial()) {
                this._inkRippleTimer = setTimeout(() => {
                    that._inkRipple.showWave(config)
                }, LIST_FEEDBACK_SHOW_TIMEOUT / 2)
            } else {
                that._inkRipple.showWave(config)
            }
        } else {
            clearTimeout(this._inkRippleTimer);
            this._inkRipple.hideWave(config)
        }
    },
    _postprocessRenderItem(args) {
        this._refreshItemElements();
        this.callBase.apply(this, arguments);
        if (this.option("_swipeEnabled")) {
            this._attachSwipeEvent($(args.itemElement))
        }
    },
    _attachSwipeEvent($itemElement) {
        var endEventName = addNamespace(swipeEventEnd, this.NAME);
        eventsEngine.on($itemElement, endEventName, this._itemSwipeEndHandler.bind(this))
    },
    _itemSwipeEndHandler(e) {
        this._itemDXEventHandler(e, "onItemSwipe", {
            direction: e.offset < 0 ? "left" : "right"
        })
    },
    _nextButtonHandler(e) {
        this._pageLoadingAction(e);
        var dataController = this._dataController;
        if (dataController.getDataSource() && !dataController.isLoading()) {
            this._scrollView.toggleLoading(true);
            this._$nextButton.detach();
            this._loadIndicationSuppressed(true);
            this._loadNextPage()
        }
    },
    _renderGroup(index, group) {
        var $groupElement = $("<div>").addClass(LIST_GROUP_CLASS).appendTo(this._getItemsContainer());
        var id = "dx-".concat((new Guid).toString());
        var groupAria = {
            role: "group",
            labelledby: id
        };
        this.setAria(groupAria, $groupElement);
        var $groupHeaderElement = $("<div>").addClass(LIST_GROUP_HEADER_CLASS).attr("id", id).appendTo($groupElement);
        var groupTemplateName = this.option("groupTemplate");
        var groupTemplate = this._getTemplate(group.template || groupTemplateName, group, index, $groupHeaderElement);
        var renderArgs = {
            index: index,
            itemData: group,
            container: getPublicElement($groupHeaderElement)
        };
        this._createItemByTemplate(groupTemplate, renderArgs);
        $("<div>").addClass(LIST_GROUP_HEADER_INDICATOR_CLASS).prependTo($groupHeaderElement);
        this._renderingGroupIndex = index;
        var $groupBody = $("<div>").addClass(LIST_GROUP_BODY_CLASS).appendTo($groupElement);
        each(groupItemsGetter(group) || [], (itemIndex, item) => {
            this._renderItem({
                group: index,
                item: itemIndex
            }, item, $groupBody)
        });
        this._groupRenderAction({
            groupElement: getPublicElement($groupElement),
            groupIndex: index,
            groupData: group
        })
    },
    downInkRippleHandler(e) {
        this._toggleActiveState($(e.currentTarget), true, e)
    },
    upInkRippleHandler(e) {
        this._toggleActiveState($(e.currentTarget), false)
    },
    attachGroupHeaderInkRippleEvents() {
        var selector = ".".concat(LIST_GROUP_HEADER_CLASS);
        var $element = this.$element();
        this._downInkRippleHandler = this._downInkRippleHandler || this.downInkRippleHandler.bind(this);
        this._upInkRippleHandler = this._upInkRippleHandler || this.upInkRippleHandler.bind(this);
        var downArguments = [$element, "dxpointerdown", selector, this._downInkRippleHandler];
        var upArguments = [$element, "dxpointerup dxpointerout", selector, this._upInkRippleHandler];
        eventsEngine.off(...downArguments);
        eventsEngine.on(...downArguments);
        eventsEngine.off(...upArguments);
        eventsEngine.on(...upArguments)
    },
    _createGroupRenderAction() {
        this._groupRenderAction = this._createActionByOption("onGroupRendered")
    },
    _clean() {
        clearTimeout(this._inkRippleTimer);
        if (this._$nextButton) {
            this._$nextButton.remove();
            this._$nextButton = null
        }
        this.callBase.apply(this, arguments)
    },
    _dispose() {
        this._isDataSourceFirstLoadCompleted(false);
        clearTimeout(this._holdTimer);
        clearTimeout(this._loadNextPageTimer);
        clearTimeout(this._showLoadingIndicatorTimer);
        this.callBase()
    },
    _toggleDisabledState(value) {
        this.callBase(value);
        this._scrollView.option("disabled", value || !this.option("scrollingEnabled"))
    },
    _toggleNextButton(value) {
        var dataController = this._dataController;
        var $nextButton = this._getNextButton();
        this.$element().toggleClass(LIST_HAS_NEXT_CLASS, value);
        if (value && dataController.isLoaded()) {
            $nextButton.appendTo(this._itemContainer())
        }
        if (!value) {
            $nextButton.detach()
        }
    },
    _getNextButton() {
        if (!this._$nextButton) {
            this._$nextButton = this._createNextButton()
        }
        return this._$nextButton
    },
    _createNextButton() {
        var $result = $("<div>").addClass(LIST_NEXT_BUTTON_CLASS);
        var $button = $("<div>").appendTo($result);
        this._createComponent($button, Button, {
            text: this.option("nextButtonText"),
            onClick: this._nextButtonHandler.bind(this),
            type: isMaterialBased() ? "default" : void 0,
            integrationOptions: {}
        });
        return $result
    },
    _moveFocus() {
        this.callBase.apply(this, arguments);
        this.scrollToItem(this.option("focusedElement"))
    },
    _refresh() {
        if (!hasWindow()) {
            this.callBase()
        } else {
            var scrollTop = this._scrollView.scrollTop();
            this.callBase();
            scrollTop && this._scrollView.scrollTo(scrollTop)
        }
    },
    _optionChanged(args) {
        switch (args.name) {
            case "pageLoadMode":
                this._toggleNextButton(args.value);
                this._initScrollView();
                break;
            case "dataSource":
                this.callBase(args);
                this._initScrollView();
                this._isDataSourceFirstLoadCompleted(false);
                break;
            case "items":
                this.callBase(args);
                this._isDataSourceFirstLoadCompleted(false);
                break;
            case "pullingDownText":
            case "pulledDownText":
            case "refreshingText":
            case "pageLoadingText":
            case "showScrollbar":
            case "bounceEnabled":
            case "scrollByContent":
            case "scrollByThumb":
            case "useNativeScrolling":
            case "scrollingEnabled":
            case "pullRefreshEnabled":
                this._initScrollView();
                this._updateLoadingState(true);
                break;
            case "nextButtonText":
            case "onItemSwipe":
            case "useInkRipple":
                this._invalidate();
                break;
            case "onScroll":
            case "onPullRefresh":
            case "onPageLoading":
                this._createScrollViewActions();
                break;
            case "grouped":
            case "collapsibleGroups":
            case "groupTemplate":
                this._invalidate();
                break;
            case "wrapItemText":
                this._toggleWrapItemText(args.value);
                break;
            case "onGroupRendered":
                this._createGroupRenderAction();
                break;
            case "width":
            case "height":
                this.callBase(args);
                this._scrollView.option(args.name, args.value);
                this._scrollView.update();
                break;
            case "indicateLoading":
                this._hideLoadingIfLoadIndicationOff();
                break;
            case "visible":
                this.callBase(args);
                this._scrollView.update();
                break;
            case "rtlEnabled":
                this._initScrollView();
                this.callBase(args);
                break;
            case "showChevronExpr":
            case "badgeExpr":
                this._invalidate();
                break;
            case "_swipeEnabled":
            case "selectByClick":
                break;
            default:
                this.callBase(args)
        }
    },
    _extendActionArgs($itemElement) {
        if (!this.option("grouped")) {
            return this.callBase($itemElement)
        }
        var $group = $itemElement.closest(".".concat(LIST_GROUP_CLASS));
        var $item = $group.find(".".concat(LIST_ITEM_CLASS));
        return extend(this.callBase($itemElement), {
            itemIndex: {
                group: $group.index(),
                item: $item.index($itemElement)
            }
        })
    },
    expandGroup(groupIndex) {
        var deferred = Deferred();
        var $group = this._getItemsContainer().find(".".concat(LIST_GROUP_CLASS)).eq(groupIndex);
        this._collapseGroupHandler($group, false).done(() => {
            deferred.resolveWith(this)
        });
        return deferred.promise()
    },
    collapseGroup(groupIndex) {
        var deferred = Deferred();
        var $group = this._getItemsContainer().find(".".concat(LIST_GROUP_CLASS)).eq(groupIndex);
        this._collapseGroupHandler($group, true).done(() => {
            deferred.resolveWith(this)
        });
        return deferred
    },
    updateDimensions() {
        var that = this;
        var deferred = Deferred();
        if (that._scrollView) {
            that._scrollView.update().done(() => {
                !that._scrollViewIsFull() && that._updateLoadingState(true);
                deferred.resolveWith(that)
            })
        } else {
            deferred.resolveWith(that)
        }
        return deferred.promise()
    },
    reload() {
        this.callBase();
        this.scrollTo(0);
        this._pullDownHandler()
    },
    repaint() {
        this.scrollTo(0);
        this.callBase()
    },
    scrollTop() {
        return this._scrollView.scrollOffset().top
    },
    clientHeight() {
        return this._scrollView.clientHeight()
    },
    scrollHeight() {
        return this._scrollView.scrollHeight()
    },
    scrollBy(distance) {
        this._scrollView.scrollBy(distance)
    },
    scrollTo(location) {
        this._scrollView.scrollTo(location)
    },
    scrollToItem(itemElement) {
        var $item = this._editStrategy.getItemElement(itemElement);
        var item = null === $item || void 0 === $item ? void 0 : $item.get(0);
        this._scrollView.scrollToElement(item, {
            bottom: getElementMargin(item, "bottom")
        })
    },
    _dimensionChanged() {
        this.updateDimensions()
    }
}).include(DataConverterMixin);
ListBase.ItemClass = ListItem;

function getScrollView() {
    return _scrollView || ScrollView
}
export function setScrollView(value) {
    _scrollView = value
}
