/**
 * DevExtreme (esm/__internal/ui/m_lookup.js)
 * Version: 24.1.7-build-24272-1937
 * Build date: Sat Sep 28 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
import {
    locate,
    move,
    resetPosition
} from "../../animation/translator";
import registerComponent from "../../core/component_registrator";
import devices from "../../core/devices";
import {
    getPublicElement
} from "../../core/element";
import {
    getFieldName
} from "../../core/options/utils";
import $ from "../../core/renderer";
import {
    ChildDefaultTemplate
} from "../../core/templates/child_default_template";
import {
    noop
} from "../../core/utils/common";
import {
    extend
} from "../../core/utils/extend";
import {
    each
} from "../../core/utils/iterator";
import {
    getHeight,
    getOuterHeight,
    getOuterWidth,
    getWidth
} from "../../core/utils/size";
import {
    nativeScrolling
} from "../../core/utils/support";
import {
    isDefined
} from "../../core/utils/type";
import {
    getWindow
} from "../../core/utils/window";
import eventsEngine from "../../events/core/events_engine";
import messageLocalization from "../../localization/message";
import DropDownList from "../../ui/drop_down_editor/ui.drop_down_list";
import Popover from "../../ui/popover/ui.popover";
import TextBox from "../../ui/text_box";
import {
    current,
    isMaterial
} from "../../ui/themes";
import {
    getElementWidth
} from "../ui/drop_down_editor/m_utils";
const window = getWindow();
const LOOKUP_CLASS = "dx-lookup";
const LOOKUP_SEARCH_CLASS = "dx-lookup-search";
const LOOKUP_SEARCH_WRAPPER_CLASS = "dx-lookup-search-wrapper";
const LOOKUP_FIELD_CLASS = "dx-lookup-field";
const LOOKUP_ARROW_CLASS = "dx-lookup-arrow";
const LOOKUP_FIELD_WRAPPER_CLASS = "dx-lookup-field-wrapper";
const LOOKUP_POPUP_CLASS = "dx-lookup-popup";
const LOOKUP_POPUP_WRAPPER_CLASS = "dx-lookup-popup-wrapper";
const LOOKUP_POPUP_SEARCH_CLASS = "dx-lookup-popup-search";
const LOOKUP_POPOVER_MODE = "dx-lookup-popover-mode";
const LOOKUP_EMPTY_CLASS = "dx-lookup-empty";
const LOOKUP_POPOVER_FLIP_VERTICAL_CLASS = "dx-popover-flipped-vertical";
const TEXTEDITOR_INPUT_CLASS = "dx-texteditor-input";
const TEXTEDITOR_EMPTY_CLASS = "dx-texteditor-empty";
const LIST_ITEM_CLASS = "dx-list-item";
const LIST_ITEM_SELECTED_CLASS = "dx-list-item-selected";
const GROUP_LIST_HEADER_CLASS = "dx-list-group-header";
const MATERIAL_LOOKUP_LIST_ITEMS_COUNT = 5;
const MATERIAL_LOOKUP_LIST_PADDING = 8;
const WINDOW_RATIO = .8;
const Lookup = DropDownList.inherit({
    _supportedKeys() {
        return extend(this.callBase(), {
            space(e) {
                e.preventDefault();
                this._validatedOpening()
            },
            enter() {
                this._validatedOpening()
            }
        })
    },
    _getDefaultOptions() {
        const getSize = side => {
            let size;
            if ("phone" === devices.real().deviceType && window.visualViewport) {
                size = window.visualViewport[side]
            } else {
                size = "width" === side ? getWidth(window) : getHeight(window)
            }
            return .8 * size
        };
        return extend(this.callBase(), {
            placeholder: messageLocalization.format("Select"),
            searchPlaceholder: messageLocalization.format("Search"),
            searchEnabled: true,
            searchStartEvent: "input change keyup",
            cleanSearchOnOpening: true,
            showCancelButton: true,
            showClearButton: false,
            clearButtonText: messageLocalization.format("Clear"),
            applyButtonText: messageLocalization.format("OK"),
            pullRefreshEnabled: false,
            useNativeScrolling: true,
            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"),
            grouped: false,
            groupTemplate: "group",
            usePopover: false,
            openOnFieldClick: true,
            showDropDownButton: false,
            focusStateEnabled: false,
            dropDownOptions: {
                showTitle: true,
                width: () => getSize("width"),
                height: () => getSize("height"),
                shading: true,
                hideOnOutsideClick: false,
                position: void 0,
                animation: {},
                title: "",
                titleTemplate: "title",
                onTitleRendered: null,
                fullScreen: false
            },
            dropDownCentered: false,
            _scrollToSelectedItemEnabled: false,
            useHiddenSubmitElement: true
        })
    },
    _setDeprecatedOptions() {
        this.callBase();
        extend(this._deprecatedOptions, {
            valueChangeEvent: {
                since: "22.1",
                alias: "searchStartEvent"
            }
        })
    },
    _defaultOptionsRules() {
        const themeName = current();
        return this.callBase().concat([{
            device: () => !nativeScrolling,
            options: {
                useNativeScrolling: false
            }
        }, {
            device: device => !devices.isSimulator() && "desktop" === devices.real().deviceType && "generic" === device.platform,
            options: {
                usePopover: true,
                dropDownOptions: {
                    height: "auto"
                }
            }
        }, {
            device: {
                platform: "ios",
                phone: true
            },
            options: {
                dropDownOptions: {
                    fullScreen: true
                }
            }
        }, {
            device: {
                platform: "ios",
                tablet: true
            },
            options: {
                dropDownOptions: {
                    width: () => .4 * Math.min(getWidth(window), getHeight(window)),
                    height: "auto"
                },
                usePopover: true
            }
        }, {
            device: () => "desktop" === devices.real().deviceType && !devices.isSimulator(),
            options: {
                focusStateEnabled: true
            }
        }, {
            device: () => isMaterial(themeName),
            options: {
                usePopover: false,
                searchEnabled: false,
                showCancelButton: false,
                dropDownCentered: true,
                _scrollToSelectedItemEnabled: true,
                dropDownOptions: {
                    hideOnOutsideClick: true,
                    _ignoreFunctionValueDeprecation: true,
                    width: () => getElementWidth(this.$element()),
                    height: function() {
                        return this._getPopupHeight()
                    }.bind(this),
                    showTitle: false,
                    shading: false
                }
            }
        }])
    },
    _init() {
        this.callBase();
        this._initActions()
    },
    _initActions() {
        this.callBase();
        this._initScrollAction();
        this._initPageLoadingAction();
        this._initPullRefreshAction()
    },
    _initPageLoadingAction() {
        this._pageLoadingAction = this._createActionByOption("onPageLoading")
    },
    _initPullRefreshAction() {
        this._pullRefreshAction = this._createActionByOption("onPullRefresh")
    },
    _initScrollAction() {
        this._scrollAction = this._createActionByOption("onScroll")
    },
    _scrollHandler(e) {
        this._scrollAction(e)
    },
    _pullRefreshHandler(e) {
        this._pullRefreshAction(e)
    },
    _pageLoadingHandler(e) {
        this._pageLoadingAction(e)
    },
    _initTemplates() {
        this.callBase();
        this._templateManager.addDefaultTemplates({
            group: new ChildDefaultTemplate("group"),
            title: new ChildDefaultTemplate("title")
        })
    },
    _initMarkup() {
        this.$element().addClass("dx-lookup").toggleClass(LOOKUP_POPOVER_MODE, this.option("usePopover"));
        this.callBase()
    },
    _inputWrapper() {
        return this.$element().find(".dx-lookup-field-wrapper")
    },
    _dataSourceOptions() {
        return extend(this.callBase(), {
            paginate: true
        })
    },
    _fireContentReadyAction: noop,
    _popupWrapperClass: () => "",
    _renderInput() {
        this._$field = $("<div>").addClass("dx-lookup-field");
        this._applyInputAttributes(this.option("inputAttr"));
        const $arrow = $("<div>").addClass("dx-lookup-arrow");
        this._$fieldWrapper = $("<div>").addClass("dx-lookup-field-wrapper").append(this._$field).append($arrow).appendTo(this.$element())
    },
    _applyInputAttributes(attributes) {
        this._$field.attr(attributes)
    },
    _getInputContainer() {
        return this._$fieldWrapper
    },
    _renderField() {
        const fieldTemplate = this._getTemplateByOption("fieldTemplate");
        if (fieldTemplate && this.option("fieldTemplate")) {
            this._renderFieldTemplate(fieldTemplate);
            return
        }
        const displayValue = this.option("displayValue");
        this._updateField(displayValue);
        const isFieldEmpty = !this.option("selectedItem");
        this.$element().toggleClass("dx-lookup-empty", isFieldEmpty).toggleClass("dx-texteditor-empty", isFieldEmpty)
    },
    _getLabelContainer() {
        return this._$field
    },
    _renderDisplayText(text) {
        if (this._input().length) {
            this.callBase(text)
        } else {
            this._updateField(text)
        }
    },
    _updateField(text) {
        text = isDefined(text) && String(text);
        this._$field.empty();
        if (text) {
            this._$field.text(text)
        } else {
            const $placeholder = $("<div>").attr({
                "data-dx_placeholder": this.option("placeholder")
            });
            this._$field.append($placeholder);
            $placeholder.addClass("dx-placeholder")
        }
    },
    _renderButtonContainers: noop,
    _renderFieldTemplate(template) {
        this._$field.empty();
        const data = this._fieldRenderData();
        template.render({
            model: data,
            container: getPublicElement(this._$field)
        })
    },
    _fieldRenderData() {
        return this.option("selectedItem")
    },
    _popupShowingHandler() {
        this.callBase.apply(this, arguments);
        if (this.option("cleanSearchOnOpening")) {
            if (this.option("searchEnabled") && this._searchBox.option("value")) {
                this._searchBox.option("value", "");
                this._searchCanceled()
            }
            this._list && this._list.option("focusedElement", null)
        }
        if (this.option("dropDownOptions.fullScreen") && this.option("_scrollToSelectedItemEnabled")) {
            this._popup.option("position").of = $(window)
        }
    },
    _popupShownHandler() {
        const scrollToSelectedItemEnabled = this.option("_scrollToSelectedItemEnabled");
        const fullScreen = this.option("dropDownOptions.fullScreen");
        if (!fullScreen && scrollToSelectedItemEnabled) {
            this._setPopupPosition()
        }
        this.callBase()
    },
    _scrollToSelectedItem() {
        const selectedIndex = this._list.option("selectedIndex");
        const listItems = this._list.option("items");
        const itemsCount = listItems.length;
        if (0 !== itemsCount) {
            if (this._list.option("grouped")) {
                this._list.scrollToItem({
                    group: itemsCount - 1,
                    item: listItems[itemsCount - 1].items.length - 1
                })
            } else {
                this._list.scrollToItem(itemsCount - 1)
            }
            this._list.scrollToItem(selectedIndex)
        }
    },
    _getDifferenceOffsets(selectedListItem) {
        return selectedListItem.offset().top - $(this.element()).offset().top
    },
    _isCenteringEnabled: (index, count) => index > 1 && index < count - 2,
    _getPopupOffset() {
        const listItemsCount = this._listItemElements().length;
        if (0 === listItemsCount) {
            return
        }
        const selectedListItem = $(this._list.element()).find(".dx-list-item-selected");
        const selectedIndex = this._listItemElements().index(selectedListItem);
        const differenceOfHeights = (getHeight(selectedListItem) - getHeight(this.element())) / 2;
        const lookupOffset = $(this._list.element()).offset().top;
        const dropDownHeightOption = this.option("dropDownOptions.height");
        const popupHeight = "function" === typeof dropDownHeightOption ? dropDownHeightOption() : dropDownHeightOption;
        const windowHeight = getHeight(window);
        let offsetTop = 0;
        if (-1 !== selectedIndex) {
            if (this._isCenteringEnabled(selectedIndex, listItemsCount)) {
                this._scrollToSelectedItem();
                const scrollOffsetTop = (popupHeight - getHeight(selectedListItem)) / 2 - this._getDifferenceOffsets(selectedListItem);
                this._list.scrollTo(this._list.scrollTop() + 4 - scrollOffsetTop);
                offsetTop = differenceOfHeights + this._getDifferenceOffsets(selectedListItem);
                if (lookupOffset < offsetTop && selectedIndex !== listItemsCount - 3) {
                    this._list.scrollTo(this._list.scrollTop() + this._getDifferenceOffsets(selectedListItem) / 2);
                    offsetTop = differenceOfHeights + this._getDifferenceOffsets(selectedListItem)
                }
            } else if (selectedIndex <= 1) {
                this._list.scrollTo(0);
                offsetTop = differenceOfHeights + this._getDifferenceOffsets(selectedListItem)
            } else if (selectedIndex >= listItemsCount - 2) {
                this._scrollToSelectedItem();
                offsetTop = differenceOfHeights + this._getDifferenceOffsets(selectedListItem)
            }
            if (lookupOffset < offsetTop) {
                this._scrollToSelectedItem();
                offsetTop = differenceOfHeights + 8
            }
        }
        const offsetBottom = popupHeight - offsetTop - getHeight(this.element());
        if (windowHeight - lookupOffset < offsetBottom) {
            this._list.scrollTo(this._list.scrollTop() + differenceOfHeights - offsetBottom);
            offsetTop = popupHeight - getHeight(this.element()) - 8
        }
        return offsetTop
    },
    _setPopupPosition() {
        if (!this.option("dropDownCentered")) {
            return
        }
        const flipped = this._popup.$wrapper().hasClass("dx-popover-flipped-vertical");
        if (flipped) {
            return
        }
        const popupContentParent = $(this._popup.$content()).parent();
        const popupOffset = this._getPopupOffset();
        const position = locate(popupContentParent);
        move(popupContentParent, {
            top: position.top - popupOffset
        })
    },
    _listItemGroupedElements() {
        const groups = this._list._getItemsContainer().children();
        const items = [];
        groups.each(((_, group) => {
            items.push($(group).find(".dx-list-group-header")[0]);
            const groupedItems = $(group).find(".dx-list-item");
            groupedItems.each(((_, item) => {
                items.push(item)
            }))
        }));
        return $(items)
    },
    _calculateListHeight(grouped) {
        const listItems = grouped ? this._listItemGroupedElements() : this._listItemElements();
        const selectedListItem = $(".dx-list-item-selected");
        const selectedIndex = listItems.index(selectedListItem);
        let listHeight = 0;
        let requireListItems = [];
        if (0 === listItems.length) {
            listHeight += 8
        } else if (listItems.length < 5) {
            listItems.each(((_, item) => {
                listHeight += getOuterHeight(item)
            }))
        } else {
            if (selectedIndex <= 1) {
                requireListItems = listItems.slice(0, 5)
            } else if (this._isCenteringEnabled(selectedIndex, listItems.length)) {
                requireListItems = listItems.slice(selectedIndex - 2, selectedIndex + 3)
            } else {
                requireListItems = listItems.slice(listItems.length - 5, listItems.length)
            }
            requireListItems.each(((_, item) => {
                listHeight += getOuterHeight(item)
            }))
        }
        return listHeight + (grouped ? 8 : 16)
    },
    _getPopupHeight() {
        var _this$_list;
        if (null !== (_this$_list = this._list) && void 0 !== _this$_list && _this$_list.itemElements().length) {
            return this._calculateListHeight(this.option("grouped")) + (this._$searchWrapper ? getOuterHeight(this._$searchWrapper) : 0) + (this._popup._$bottom ? getOuterHeight(this._popup._$bottom) : 0) + (this._popup._$title ? getOuterHeight(this._popup._$title) : 0)
        }
        return "auto"
    },
    _popupTabHandler: noop,
    _renderPopup() {
        if (this.option("usePopover") && !this.option("dropDownOptions.fullScreen")) {
            if (this.option("_scrollToSelectedItemEnabled")) {
                this.callBase()
            } else {
                this._renderPopover();
                this._attachPopupKeyHandler()
            }
        } else {
            this.callBase()
        }
        this._$popup.addClass("dx-lookup-popup");
        this._popup.$wrapper().addClass("dx-lookup-popup-wrapper")
    },
    _renderPopover() {
        this._popup = this._createComponent(this._$popup, Popover, extend(this._popupConfig(), this._options.cache("dropDownOptions"), {
            showEvent: null,
            hideEvent: null,
            target: this.$element(),
            fullScreen: false,
            shading: false,
            hideOnParentScroll: true,
            _fixWrapperPosition: false,
            width: this._isInitialOptionValue("dropDownOptions.width") ? function() {
                return getOuterWidth(this.$element())
            }.bind(this) : this._popupConfig().width
        }));
        this._popup.$overlayContent().attr("role", "dialog");
        this._popup.on({
            showing: this._popupShowingHandler.bind(this),
            shown: this._popupShownHandler.bind(this),
            hiding: this._popupHidingHandler.bind(this),
            hidden: this._popupHiddenHandler.bind(this),
            contentReady: this._contentReadyHandler.bind(this)
        });
        if (this.option("_scrollToSelectedItemEnabled")) {
            this._popup._$arrow.remove()
        }
        this._setPopupContentId(this._popup.$content());
        this._contentReadyHandler()
    },
    _popupHidingHandler() {
        this.callBase();
        this.option("focusStateEnabled") && this.focus()
    },
    _popupHiddenHandler() {
        this.callBase();
        if (this.option("_scrollToSelectedItemEnabled")) {
            resetPosition($(this._popup.content()).parent())
        }
    },
    _preventFocusOnPopup: noop,
    _popupConfig() {
        const result = extend(this.callBase(), {
            toolbarItems: this._getPopupToolbarItems(),
            hideOnParentScroll: false,
            onPositioned: null,
            maxHeight: "100vh",
            showTitle: this.option("dropDownOptions.showTitle"),
            title: this.option("dropDownOptions.title"),
            titleTemplate: this._getTemplateByOption("dropDownOptions.titleTemplate"),
            onTitleRendered: this.option("dropDownOptions.onTitleRendered"),
            fullScreen: this.option("dropDownOptions.fullScreen"),
            shading: this.option("dropDownOptions.shading"),
            hideOnOutsideClick: this.option("dropDownOptions.hideOnOutsideClick") || this.option("dropDownOptions.closeOnOutsideClick")
        });
        delete result.animation;
        delete result.position;
        if (this.option("_scrollToSelectedItemEnabled")) {
            result.position = this.option("dropDownCentered") ? {
                my: "left top",
                at: "left top",
                of: this.element()
            } : {
                my: "left top",
                at: "left bottom",
                of: this.element()
            };
            result.hideOnParentScroll = true
        }
        each(["position", "animation", "width", "height"], ((_, optionName) => {
            const popupOptionValue = this.option(`dropDownOptions.${optionName}`);
            if (void 0 !== popupOptionValue) {
                result[optionName] = popupOptionValue
            }
        }));
        return result
    },
    _getPopupToolbarItems() {
        const buttonsConfig = "useButtons" === this.option("applyValueMode") ? this._popupToolbarItemsConfig() : [];
        const cancelButton = this._getCancelButtonConfig();
        if (cancelButton) {
            buttonsConfig.push(cancelButton)
        }
        const clearButton = this._getClearButtonConfig();
        if (clearButton) {
            buttonsConfig.push(clearButton)
        }
        return this._applyButtonsLocation(buttonsConfig)
    },
    _popupToolbarItemsConfig() {
        return [{
            shortcut: "done",
            options: {
                onClick: this._applyButtonHandler.bind(this),
                text: this.option("applyButtonText")
            }
        }]
    },
    _getCancelButtonConfig() {
        return this.option("showCancelButton") ? {
            shortcut: "cancel",
            onClick: this._cancelButtonHandler.bind(this),
            options: {
                text: this.option("cancelButtonText")
            }
        } : null
    },
    _getClearButtonConfig() {
        return this.option("showClearButton") ? {
            shortcut: "clear",
            onClick: this._resetValue.bind(this),
            options: {
                text: this.option("clearButtonText")
            }
        } : null
    },
    _applyButtonHandler(args) {
        if (args) {
            this._saveValueChangeEvent(args.event)
        }
        this.option("value", this._valueGetter(this._currentSelectedItem()));
        this.callBase()
    },
    _cancelButtonHandler() {
        this._refreshSelected();
        this.callBase()
    },
    _refreshPopupVisibility() {
        if (this.option("opened")) {
            this._updateListDimensions()
        }
    },
    _dimensionChanged() {
        if (this.option("usePopover") && !this.option("dropDownOptions.width")) {
            this.option("dropDownOptions.width", getWidth(this.$element()))
        }
        this._updateListDimensions()
    },
    _input() {
        return this._$searchBox || this.callBase()
    },
    _renderPopupContent() {
        this.callBase();
        this._renderSearch()
    },
    _renderValueChangeEvent: noop,
    _renderSearch() {
        const isSearchEnabled = this.option("searchEnabled");
        this._toggleSearchClass(isSearchEnabled);
        if (isSearchEnabled) {
            const $searchWrapper = this._$searchWrapper = $("<div>").addClass("dx-lookup-search-wrapper");
            const $searchBox = this._$searchBox = $("<div>").addClass("dx-lookup-search").appendTo($searchWrapper);
            const currentDevice = devices.current();
            const searchMode = currentDevice.android ? "text" : "search";
            let isKeyboardListeningEnabled = false;
            const textBoxOptions = {
                mode: searchMode,
                showClearButton: true,
                valueChangeEvent: this.option("searchStartEvent"),
                inputAttr: {
                    "aria-label": "Search"
                },
                onDisposing: () => isKeyboardListeningEnabled = false,
                onFocusIn: () => isKeyboardListeningEnabled = true,
                onFocusOut: () => isKeyboardListeningEnabled = false,
                onKeyboardHandled: opts => isKeyboardListeningEnabled && this._list._keyboardHandler(opts),
                onValueChanged: e => this._searchHandler(e)
            };
            this._searchBox = this._createComponent($searchBox, TextBox, textBoxOptions);
            this._registerSearchKeyHandlers();
            $searchWrapper.insertBefore(this._$list);
            this._setSearchPlaceholder()
        }
    },
    _updateActiveDescendant() {
        this.callBase();
        if (!this._$searchBox) {
            return
        }
        const $input = this._$searchBox.find("input");
        this.callBase($input)
    },
    _removeSearch() {
        this._$searchWrapper && this._$searchWrapper.remove();
        delete this._$searchWrapper;
        this._$searchBox && this._$searchBox.remove();
        delete this._$searchBox;
        delete this._searchBox
    },
    _selectListItemHandler(e) {
        const $itemElement = $(this._list.option("focusedElement"));
        if (!$itemElement.length) {
            return
        }
        e.preventDefault();
        e.target = $itemElement.get(0);
        this._saveValueChangeEvent(e);
        this._selectListItem(e.itemData, $itemElement)
    },
    _registerSearchKeyHandlers() {
        this._searchBox.registerKeyHandler("enter", this._selectListItemHandler.bind(this));
        this._searchBox.registerKeyHandler("space", this._selectListItemHandler.bind(this));
        this._searchBox.registerKeyHandler("end", noop);
        this._searchBox.registerKeyHandler("home", noop)
    },
    _toggleSearchClass(isSearchEnabled) {
        if (this._popup) {
            this._popup.$wrapper().toggleClass("dx-lookup-popup-search", isSearchEnabled)
        }
    },
    _setSearchPlaceholder() {
        if (!this._$searchBox) {
            return
        }
        const minSearchLength = this.option("minSearchLength");
        let placeholder = this.option("searchPlaceholder");
        if (minSearchLength && placeholder === messageLocalization.format("Search")) {
            placeholder = messageLocalization.getFormatter("dxLookup-searchPlaceholder")(minSearchLength)
        }
        this._searchBox.option("placeholder", placeholder)
    },
    _setAriaTargetForList: noop,
    _listConfig() {
        return extend(this.callBase(), {
            tabIndex: 0,
            grouped: this.option("grouped"),
            groupTemplate: this._getTemplateByOption("groupTemplate"),
            pullRefreshEnabled: this.option("pullRefreshEnabled"),
            useNativeScrolling: this.option("useNativeScrolling"),
            pullingDownText: this.option("pullingDownText"),
            pulledDownText: this.option("pulledDownText"),
            refreshingText: this.option("refreshingText"),
            pageLoadingText: this.option("pageLoadingText"),
            onScroll: this._scrollHandler.bind(this),
            onPullRefresh: this._pullRefreshHandler.bind(this),
            onPageLoading: this._pageLoadingHandler.bind(this),
            pageLoadMode: this.option("pageLoadMode"),
            nextButtonText: this.option("nextButtonText"),
            indicateLoading: this.option("searchEnabled"),
            onSelectionChanged: this._getSelectionChangedHandler()
        })
    },
    _getSelectionChangedHandler() {
        return this.option("showSelectionControls") ? this._selectionChangeHandler.bind(this) : noop
    },
    _listContentReadyHandler() {
        this.callBase(...arguments);
        this._refreshSelected()
    },
    _runWithoutCloseOnScroll(callback) {
        const {
            _scrollToSelectedItemEnabled: _scrollToSelectedItemEnabled
        } = this.option();
        const hideOnParentScroll = this._popup.option("hideOnParentScroll");
        if (!_scrollToSelectedItemEnabled) {
            callback()
        } else {
            this._popup.option("hideOnParentScroll", false);
            callback();
            this._hideOnParentScrollTimer = setTimeout((() => {
                this._popup.option("hideOnParentScroll", hideOnParentScroll)
            }))
        }
    },
    _setFocusPolicy() {
        if (!this.option("focusStateEnabled")) {
            return
        }
        this._runWithoutCloseOnScroll((() => {
            if (this.option("searchEnabled")) {
                this._searchBox.focus()
            } else {
                this._list.focus()
            }
        }))
    },
    _focusTarget() {
        return this._$field
    },
    _keyboardEventBindingTarget() {
        return this._$field
    },
    _listItemClickHandler(e) {
        this._saveValueChangeEvent(e.event);
        this._selectListItem(e.itemData, e.event.currentTarget)
    },
    _selectListItem(itemData, target) {
        this._list.selectItem(target);
        if ("instantly" === this.option("applyValueMode")) {
            this._applyButtonHandler()
        }
    },
    _currentSelectedItem() {
        return this.option("grouped") ? this._list.option("selectedItems[0]").items[0] : this._list.option("selectedItems[0]")
    },
    _resetValue(e) {
        this._saveValueChangeEvent(e.event);
        this.option("value", null);
        this.option("opened", false)
    },
    _searchValue() {
        return this.option("searchEnabled") && this._searchBox ? this._searchBox.option("value") : ""
    },
    _renderInputValue() {
        return this.callBase().always((() => {
            this._refreshSelected()
        }))
    },
    _renderPlaceholder() {
        if (0 === this.$element().find(".dx-texteditor-input").length) {
            return
        }
        this.callBase()
    },
    _clean() {
        this._$fieldWrapper.remove();
        clearTimeout(this._hideOnParentScrollTimer);
        this._hideOnParentScrollTimer = null;
        this._$searchBox = null;
        this.callBase()
    },
    _optionChanged(args) {
        var _this$_searchBox;
        const {
            name: name,
            fullName: fullName,
            value: value
        } = args;
        switch (name) {
            case "dataSource":
                this.callBase(...arguments);
                this._renderField();
                break;
            case "searchEnabled":
                if (this._popup) {
                    this._removeSearch();
                    this._renderSearch()
                }
                break;
            case "searchPlaceholder":
                this._setSearchPlaceholder();
                break;
            case "minSearchLength":
                this._setSearchPlaceholder();
                this.callBase(...arguments);
                break;
            case "inputAttr":
                this._applyInputAttributes(value);
                break;
            case "usePopover":
            case "placeholder":
                this._invalidate();
                break;
            case "clearButtonText":
            case "showClearButton":
            case "showCancelButton":
                this._setPopupOption("toolbarItems", this._getPopupToolbarItems());
                break;
            case "applyValueMode":
            default:
                this.callBase(...arguments);
                break;
            case "onPageLoading":
                this._initPageLoadingAction();
                break;
            case "onPullRefresh":
                this._initPullRefreshAction();
                break;
            case "pullRefreshEnabled":
            case "useNativeScrolling":
            case "pullingDownText":
            case "pulledDownText":
            case "refreshingText":
            case "pageLoadingText":
            case "nextButtonText":
            case "grouped":
            case "groupTemplate":
                this._setListOption(name);
                break;
            case "searchStartEvent":
                null === (_this$_searchBox = this._searchBox) || void 0 === _this$_searchBox || _this$_searchBox.option("valueChangeEvent", value);
                break;
            case "onScroll":
                this._initScrollAction();
                break;
            case "pageLoadMode":
                this._setListOption("pageLoadMode", this.option("pageLoadMode"));
                break;
            case "cleanSearchOnOpening":
            case "_scrollToSelectedItemEnabled":
                break;
            case "dropDownOptions":
                switch (fullName) {
                    case "dropDownOptions.width":
                    case "dropDownOptions.height":
                        this._popupOptionChanged({
                            name: name,
                            fullName: fullName,
                            value: "auto" === value ? this.initialOption("dropDownOptions")[getFieldName(fullName)] : value
                        });
                        this._options.cache("dropDownOptions", this.option("dropDownOptions"));
                        break;
                    default:
                        this.callBase(...arguments)
                }
                break;
            case "dropDownCentered":
                if (this.option("_scrollToSelectedItemEnabled")) {
                    this.option("dropDownOptions.position", void 0);
                    this._renderPopup()
                }
        }
    },
    focus() {
        this.option("opened") ? this._setFocusPolicy() : eventsEngine.trigger(this._focusTarget(), "focus")
    },
    field() {
        return this._$field
    }
});
registerComponent("dxLookup", Lookup);
export default Lookup;
