import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// (C) 2007-2026 GoodData Corporation
import { Fragment, useCallback, useEffect, useState, } from "react";
import cx from "classnames";
import { injectIntl } from "react-intl";
import { UiPagedVirtualList, } from "../@ui/UiPagedVirtualList/UiPagedVirtualList.js";
import { DETAILED_ANNOUNCEMENT_THRESHOLD, UiSearchResultsAnnouncement, } from "../@ui/UiSearchResultsAnnouncement/UiSearchResultsAnnouncement.js";
import { AutoSize } from "../AutoSize/AutoSize.js";
import { Input } from "../Form/Input.js";
import { LoadingMask } from "../LoadingMask/LoadingMask.js";
import { NoData } from "../NoData/NoData.js";
import { isTypingKey } from "../utils/events.js";
import { DropdownTabs } from "./DropdownTabs.js";
/**
 * @internal
 */
export const LOADING_HEIGHT = 100;
/**
 * @internal
 */
export const DEFAULT_ITEM_HEIGHT = 28;
/**
 * @internal
 */
export const DEFAULT_MOBILE_ITEM_HEIGHT = 40;
const DefaultNoDataComponent = injectIntl(({ hasNoMatchingData, intl }) => (_jsx(NoData, { hasNoMatchingData: hasNoMatchingData, notFoundLabel: intl.formatMessage({ id: "gs.noData.noMatchingData" }), noDataLabel: intl.formatMessage({ id: "gs.noData.noDataAvailable" }) })));
const defaultNoData = (props) => {
    return _jsx(DefaultNoDataComponent, { hasNoMatchingData: props.hasNoMatchingData });
};
/**
 * Dropdown list component with paged virtual list implementation
 * @internal
 *
 */
export function DropdownList({ id, title, className = "", tabsClassName = "", width, height, maxHeight, onKeyDownSelect, onKeyDownConfirm, isMobile, isLoading, items = [], itemsCount = items.length, itemHeight = DEFAULT_ITEM_HEIGHT, containerPadding = 0, mobileItemHeight = DEFAULT_MOBILE_ITEM_HEIGHT, showSearch, disableAutofocus, searchString, searchLabel, searchPlaceholder, searchFieldSize, onSearch, showTabs, tabs, selectedTabId, onTabSelect, renderNoData = defaultNoData, footer, closeDropdown, accessibilityConfig, renderItem, body, itemHeightGetter, itemTitleGetter, loadNextPage, hasNextPage, skeletonItemsCount = 0, shouldLoadNextPage, isNextPageLoading = false, SkeletonItem, onScroll, scrollToItem, scrollToItemKeyExtractor, }) {
    const [currentSearchString, setCurrentSearchString] = useState(searchString);
    const hasNoData = !isLoading && itemsCount === 0;
    const hasNoMatchingData = hasNoData && !!currentSearchString;
    const searchWrapperStyle = isMobile || width === undefined ? { display: "contents" } : { width };
    const listClassNames = cx("gd-infinite-list", className);
    const searchFieldClassNames = cx("gd-list-searchfield", "gd-flex-item");
    const renderFooter = () => {
        if (!footer) {
            return null;
        }
        if (typeof footer === "function") {
            return footer(closeDropdown);
        }
        return footer;
    };
    const renderBody = () => {
        if (!body) {
            return null;
        }
        if (typeof body === "function") {
            return body(closeDropdown);
        }
        return body;
    };
    const onChange = useCallback((search) => {
        onSearch?.(search.toString());
        setCurrentSearchString(search.toString());
    }, [onSearch]);
    const searchFilled = (currentSearchString ?? "").length > 0;
    const onEscKeyPress = useCallback((e) => {
        if (searchFilled) {
            e.stopPropagation();
        }
        else {
            closeDropdown?.();
        }
    }, [searchFilled, closeDropdown]);
    useEffect(() => {
        // update string if dropdown is not getting unmounted on close to not have previous search on re-open
        setCurrentSearchString(searchString);
    }, [searchString]);
    return (_jsxs(Fragment, { children: [title ? _jsx("div", { className: "gd-list-title", children: title }) : null, showSearch ? (_jsxs(_Fragment, { children: [
                    _jsx("div", { style: searchWrapperStyle, onKeyDown: (e) => {
                            if (isTypingKey(e)) {
                                e.stopPropagation();
                            }
                        }, children: _jsx(Input, { className: searchFieldClassNames, value: currentSearchString, onChange: onChange, isSmall: searchFieldSize === "small", placeholder: searchPlaceholder, clearOnEsc: true, onEscKeyPress: onEscKeyPress, isSearch: true, autofocus: !disableAutofocus, accessibilityConfig: {
                                ariaLabel: searchLabel,
                            } }) }), _jsx(UiSearchResultsAnnouncement, { totalResults: currentSearchString ? itemsCount : undefined, resultValues: itemsCount <= DETAILED_ANNOUNCEMENT_THRESHOLD && itemTitleGetter
                            ? items.map(itemTitleGetter)
                            : undefined })
                ] })) : null, showTabs ? (_jsx(DropdownTabs, { tabs: tabs, selectedTabId: selectedTabId, onTabSelect: onTabSelect, className: tabsClassName })) : null, renderBody(), hasNoData ? (_jsx("div", { style: { width: isMobile ? "auto" : width }, children: renderNoData({ hasNoMatchingData }) })) : null, isLoading ? _jsx(LoadingMask, { width: isMobile ? "100%" : width, height: LOADING_HEIGHT }) : null, !isLoading && itemsCount > 0 ? (_jsx(AutoSize, { children: (autoSize) => {
                    const listWidth = isMobile ? autoSize.width : (width ?? (autoSize.width || 200));
                    const listHeight = isMobile ? autoSize.height : height;
                    const effectiveItemHeight = isMobile
                        ? Math.max(mobileItemHeight, itemHeight)
                        : itemHeight;
                    const effectiveMaxHeight = maxHeight || listHeight || 300;
                    return (_jsx("div", { "data-testid": "gd-dropdown-list", id: id, style: { width: listWidth }, className: listClassNames, role: accessibilityConfig?.role === "listbox" ||
                            accessibilityConfig?.role === "list"
                            ? undefined
                            : accessibilityConfig?.role, "aria-label": accessibilityConfig?.role === "listbox" ||
                            accessibilityConfig?.role === "list"
                            ? undefined
                            : accessibilityConfig?.ariaLabel, "aria-labelledby": accessibilityConfig?.role === "listbox" ||
                            accessibilityConfig?.role === "list"
                            ? undefined
                            : accessibilityConfig?.ariaLabelledBy, children: _jsx(UiPagedVirtualList, { maxHeight: effectiveMaxHeight, items: items, itemHeight: effectiveItemHeight, itemsGap: 0, itemPadding: 0, containerPadding: containerPadding, onKeyDownSelect: onKeyDownSelect, onKeyDownConfirm: onKeyDownConfirm, closeDropdown: closeDropdown, itemHeightGetter: itemHeightGetter, hasNextPage: hasNextPage, loadNextPage: loadNextPage, skeletonItemsCount: skeletonItemsCount, SkeletonItem: SkeletonItem, shouldLoadNextPage: shouldLoadNextPage, isLoading: isNextPageLoading, onScroll: onScroll, scrollToItem: scrollToItem, scrollToItemKeyExtractor: scrollToItemKeyExtractor, representAs: accessibilityConfig?.role === "listbox"
                                ? "listbox"
                                : accessibilityConfig?.role === "list"
                                    ? "list"
                                    : undefined, listboxProps: accessibilityConfig?.role === "listbox" ||
                                accessibilityConfig?.role === "list"
                                ? {
                                    "aria-label": accessibilityConfig?.ariaLabel,
                                    "aria-labelledby": accessibilityConfig?.ariaLabelledBy,
                                }
                                : undefined, children: (item) => {
                                const rowIndex = items.indexOf(item);
                                const rowHeight = itemHeightGetter?.(rowIndex) ?? effectiveItemHeight;
                                const listWidth = isMobile
                                    ? autoSize.width
                                    : (width ?? (autoSize.width || 200));
                                return renderItem({
                                    rowIndex,
                                    item,
                                    width: listWidth,
                                    height: rowHeight,
                                    isFirst: rowIndex === 0,
                                    isLast: rowIndex === itemsCount - 1,
                                });
                            } }) }));
                } })) : null, renderFooter()] }));
}
