import { Fun, Obj, Optional } from '@ephox/katamari';
import * as DropdownUtils from '../../dropdown/DropdownUtils';
import * as ButtonBase from '../../ui/common/ButtonBase';
import * as DropdownSchema from '../../ui/schema/DropdownSchema';
import { Coupling } from '../behaviour/Coupling';
import { Focusing } from '../behaviour/Focusing';
import { Keying } from '../behaviour/Keying';
import { Sandboxing } from '../behaviour/Sandboxing';
import { Toggling } from '../behaviour/Toggling';
import * as SketchBehaviours from '../component/SketchBehaviours';
import * as AlloyTriggers from '../events/AlloyTriggers';
import * as SystemEvents from '../events/SystemEvents';
import * as Sketcher from './Sketcher';
import * as TieredMenu from './TieredMenu';
const factory = (detail, components, _spec, externals) => {
    const lookupAttr = (attr) => Obj.get(detail.dom, 'attributes').bind((attrs) => Obj.get(attrs, attr));
    const switchToMenu = (sandbox) => {
        Sandboxing.getState(sandbox).each((tmenu) => {
            TieredMenu.tieredMenu.highlightPrimary(tmenu);
        });
    };
    const action = (component) => {
        const onOpenSync = switchToMenu;
        DropdownUtils.togglePopup(detail, Fun.identity, component, externals, onOpenSync, DropdownUtils.HighlightOnOpen.HighlightFirst).get(Fun.noop);
    };
    const apis = {
        expand: (comp) => {
            if (!Toggling.isOn(comp)) {
                DropdownUtils.togglePopup(detail, Fun.identity, comp, externals, Fun.noop, DropdownUtils.HighlightOnOpen.HighlightNone).get(Fun.noop);
            }
        },
        open: (comp) => {
            if (!Toggling.isOn(comp)) {
                DropdownUtils.togglePopup(detail, Fun.identity, comp, externals, Fun.noop, DropdownUtils.HighlightOnOpen.HighlightFirst).get(Fun.noop);
            }
        },
        isOpen: Toggling.isOn,
        close: (comp) => {
            if (Toggling.isOn(comp)) {
                DropdownUtils.togglePopup(detail, Fun.identity, comp, externals, Fun.noop, DropdownUtils.HighlightOnOpen.HighlightFirst).get(Fun.noop);
            }
        },
        // If we are open, refresh the menus in the tiered menu system
        repositionMenus: (comp) => {
            if (Toggling.isOn(comp)) {
                DropdownUtils.repositionMenus(comp);
            }
        }
    };
    const triggerExecute = (comp, _se) => {
        AlloyTriggers.emitExecute(comp);
        return Optional.some(true);
    };
    return {
        uid: detail.uid,
        dom: detail.dom,
        components,
        behaviours: SketchBehaviours.augment(detail.dropdownBehaviours, [
            Toggling.config({
                toggleClass: detail.toggleClass,
                aria: {
                    mode: 'expanded'
                }
            }),
            Coupling.config({
                others: {
                    sandbox: (hotspot) => {
                        return DropdownUtils.makeSandbox(detail, hotspot, {
                            onOpen: () => Toggling.on(hotspot),
                            onClose: () => Toggling.off(hotspot)
                        });
                    }
                }
            }),
            Keying.config({
                mode: 'special',
                onSpace: triggerExecute,
                onEnter: triggerExecute,
                onDown: (comp, _se) => {
                    if (Dropdown.isOpen(comp)) {
                        const sandbox = Coupling.getCoupled(comp, 'sandbox');
                        switchToMenu(sandbox);
                    }
                    else {
                        Dropdown.open(comp);
                    }
                    return Optional.some(true);
                },
                onEscape: (comp, _se) => {
                    if (Dropdown.isOpen(comp)) {
                        Dropdown.close(comp);
                        return Optional.some(true);
                    }
                    else {
                        return Optional.none();
                    }
                }
            }),
            Focusing.config({})
        ]),
        events: ButtonBase.events(Optional.some(action)),
        eventOrder: {
            ...detail.eventOrder,
            // Order, the button state is toggled first, so assumed !selected means close.
            [SystemEvents.execute()]: ['disabling', 'toggling', 'alloy.base.behaviour']
        },
        apis,
        domModification: {
            attributes: {
                'aria-haspopup': 'true',
                ...detail.role.fold(() => ({}), (role) => ({ role })),
                ...detail.dom.tag === 'button' ? { type: lookupAttr('type').getOr('button') } : {}
            }
        }
    };
};
const Dropdown = Sketcher.composite({
    name: 'Dropdown',
    configFields: DropdownSchema.schema(),
    partFields: DropdownSchema.parts(),
    factory,
    apis: {
        open: (apis, comp) => apis.open(comp),
        expand: (apis, comp) => apis.expand(comp),
        close: (apis, comp) => apis.close(comp),
        isOpen: (apis, comp) => apis.isOpen(comp),
        repositionMenus: (apis, comp) => apis.repositionMenus(comp)
    }
});
export { Dropdown };
//# sourceMappingURL=Dropdown.js.map