import { Option } from "@opendaw/lib-std";
import { Events } from "@opendaw/lib-dom";
import { MenuItem } from "../menu/MenuItems";
export var ContextMenu;
(function (ContextMenu) {
    ContextMenu.CONTEXT_MENU_EVENT_TYPE = "--context-menu";
    class CollectorImpl {
        client;
        static collecting = Option.None;
        #root = MenuItem.root();
        #chain = Promise.resolve();
        #hasItems = false;
        #separatorBefore = false;
        constructor(client) {
            this.client = client;
        }
        get root() { return this.#root; }
        get hasItems() { return this.#hasItems; }
        addItems = (...items) => {
            items.forEach((item) => {
                if (item.hidden) {
                    return;
                }
                if (this.#separatorBefore) {
                    item.addSeparatorBefore();
                }
                this.#root.addMenuItem(item);
                this.#hasItems = true;
                this.#separatorBefore = false;
            });
            this.#separatorBefore = true;
            return this;
        };
        appendToChain = (fn) => {
            this.#chain = this.#chain.then(async () => { await fn(); });
        };
        waitForChain = () => this.#chain;
        abort() { CollectorImpl.collecting = Option.None; }
    }
    ContextMenu.install = (owner, menuFactory) => Events.subscribe(owner, "contextmenu", async (mouseEvent) => {
        if (CollectorImpl.collecting.nonEmpty()) {
            console.warn("One context-menu is still populating (abort)");
            return;
        }
        mouseEvent.preventDefault();
        const event = new Event(ContextMenu.CONTEXT_MENU_EVENT_TYPE, { bubbles: true, composed: true, cancelable: true });
        const collector = new CollectorImpl(mouseEvent);
        CollectorImpl.collecting = Option.wrap(collector);
        mouseEvent.target?.dispatchEvent(event);
        await collector.waitForChain();
        if (CollectorImpl.collecting.nonEmpty()) {
            if (collector.hasItems) {
                menuFactory(collector.root, mouseEvent);
            }
            CollectorImpl.collecting = Option.None;
        }
    }, { capture: true });
    ContextMenu.subscribe = (target, collect) => Events.subscribeAny(target, ContextMenu.CONTEXT_MENU_EVENT_TYPE, () => CollectorImpl.collecting.ifSome((collector) => {
        collector.appendToChain(() => collect(collector));
    }), { capture: false });
})(ContextMenu || (ContextMenu = {}));
