import { ApproxStructure, Assertions, Step, Waiter } from '@ephox/agar';
import { Arr, Fun, Merger, Obj } from '@ephox/katamari';
import { SelectorFind } from '@ephox/sugar';
import * as Behaviour from 'ephox/alloy/api/behaviour/Behaviour';
import { Disabling } from 'ephox/alloy/api/behaviour/Disabling';
import { Representing } from 'ephox/alloy/api/behaviour/Representing';
import * as ItemWidget from 'ephox/alloy/api/ui/ItemWidget';
import { Menu } from 'ephox/alloy/api/ui/Menu';
import * as Tagger from 'ephox/alloy/registry/Tagger';
const renderMenu = (spec) => ({
    dom: {
        tag: 'ol',
        classes: ['menu'],
        attributes: spec.text !== undefined ? {
            'aria-label': spec.text
        } : {}
    },
    items: spec.items,
    components: [
        Menu.parts.items({})
    ]
});
const renderItem = (spec) => {
    switch (spec.type) {
        case 'widget':
            return {
                type: 'widget',
                data: spec.data,
                dom: {
                    tag: 'li',
                    attributes: {
                        'data-value': spec.data.value
                    },
                    classes: ['item-widget']
                },
                components: [
                    ItemWidget.parts.widget(spec.widget)
                ]
            };
        case 'separator':
            return {
                type: spec.type,
                dom: {
                    tag: 'li',
                    classes: [],
                    innerHtml: spec.text
                },
                components: []
            };
        case 'item':
            return {
                type: spec.type,
                data: spec.data,
                hasSubmenu: spec.hasSubmenu,
                dom: {
                    tag: 'li',
                    attributes: {
                        'data-value': spec.data.value,
                        'data-test-id': 'item-' + spec.data.value,
                        'aria-disabled': spec.data.meta.disabled === true ? true : false,
                        'id': spec.data.value
                    },
                    classes: [],
                    innerHtml: spec.data.meta.text
                },
                components: [],
                toggling: spec.toggling,
                itemBehaviours: Behaviour.derive([
                    Disabling.config({
                        disabled: () => spec.data.meta.disabled
                    })
                ])
            };
    }
};
const part = (store) => ({
    dom: {
        tag: 'div'
    },
    markers: itemMarkers,
    onExecute: (_dropdown, item) => {
        const v = Representing.getValue(item);
        return store.adderH('dropdown.menu.execute: ' + v.value)();
    }
});
const mStoreMenuUid = (component) => Step.stateful((value, next, _die) => {
    const menu = SelectorFind.descendant(component.element, '.menu').getOrDie('Could not find menu');
    const uid = Tagger.readOrDie(menu);
    next(Merger.deepMerge(value, { menuUid: uid }));
});
const mWaitForNewMenu = (component) => 
// TODO: Create an API to hide this detail
Step.raw((value, next, die, logs) => {
    Waiter.sTryUntil('Waiting for a new menu (different uid)', Step.sync(() => {
        SelectorFind.descendant(component.element, '.menu').filter((menu) => {
            const uid = Tagger.readOrDie(menu);
            return value.menuUid !== uid;
        }).getOrDie('New menu has not appeared');
    }), 100, 3000).runStep(value, next, die, logs);
});
const assertLazySinkArgs = (expectedTag, expectedClass, comp) => {
    Assertions.assertStructure('Lazy sink should get passed the right button', ApproxStructure.build((s, _str, arr) => s.element(expectedTag, {
        classes: [arr.has(expectedClass)]
    })), comp.element);
};
const getSampleTieredData = () => {
    /* Menu structure
  
    all-menus/
    ├─ menu-a/
    │  ├─ a-alpha
    │  ├─ a-beta/
    │  │  ├─ b-alpha
    │  ├─ a-gamma
  */
    return {
        primary: 'menu-a',
        menus: Obj.map({
            'menu-a': {
                value: 'menu-a',
                items: Arr.map([
                    { type: 'item', data: { value: 'a-alpha', meta: { text: 'a-Alpha' } }, hasSubmenu: false },
                    { type: 'item', data: { value: 'a-beta', meta: { text: 'a-Beta' } }, hasSubmenu: true },
                    { type: 'item', data: { value: 'a-gamma', meta: { text: 'a-Gamma' } }, hasSubmenu: false }
                ], renderItem)
            },
            'a-beta': {
                value: 'menu-b',
                items: Arr.map([
                    { type: 'item', data: { value: 'b-alpha', meta: { text: 'b-Alpha' } }, hasSubmenu: false }
                ], renderItem)
            }
        }, renderMenu),
        expansions: {
            'a-beta': 'a-beta'
        }
    };
};
// ASSUMPTION: the ApproxStructure.build arguments s, str, arr are always the same
// so we don't need to pass the originals through to functions.
const structNotActiveItem = ApproxStructure.build((s, str, arr) => s.element('li', {
    classes: [arr.has('item'), arr.not('selected-item')]
}));
const structActiveItem = ApproxStructure.build((s, str, arr) => s.element('li', {
    classes: [arr.has('item'), arr.has('selected-item')]
}));
const itemsHaveActiveStates = (states) => Arr.map(states, (s) => {
    return s ? structActiveItem : structNotActiveItem;
});
const itemMarkers = {
    item: 'item',
    selectedItem: 'selected-item',
    menu: 'menu',
    selectedMenu: 'selected-menu',
    backgroundMenu: 'background-menu'
};
const markers = Fun.constant(itemMarkers);
export { assertLazySinkArgs, renderItem, renderMenu, part, markers, mWaitForNewMenu, mStoreMenuUid, getSampleTieredData, structNotActiveItem, structActiveItem, itemsHaveActiveStates };
//# sourceMappingURL=TestDropdownMenu.js.map