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 _elItems, _elParent, _elTrigger, _listbox, _onToggle, _selected, _value;
import { modulo } from './modulo';
export class MenuControl {
    constructor(options) {
        _elItems.set(this, []);
        _elParent.set(this, void 0);
        _elTrigger.set(this, void 0);
        _listbox.set(this, void 0);
        _onToggle.set(this, void 0);
        _selected.set(this, void 0);
        _value.set(this, void 0);
        this.handleClickDocument = (event) => {
            const parent = __classPrivateFieldGet(this, _elParent);
            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.selectTrigger();
        };
        this.handleKeyDownTrigger = (event) => {
            return this.handleKeyDown(event, true);
        };
        this.handleKeyDownItem = (event) => {
            return this.handleKeyDown(event, false);
        };
        __classPrivateFieldSet(this, _elParent, options.parent);
        __classPrivateFieldSet(this, _listbox, options.listbox);
        __classPrivateFieldSet(this, _elTrigger, options.trigger);
        __classPrivateFieldSet(this, _onToggle, options.onToggle);
        document.addEventListener('click', this.handleClickDocument);
        __classPrivateFieldGet(this, _elTrigger).addEventListener('click', this.handleClickTrigger);
        __classPrivateFieldGet(this, _elTrigger).addEventListener('keydown', this.handleKeyDownTrigger);
    }
    dispose() {
        document.removeEventListener('click', this.handleClickDocument);
        __classPrivateFieldGet(this, _elTrigger).removeEventListener('click', this.handleClickTrigger);
        __classPrivateFieldGet(this, _elTrigger).removeEventListener('keydown', this.handleKeyDownTrigger);
    }
    next(current = __classPrivateFieldGet(this, _selected)) {
        const e = __classPrivateFieldGet(this, _elItems).filter(e => !e.disabled);
        const i = current ? __classPrivateFieldGet(this, _elItems).indexOf(current) : -1;
        const target = current ? e[modulo(i + 1, e.length)] : e[0];
        this.selectItem(target);
    }
    prev(current = __classPrivateFieldGet(this, _selected)) {
        const e = __classPrivateFieldGet(this, _elItems).filter(e => !e.disabled);
        const i = current ? __classPrivateFieldGet(this, _elItems).indexOf(current) : -1;
        const target = current ? e[modulo(i - 1, e.length)] : e[e.length - 1];
        this.selectItem(target);
    }
    setItems(items) {
        var _a;
        const role = __classPrivateFieldGet(this, _listbox) ? 'option' : 'menuitem';
        __classPrivateFieldSet(this, _elItems, 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 || role;
            item.tabIndex = (_a = item.tabIndex) !== null && _a !== void 0 ? _a : -1;
        }
    }
    setValue(item) {
        __classPrivateFieldSet(this, _value, item);
    }
    getNative(el) {
        return el.shadowRoot
            ? el.shadowRoot.querySelector('button, input')
            : el;
    }
    handleKeyDown(event, trigger) {
        switch (event.key) {
            case 'Tab':
                return this.toggle(false);
            case 'Enter':
                const target = event.target;
                if (this.isDropdownOption(target))
                    this.getNative(target).click();
            case ' ':
                if (!trigger)
                    return;
                if (__classPrivateFieldGet(this, _value))
                    this.selectItem(__classPrivateFieldGet(this, _value));
                else
                    this.next();
                event.preventDefault();
                return;
            case 'Esc':
            case 'Escape':
                this.toggle(false);
                this.selectTrigger();
                return;
            case 'End':
                if (!trigger)
                    return;
                const last = __classPrivateFieldGet(this, _elItems)[__classPrivateFieldGet(this, _elItems).length - 1];
                return this.selectItem(last);
            case 'Home':
                if (!trigger)
                    return;
                const first = __classPrivateFieldGet(this, _elItems)[0];
                return this.selectItem(first);
            case 'Left':
            case 'ArrowLeft':
                if (trigger && __classPrivateFieldGet(this, _listbox))
                    return this.toggle(true);
            case 'Up':
            case 'ArrowUp':
                return this.prev(__classPrivateFieldGet(this, _selected) || __classPrivateFieldGet(this, _value));
            case 'Right':
            case 'ArrowRight':
                if (trigger && __classPrivateFieldGet(this, _listbox))
                    return this.toggle(true);
            case 'Down':
            case 'ArrowDown':
                return this.next(__classPrivateFieldGet(this, _selected) || __classPrivateFieldGet(this, _value));
            default:
                if (trigger && __classPrivateFieldGet(this, _listbox))
                    return this.toggle(true);
        }
    }
    isDropdownOption(el) {
        return !!el && el.type === 'dropdown';
    }
    selectItem(item) {
        if (!item)
            return;
        this.toggle(true);
        __classPrivateFieldSet(this, _selected, item);
        setTimeout(() => this.getNative(item).focus(), 100);
    }
    selectTrigger() {
        this.toggle(false);
        this.getNative(__classPrivateFieldGet(this, _elTrigger)).focus();
    }
    toggle(active) {
        __classPrivateFieldSet(this, _selected, undefined);
        __classPrivateFieldGet(this, _onToggle).call(this, active);
    }
}
_elItems = new WeakMap(), _elParent = new WeakMap(), _elTrigger = new WeakMap(), _listbox = new WeakMap(), _onToggle = new WeakMap(), _selected = new WeakMap(), _value = new WeakMap();
