import { useCallback, useMemo, useState, useEffect } from 'react';
import { Button, ComboBox, Flex, menuHelpers } from '@pega/cosmos-react-core';
import { getFilterRegex, list, tree, createNewButton } from './ComboBox.mocks';
export default {
    title: 'Core/ComboBox',
    component: ComboBox,
    args: {
        label: '',
        labelHidden: false,
        info: 'Type in or click to expand the Popover',
        placeholder: '',
        status: undefined,
        required: false,
        disabled: false,
        readOnly: false,
        showAdditionalInfo: false,
        createNew: true,
        scrollAt: 6
    },
    argTypes: {
        label: { control: { type: 'text' } },
        labelHidden: { control: { type: 'boolean' } },
        info: { control: { type: 'text', label: 'Helper text' } },
        placeholder: { control: { type: 'text' } },
        status: { options: [undefined, 'success', 'warning', 'error'], control: { type: 'select' } },
        required: { control: { type: 'boolean' } },
        disabled: { control: { type: 'boolean' } },
        readOnly: { control: { type: 'boolean' } },
        showAdditionalInfo: { control: { type: 'boolean' } },
        createNew: { control: { type: 'boolean' } },
        scrollAt: { control: { type: 'number' } }
    }
};
export const FilterableSingleSelect = (args) => {
    const [items, setItems] = useState(tree);
    const selected = useMemo(() => menuHelpers.getSelected(items)[0], [items]);
    const [filterValue, setFilterValue] = useState('');
    const filterRegex = useMemo(() => getFilterRegex(filterValue), [filterValue]);
    const itemsToRender = useMemo(() => {
        const newItems = filterValue
            ? menuHelpers.flatten(items).filter(({ primary }) => {
                return filterRegex.test(primary);
            })
            : items;
        return menuHelpers.mapTree(newItems, item => ({
            ...item,
            selected: item.items ? undefined : !!item.selected
        }));
    }, [filterValue, items]);
    const selectItem = useCallback((id) => {
        setFilterValue('');
        setItems(cur => menuHelpers.selectItem(cur, id, 'single-select'));
    }, []);
    const clearSelection = () => {
        setItems(cur => menuHelpers.mapTree(cur, item => {
            return {
                ...item,
                selected: false
            };
        }));
    };
    return (<ComboBox additionalInfo={args.showAdditionalInfo
            ? {
                content: 'Some additional info'
            }
            : undefined} label={args.label} labelHidden={args.labelHidden} info={args.info} placeholder={args.placeholder} status={args.status} required={args.required} disabled={args.disabled} readOnly={args.readOnly} mode='single-select' selected={selected
            ? {
                items: {
                    id: selected.id,
                    text: selected.primary
                }
            }
            : undefined} value={filterValue} onChange={(e) => {
            if (!e.target.value)
                clearSelection();
            setFilterValue(e.target.value);
        }} onBlur={() => {
            setFilterValue('');
        }} menu={{
            items: itemsToRender,
            onCreateNew: args.onCreateNew,
            onItemClick: selectItem,
            accent: filterRegex,
            emptyText: 'No items',
            scrollAt: args.scrollAt,
            footer: args.createNew ? createNewButton : undefined
        }}/>);
};
FilterableSingleSelect.args = {
    label: 'ComboBox Single Autocomplete'
};
export const NonFilterableSingleSelect = (args) => {
    const pageSize = 10;
    const [items, setItems] = useState(() => {
        return menuHelpers.mapTree(tree.slice(0, pageSize), item => ({
            ...item,
            selected: item.items ? undefined : !!item.selected
        }));
    });
    const [isLoading, setIsLoading] = useState(false);
    const [hasMore, setHasMore] = useState(true);
    const selected = useMemo(() => menuHelpers.getSelected(items)[0], [items]);
    const selectItem = useCallback((id) => {
        setItems(cur => menuHelpers.selectItem(cur, id, 'single-select'));
    }, []);
    const loadMore = useCallback((expandedItemId) => {
        if (!isLoading && !expandedItemId) {
            setIsLoading(true);
            setTimeout(() => {
                setIsLoading(false);
                setItems(prevItems => {
                    const newItems = menuHelpers.mapTree(tree.slice(prevItems.length, prevItems.length + pageSize), item => ({
                        ...item,
                        selected: item.items ? undefined : !!item.selected
                    }));
                    if (newItems.length === 0)
                        setHasMore(false);
                    return menuHelpers.appendTo(prevItems, newItems, expandedItemId);
                });
            }, 2000);
        }
    }, [items, isLoading]);
    return (<ComboBox additionalInfo={args.showAdditionalInfo
            ? {
                content: 'Some additional info'
            }
            : undefined} label={args.label} labelHidden={args.labelHidden} info={args.info} placeholder={args.placeholder} status={args.status} required={args.required} disabled={args.disabled} readOnly={args.readOnly} selected={selected
            ? {
                items: {
                    id: selected.id,
                    text: selected.primary
                }
            }
            : undefined} menu={{
            items,
            onItemClick: selectItem,
            loading: isLoading,
            loadMore: hasMore ? loadMore : undefined,
            scrollAt: args.scrollAt,
            footer: args.createNew ? createNewButton : undefined
        }}/>);
};
NonFilterableSingleSelect.args = {
    label: 'ComboBox Single Select',
    info: 'Click on dropdown button to expand the Popover',
    placeholder: '-Choose option-'
};
export const FilterableMultiSelect = (args) => {
    const [items, setItems] = useState(tree);
    const [filterValue, setFilterValue] = useState('');
    const selected = useMemo(() => {
        return menuHelpers.getSelected(items).map(item => ({ text: item.primary, id: item.id }));
    }, [items]);
    const filterRegex = useMemo(() => getFilterRegex(filterValue), [filterValue]);
    const itemsToRender = useMemo(() => {
        const newItems = filterValue
            ? menuHelpers.flatten(items).filter(({ primary }) => {
                return filterRegex.test(primary);
            })
            : items;
        return menuHelpers.mapTree(newItems, item => ({
            ...item,
            selected: item.items ? undefined : !!item.selected
        }));
    }, [filterValue, items]);
    const toggleItem = (id) => {
        setItems(cur => menuHelpers.toggleSelected(cur, id, 'multi-select'));
    };
    return (<ComboBox additionalInfo={args.showAdditionalInfo
            ? {
                content: 'Some additional info'
            }
            : undefined} mode='multi-select' label={args.label} labelHidden={args.labelHidden} info={args.info} placeholder={args.placeholder} status={args.status} required={args.required} disabled={args.disabled} readOnly={args.readOnly} selected={{
            items: selected,
            onRemove: toggleItem
        }} value={filterValue} onChange={(e) => {
            setFilterValue(e.target.value);
        }} onBlur={() => {
            setFilterValue('');
        }} menu={{
            items: itemsToRender,
            onItemClick: toggleItem,
            accent: filterRegex,
            emptyText: 'No items',
            scrollAt: args.scrollAt,
            footer: args.createNew ? createNewButton : undefined
        }}/>);
};
FilterableMultiSelect.args = {
    label: 'ComboBox Multi Autocomplete'
};
export const NonFilterableMultiSelect = (args) => {
    const [items, setItems] = useState(menuHelpers.mapTree(list, item => ({ id: item.id, primary: item.primary })));
    const selected = useMemo(() => {
        return menuHelpers.getSelected(items).map(item => ({ text: item.primary, id: item.id }));
    }, [items]);
    const toggleItem = (id) => {
        setItems(cur => menuHelpers.toggleSelected(cur, id, 'multi-select'));
    };
    const itemsToRender = useMemo(() => {
        return menuHelpers.mapTree(items, item => ({
            ...item,
            selected: item.items ? undefined : !!item.selected
        }));
    }, [items]);
    return (<ComboBox additionalInfo={args.showAdditionalInfo
            ? {
                content: 'Some additional info'
            }
            : undefined} mode='multi-select' label={args.label} labelHidden={args.labelHidden} info={args.info} placeholder={args.placeholder} status={args.status} required={args.required} disabled={args.disabled} readOnly={args.readOnly} selected={{
            items: selected,
            onRemove: toggleItem
        }} menu={{
            items: itemsToRender,
            onItemClick: toggleItem,
            scrollAt: args.scrollAt,
            footer: args.createNew ? createNewButton : undefined
        }}/>);
};
NonFilterableMultiSelect.args = {
    label: 'ComboBox Multi Select',
    info: 'Click on dropdown button to expand the Popover',
    placeholder: '-Choose options-'
};
export const FilterableMultiSelectSelectableParent = (args) => {
    const [items, setItems] = useState(tree);
    const [filterValue, setFilterValue] = useState('');
    const selected = useMemo(() => {
        return menuHelpers.getSelected(items).map(item => ({ text: item.primary, id: item.id }));
    }, [items]);
    const filterRegex = useMemo(() => getFilterRegex(filterValue), [filterValue]);
    const itemsToRender = useMemo(() => {
        const newItems = filterValue
            ? menuHelpers.flatten(items).filter(({ primary }) => {
                return filterRegex.test(primary);
            })
            : items;
        return menuHelpers.mapTree(newItems, item => ({
            ...item,
            selected: !!item.selected
        }));
    }, [filterValue, items]);
    const toggleItem = (id) => {
        setItems(cur => menuHelpers.toggleSelected(cur, id, 'multi-select'));
    };
    return (<ComboBox additionalInfo={args.showAdditionalInfo
            ? {
                content: 'Some additional info'
            }
            : undefined} mode='multi-select' label={args.label} labelHidden={args.labelHidden} info={args.info} placeholder={args.placeholder} status={args.status} required={args.required} disabled={args.disabled} readOnly={args.readOnly} selected={{
            items: selected,
            onRemove: toggleItem
        }} value={filterValue} onChange={(e) => {
            setFilterValue(e.target.value);
        }} onBlur={() => {
            setFilterValue('');
        }} menu={{
            items: itemsToRender,
            onItemClick: toggleItem,
            accent: filterRegex,
            emptyText: 'No items',
            scrollAt: args.scrollAt,
            footer: args.createNew ? createNewButton : undefined
        }}/>);
};
FilterableMultiSelectSelectableParent.args = {
    label: 'ComboBox Multi Selectable Parent'
};
export const FilterableMultiSelectLazyChildren = (args) => {
    const rootItemId = '01';
    const lazyItems = useMemo(() => {
        return [
            { id: '01-1', primary: 'Paul McDonald', secondary: ['Leads', 'Engineer'] },
            { id: '01-2', primary: 'Frank Walker', secondary: ['Leads', 'Engineer'] },
            { id: '01-3', primary: 'Edward Green', secondary: ['Leads', 'Engineer'] },
            { id: '01-4', primary: 'Shaun McMinneman', secondary: ['Leads', 'Engineer'] },
            { id: '01-5', primary: 'Hank Fitzgerald', secondary: ['Leads', 'Engineer'] },
            { id: '01-6', primary: 'Mindy Stark', secondary: ['Leads', 'Engineer'] },
            { id: '01-7', primary: 'Shane Howard', secondary: ['Leads', 'Engineer'] },
            { id: '01-8', primary: 'Raul Singh', secondary: ['Leads', 'Engineer'] }
        ];
    }, []);
    const [items, setItems] = useState([
        {
            id: rootItemId,
            primary: 'Group',
            secondary: ['Leads', 'Engineer'],
            items: []
        }
    ]);
    const [loading, setLoading] = useState(false);
    const [hasMore, setHasMore] = useState(false);
    const [filterValue, setFilterValue] = useState('');
    const selected = useMemo(() => {
        return menuHelpers.getSelected(items).map(item => ({ text: item.primary, id: item.id }));
    }, [items]);
    const filterRegex = useMemo(() => getFilterRegex(filterValue), [filterValue]);
    const itemsToRender = useMemo(() => {
        const newItems = filterValue
            ? menuHelpers.flatten(items).filter(({ primary }) => {
                return filterRegex.test(primary);
            })
            : items;
        return menuHelpers.mapTree(newItems, item => ({
            ...item,
            selected: item.items ? undefined : !!item.selected
        }));
    }, [filterValue, items]);
    const loadMore = useCallback(() => {
        if (!loading) {
            setLoading(true);
            setTimeout(() => {
                setLoading(false);
                setItems(() => {
                    const previousNestedLength = menuHelpers.getItem(items, rootItemId)?.items?.length || 0;
                    const newItems = lazyItems.slice(previousNestedLength, previousNestedLength + 3);
                    if (newItems.length === 0)
                        setHasMore(false);
                    return menuHelpers.appendTo(items, newItems, rootItemId);
                });
            }, 2000);
        }
    }, [items, loading]);
    const toggleItem = (id) => {
        setItems(cur => menuHelpers.toggleSelected(cur, id, 'multi-select'));
    };
    useEffect(() => {
        if (hasMore) {
            loadMore();
        }
    }, [hasMore]);
    const onItemExpand = useCallback(() => {
        setHasMore(true);
    }, []);
    const onItemCollapse = useCallback(() => {
        setHasMore(false);
        setLoading(false);
        setItems(cur => [{ ...cur[0], items: [] }]);
    }, []);
    return (<ComboBox additionalInfo={args.showAdditionalInfo
            ? {
                content: 'Some additional info'
            }
            : undefined} mode='multi-select' label={args.label} labelHidden={args.labelHidden} info={args.info} placeholder={args.placeholder} status={args.status} required={args.required} disabled={args.disabled} readOnly={args.readOnly} selected={{
            items: selected,
            onRemove: toggleItem
        }} value={filterValue} onChange={(e) => {
            setFilterValue(e.target.value);
        }} onBlur={() => {
            setFilterValue('');
        }} menu={{
            items: itemsToRender,
            onItemClick: toggleItem,
            onItemExpand,
            onItemCollapse,
            loading,
            loadMore: hasMore ? loadMore : undefined,
            accent: filterRegex,
            emptyText: 'No items',
            scrollAt: args.scrollAt,
            footer: args.createNew ? createNewButton : undefined
        }}/>);
};
FilterableMultiSelectLazyChildren.args = {
    label: 'ComboBox Multi Lazy Children'
};
export const MenuWithCreateNew = () => {
    return <ComboBox label='Operators' menu={{ items: list, onCreateNew: () => { } }}/>;
};
MenuWithCreateNew.argTypes = {
    label: { table: { disable: true } },
    labelHidden: { table: { disable: true } },
    info: { table: { disable: true } },
    placeholder: { table: { disable: true } },
    status: { table: { disable: true } },
    required: { table: { disable: true } },
    disabled: { table: { disable: true } },
    readOnly: { table: { disable: true } },
    showAdditionalInfo: { table: { disable: true } },
    createNew: { table: { disable: true } },
    scrollAt: { table: { disable: true } }
};
export const MenuWithListFetching = () => {
    const [items, setItems] = useState([]);
    const [loading, setLoading] = useState(false);
    const fetchItems = () => {
        if (loading || items.length > 0)
            return;
        setLoading(true);
        new Promise(r => {
            setTimeout(r, 3000);
        }).then(() => {
            setItems(list.slice(1, 10));
            setLoading(false);
        });
    };
    return (<Flex container={{ direction: 'column', gap: 2 }}>
      <Button onClick={() => setItems([])}>Clear Items In Combobox</Button>
      <ComboBox label='Cars' onMenuOpen={fetchItems} menu={{
            items,
            loading
        }}/>
    </Flex>);
};
MenuWithListFetching.argTypes = {
    label: { table: { disable: true } },
    labelHidden: { table: { disable: true } },
    info: { table: { disable: true } },
    placeholder: { table: { disable: true } },
    status: { table: { disable: true } },
    required: { table: { disable: true } },
    disabled: { table: { disable: true } },
    readOnly: { table: { disable: true } },
    showAdditionalInfo: { table: { disable: true } },
    createNew: { table: { disable: true } },
    scrollAt: { table: { disable: true } }
};
//# sourceMappingURL=ComboBox.stories.jsx.map