import { useCallback, useMemo, useState } from 'react';
import { StandardDragDropList, DragDropManager } from '@pega/cosmos-react-dnd';
import { Button, Flex, Icon, useElement } from '@pega/cosmos-react-core';
import { mockQuery, mockFields, mockGroups, mockViews } from './mockData';
import ItemConfig from './ItemConfig';
import SelectionMenu from './SelectionMenu';
export default ({ items, draggable, info, icons, onConfigure, onRemove, onAddTo, selectable, footer, onSelectionChange }) => {
    const [mockRawItems, setMockRawItems] = useState(items);
    const [configItemId, setConfigItemId] = useState(null);
    const [configTarget, setConfigTarget] = useElement(null);
    const [selectionMenuTarget, setSelectionMenuTarget] = useElement(null);
    const [selectionConstraint, setSelectionConstraint] = useState();
    const [addToItemId, setAddToItemId] = useState(null);
    const [errors, setErrors] = useState([]);
    const onAddContent = useCallback(async (selected) => {
        setSelectionMenuTarget(null);
        setSelectionConstraint(undefined);
        if (selected.length === 0)
            return;
        const addedItems = await mockQuery({ id: selected.map(({ id }) => id) });
        setMockRawItems(cur => {
            if (addToItemId) {
                return cur.map(item => {
                    if (item.id === addToItemId && item.items) {
                        return {
                            ...item,
                            items: [
                                ...item.items,
                                ...addedItems.map(nestedItem => ({
                                    ...nestedItem,
                                    id: `${addToItemId}:${nestedItem.id}`
                                }))
                            ]
                        };
                    }
                    return item;
                });
            }
            return [...cur, ...addedItems.filter(newItem => !cur.find(({ id }) => id === newItem.id))];
        });
    }, [addToItemId, setSelectionMenuTarget]);
    const onItemConfigure = useCallback((id, e) => {
        setConfigTarget(e.currentTarget);
        setConfigItemId(id);
    }, [setConfigTarget]);
    const onItemRemove = useCallback((id) => {
        setMockRawItems(cur => cur.filter(rawItem => {
            if (rawItem.id === id)
                return false;
            if (rawItem.items && rawItem.items.find(ri => ri.id === id)) {
                rawItem.items = rawItem.items.filter(ri => ri.id !== id);
            }
            return true;
        }));
    }, []);
    const onAddToGroup = useCallback((groupId, e) => {
        setAddToItemId(groupId);
        setSelectionMenuTarget(e.currentTarget);
        setSelectionConstraint({ types: ['Field'] });
    }, [setSelectionMenuTarget]);
    const showSelectionMenu = useCallback((e) => {
        setSelectionMenuTarget(e.currentTarget);
    }, [setSelectionMenuTarget]);
    const onChange = useCallback(updatedItems => {
        setMockRawItems(cur => {
            const findRawItem = (id) => {
                for (let i = 0; i < cur.length; i += 1) {
                    if (cur[i].id === id)
                        return cur[i];
                    if (cur[i].items) {
                        const subItem = cur[i].items.find(s => s.id === id);
                        if (subItem)
                            return subItem;
                    }
                }
                return [...mockFields, ...mockViews, ...mockGroups].find(rawItem => rawItem.id === id);
            };
            return updatedItems.map(item => {
                const rawItem = findRawItem(item.id);
                if (item.items) {
                    const rawSubItems = item.items.map(subItem => {
                        return findRawItem(subItem.id);
                    });
                    return { ...rawItem, items: rawSubItems };
                }
                return rawItem;
            });
        });
    }, []);
    const createListItems = useCallback((mci, onATG) => {
        return mci.map(rawItem => {
            const itemError = errors?.find(error => error.rawItemId === rawItem.id);
            const primary = rawItem.type === 'View'
                ? {
                    text: rawItem.label,
                    href: '/some-url',
                    onClick: (e) => {
                        e.preventDefault();
                    }
                }
                : rawItem.label;
            const baseItem = {
                ...rawItem,
                primary,
                draggable,
                info,
                secondary: rawItem.subType ?? rawItem.type,
                status: itemError ? { type: 'error', message: itemError.message } : undefined,
                onConfigure: onConfigure ? onItemConfigure : undefined,
                onRemove: onRemove ? onItemRemove : undefined,
                icon: icons ? rawItem.icon : undefined,
                items: undefined
            };
            return rawItem.type === 'Group'
                ? {
                    ...baseItem,
                    items: rawItem.items ? createListItems(rawItem.items, onATG) : [],
                    accept: 'Field',
                    onAddTo: onAddTo ? onATG : undefined
                }
                : baseItem;
        });
    }, [
        errors,
        onItemConfigure,
        onItemRemove,
        draggable,
        info,
        icons,
        onConfigure,
        onRemove,
        onAddTo,
        footer,
        selectable
    ]);
    const itemsToRender = useMemo(() => {
        return createListItems(mockRawItems, onAddToGroup);
    }, [mockRawItems, onAddToGroup, createListItems]);
    const handleSelectionChange = (item) => {
        const updateItemSelection = (rawItem) => {
            if (rawItem.id === item.id)
                return { ...rawItem, selected: item.selected };
            if (rawItem.items?.find(ri => ri.id === item.id)) {
                return {
                    ...rawItem,
                    items: rawItem.items.map(ri => ri.id === item.id ? { ...ri, selected: item.selected } : ri)
                };
            }
            return rawItem;
        };
        setMockRawItems(cur => cur.map(updateItemSelection));
        onSelectionChange?.();
    };
    return (<>
      <DragDropManager>
        {useMemo(() => (<StandardDragDropList accept={['Field', 'View', 'Group']} heading='Mock view' info={info} items={itemsToRender} onChange={onChange} onItemSelection={selectable ? handleSelectionChange : undefined} footer={footer ? (<Button onClick={showSelectionMenu} variant='link'>
                    <Flex container={{ inline: true, alignItems: 'center', gap: 1 }}>
                      <Icon name='plus'/>
                      <span>Add</span>
                    </Flex>
                  </Button>) : undefined}/>), [itemsToRender, showSelectionMenu, onChange])}
      </DragDropManager>
      {configTarget && configItemId && (<ItemConfig itemId={configItemId} target={configTarget} onCancel={() => {
                setConfigTarget(null);
                setConfigItemId(null);
                setErrors(currentErrors => {
                    const currentItemError = currentErrors?.find(err => err.rawItemId === configItemId);
                    return currentItemError
                        ? currentErrors.filter(err => err.rawItemId !== configItemId)
                        : [
                            ...currentErrors,
                            { rawItemId: configItemId, message: 'Misconfiguration detected' }
                        ];
                });
            }} onSubmit={() => {
                setConfigTarget(null);
                setConfigItemId(null);
            }}/>)}
      {selectionMenuTarget && (<SelectionMenu target={selectionMenuTarget} constraint={selectionConstraint} onCancel={() => {
                setSelectionMenuTarget(null);
                setAddToItemId(null);
                setSelectionConstraint(undefined);
            }} onSubmit={onAddContent}/>)}
    </>);
};
//# sourceMappingURL=Demo.jsx.map