var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, privateMap, value) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to set private field on non-instance");
    }
    privateMap.set(receiver, value);
    return value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, privateMap) {
    if (!privateMap.has(receiver)) {
        throw new TypeError("attempted to get private field on non-instance");
    }
    return privateMap.get(receiver);
};
var _items, _onToggle, _parent, _selected, _trigger;
import { modulo } from './modulo';
export class MenuControl {
    constructor(parent, trigger, onToggle) {
        _items.set(this, []);
        _onToggle.set(this, void 0);
        _parent.set(this, void 0);
        _selected.set(this, void 0);
        _trigger.set(this, void 0);
        this.handleClickDocument = (event) => {
            const parent = __classPrivateFieldGet(this, _parent);
            if (parent.contains(event.target))
                return;
            if (event.composedPath().indexOf(parent) >= 0)
                return;
            this.toggle(false);
        };
        this.handleClickTrigger = () => {
            this.toggle();
        };
        this.handleClickItem = () => {
            this.toggle(false);
            this.select(__classPrivateFieldGet(this, _trigger));
        };
        this.handleKeyDownTrigger = (event) => {
            return this.handleKeyDown(event, true);
        };
        this.handleKeyDownItem = (event) => {
            return this.handleKeyDown(event, false);
        };
        __classPrivateFieldSet(this, _onToggle, onToggle);
        __classPrivateFieldSet(this, _parent, parent);
        __classPrivateFieldSet(this, _trigger, trigger);
        document.addEventListener('click', this.handleClickDocument);
        __classPrivateFieldGet(this, _trigger).addEventListener('click', this.handleClickTrigger);
        __classPrivateFieldGet(this, _trigger).addEventListener('keydown', this.handleKeyDownTrigger);
    }
    get selectedIndex() {
        return __classPrivateFieldGet(this, _selected) ? __classPrivateFieldGet(this, _items).indexOf(__classPrivateFieldGet(this, _selected)) : -1;
    }
    dispose() {
        document.removeEventListener('click', this.handleClickDocument);
        __classPrivateFieldGet(this, _trigger).removeEventListener('click', this.handleClickTrigger);
        __classPrivateFieldGet(this, _trigger).removeEventListener('keydown', this.handleKeyDownTrigger);
        for (const item of __classPrivateFieldGet(this, _items)) {
            item.removeEventListener('keydown', this.handleKeyDownItem);
            item.removeEventListener('click', this.handleClickItem);
        }
    }
    next() {
        const target = __classPrivateFieldGet(this, _selected) ? __classPrivateFieldGet(this, _items)[modulo(this.selectedIndex + 1, __classPrivateFieldGet(this, _items).length)]
            : __classPrivateFieldGet(this, _items)[0];
        this.select(target);
    }
    prev() {
        const target = __classPrivateFieldGet(this, _selected) ? __classPrivateFieldGet(this, _items)[modulo(this.selectedIndex - 1, __classPrivateFieldGet(this, _items).length)]
            : __classPrivateFieldGet(this, _items)[__classPrivateFieldGet(this, _items).length - 1];
        this.select(target);
    }
    setItems(items) {
        var _a;
        __classPrivateFieldSet(this, _items, items);
        for (const item of items) {
            item.removeEventListener('keydown', this.handleKeyDownItem);
            item.removeEventListener('click', this.handleClickItem);
            item.addEventListener('keydown', this.handleKeyDownItem);
            item.addEventListener('click', this.handleClickItem);
            item.a11yRole = item.a11yRole || 'menuitem';
            item.a11yTabIndex = (_a = item.a11yTabIndex) !== null && _a !== void 0 ? _a : -1;
        }
    }
    handleKeyDown(event, trigger) {
        switch (event.keyCode) {
            case 9: // Tab
                return this.toggle(false);
            case 13: // Enter
            case 32: // Space
                if (!trigger)
                    return;
                this.next();
                event.preventDefault();
                return;
            case 27: // Escape
                this.toggle(false);
                this.select(__classPrivateFieldGet(this, _trigger));
                return;
            case 35: // End
                return !trigger && this.select(__classPrivateFieldGet(this, _items)[__classPrivateFieldGet(this, _items).length - 1]);
            case 36: // Home
                return !trigger && this.select(__classPrivateFieldGet(this, _items)[0]);
            case 37: // Arrow Left
            case 38: // Arrow Up
                return this.prev();
            case 39: // Arrow Right
            case 40: // Arrow Down
                return this.next();
        }
    }
    isBceButton(el) {
        return 'design' in el;
    }
    select(el) {
        if (!el)
            return;
        if (this.isBceButton(el) && el.a11yRole === 'menuitem') {
            this.toggle(true);
            __classPrivateFieldSet(this, _selected, el);
        }
        if (el.shadowRoot)
            el.shadowRoot.querySelector('button').focus();
        else
            el.focus();
    }
    toggle(active) {
        __classPrivateFieldSet(this, _selected, undefined);
        __classPrivateFieldGet(this, _onToggle).call(this, active);
    }
}
_items = new WeakMap(), _onToggle = new WeakMap(), _parent = new WeakMap(), _selected = new WeakMap(), _trigger = new WeakMap();
