import { Host, h } from "@stencil/core";
import { detectClickOutside } from "../../../global/utils/detectClickOutside";
import { detectFocusOutside } from "../../../global/utils/detectFocusOutside";
import { randomIdGenerator } from "../../../global/utils/randomIdGenerator";
function deserializeProp(prop) {
    if (typeof prop === 'string') {
        return JSON.parse(prop);
    }
    return prop;
}
/**
 * @swedishName Rullgardinsmeny
 */
export class ContextMenu {
    constructor() {
        this.itemRefs = {};
        this.visible = false;
        this.activeItemIdx = undefined;
        this.selectItemIdx = 0;
        this.afId = randomIdGenerator('digi-context-menu');
        this.afIcon = undefined;
        this.afTitle = undefined;
        this.afMenuItems = undefined;
        this.afDir = undefined;
        this.afLang = undefined;
        this.afAriaLabel = undefined;
        this.afMenuPosition = 'left-bottom';
        this.afActiveItem = undefined;
    }
    clickHandler(e) {
        const target = e.target;
        const selector = `#${this.afId}-identifier`;
        if (detectClickOutside(target, selector) && this.visible) {
            this.hideMenu();
        }
    }
    focusoutHandler(e) {
        const target = e.target;
        const selector = `#${this.afId}-identifier`;
        if (detectFocusOutside(target, selector) && this.visible) {
            this.hideMenu();
            this.afBlur.emit();
        }
    }
    syncActiveItem() {
        if (this.afActiveItem != null) {
            const menuItems = this.afMenuItems;
            this.activeItemIdx = menuItems.findIndex((item) => item.id.toString() === this.afActiveItem);
        }
    }
    syncItems() {
        this.afMenuItems = deserializeProp(this.afMenuItems);
    }
    componentWillLoad() {
        this.syncItems();
        this.syncActiveItem();
    }
    get digiIcon() {
        if (this.afIcon != null) {
            return `digi-icon-${this.afIcon}`;
        }
    }
    hideMenu() {
        this.visible = false;
        this.afToggleMenu.emit(this.visible);
    }
    showMenu() {
        this.visible = true;
        this.afToggleMenu.emit(this.visible);
    }
    isLink() {
        if (this.afMenuItems && this.afMenuItems.length > 0) {
            const itemToCheck = this.afMenuItems[0];
            return itemToCheck.type && itemToCheck.type === 'link';
        }
        return false;
    }
    async handleToggle() {
        if (this.visible) {
            this.hideMenu();
            this.focusOnButton();
        }
        else {
            this.showMenu();
            if (!this.isLink()) {
                const idx = this.activeItemIdx || 0;
                const item = this.afMenuItems[idx];
                setTimeout(() => this.itemRefs[item.id].focus(), 25);
            }
        }
    }
    async focusOnButton() {
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-expect-error
        const digiButton = this.buttonRef;
        const button = (await digiButton.afMGetButtonElement());
        button.focus();
    }
    handleChangeItem(item, idx) {
        this.activeItemIdx = idx;
        this.handleToggle();
        this.afChangeItem.emit({ item, idx });
    }
    handleRef(ref, refId, payload) {
        if (refId === 'item') {
            this.itemRefs[payload.id] = ref;
        }
    }
    isActive(idx) {
        if ((this.activeItemIdx !== undefined || this.activeItemIdx !== null) &&
            this.activeItemIdx === idx) {
            return true;
        }
        return false;
    }
    isSelected(idx) {
        return this.selectItemIdx === idx;
    }
    nextIdx(idx) {
        if (idx > this.afMenuItems.length - 1) {
            return 0;
        }
        else if (idx < 0) {
            return this.afMenuItems.length - 1;
        }
        else {
            return idx;
        }
    }
    activateItem(idx) {
        const item = this.afMenuItems[idx];
        this.activeItemIdx = idx;
        this.focusItem(idx);
        this.handleChangeItem(item, idx);
    }
    focusItem(idx) {
        var _a;
        const item = this.afMenuItems[idx];
        this.selectItemIdx = idx;
        (_a = this.itemRefs[item.id]) === null || _a === void 0 ? void 0 : _a.focus();
        this.afFocusItem.emit({ item, idx });
    }
    focusCaptured() {
        const menuItems = this.afMenuItems;
        return menuItems.some((item) => this.itemRefs[item.id] === document.activeElement);
    }
    handleKey(e) {
        if (!this.focusCaptured())
            return;
        switch (e.key) {
            case 'ArrowUp':
                this.focusItem(this.nextIdx(this.selectItemIdx - 1));
                break;
            case 'ArrowDown':
                this.focusItem(this.nextIdx(this.selectItemIdx + 1));
                break;
            case 'Escape':
                this.hideMenu();
                this.focusOnButton();
                break;
            case 'Enter':
            case ' ':
                e.preventDefault();
                e.stopPropagation();
                this.activateItem(this.selectItemIdx);
                break;
            default:
                break;
        }
    }
    handleLinkClick(e, item, idx) {
        if (!item.overrideLink) {
            window.location.assign(item.href);
        }
        else {
            e.preventDefault();
            this.handleChangeItem(item, idx);
        }
    }
    renderLink(item, idx) {
        const menuItem = this.afMenuItems[idx];
        return (h("li", { id: `${this.afId}-listbox-item-${item.id}`, key: item.id, class: {
                'digi-navigation-context-menu__item': true,
                'digi-navigation-context-menu__item--link': true,
                'digi-navigation-context-menu__item--active': this.isActive(idx)
            }, dir: this.afDir, lang: this.afLang, ref: (ref) => { var _a; return (_a = this.handleRef) === null || _a === void 0 ? void 0 : _a.call(this, ref, 'item', item); } }, h("a", { "aria-label": item.ariaLabel ? item.ariaLabel : null, href: menuItem.href ? menuItem.href : null, onClick: (e) => this.handleLinkClick(e, item, idx) }, item.title)));
    }
    renderDiv(item, idx) {
        return (h("div", { role: "option", id: `${this.afId}-listbox-item-${item.id}`, key: item.id, class: {
                'digi-navigation-context-menu__item': true,
                'digi-navigation-context-menu__item--active': this.isActive(idx)
            }, dir: this.afDir, lang: this.afLang, "aria-selected": this.isActive(idx).toString(), tabIndex: this.isSelected(idx) ? 0 : -1, onClick: () => { var _a; return (_a = this.handleChangeItem) === null || _a === void 0 ? void 0 : _a.call(this, item, idx); }, ref: (ref) => { var _a; return (_a = this.handleRef) === null || _a === void 0 ? void 0 : _a.call(this, ref, 'item', item); } }, h("div", { class: "content-wrapper" }, h("digi-icon-check", { class: "digi-navigation-context-menu__button-icon", slot: "icon", style: {
                visibility: idx === this.activeItemIdx && this.visible
                    ? 'visible'
                    : 'hidden'
            } }), h("span", { "aria-label": item.ariaLabel ? item.ariaLabel : null }, item.title)), ' '));
    }
    render() {
        const menuItems = this.afMenuItems;
        return (h(Host, { key: 'd9024d6373cbed4e449d880eb5999921941311c8' }, h("div", { key: '2e71d1de06967dee77553c0e171338f0ec2a16b2', id: `${this.afId}-identifier`, class: {
                'digi-navigation-context-menu': true,
                'digi-navigation-context-menu--active': this.visible
            } }, h("digi-button", { key: 'f72ca1811f2c10873bff2cf6c6edfb6d690909b3', id: `${this.afId}-trigger`, ref: (ref) => (this.buttonRef = ref), onClick: () => this.handleToggle(), afVariation: "function", afAriaControls: `${this.afId}-dropdown`, afAriaExpanded: this.visible, afAriaLabel: this.afAriaLabel || null, class: "digi-navigation-context-menu__trigger-button" }, !!this.afIcon && h(this.digiIcon, { key: 'a7d28de1604540f5bc90ac45f92c11db03c9e3f4', slot: "icon" }), this.afTitle, h("digi-icon-chevron-down", { key: '39a9b3cc9d61b8a43f6b32391f20fdf183e620c4', class: "digi-navigation-context-menu__toggle-icon", slot: "icon-secondary" })), h("div", { key: 'f9a7c9014f2683e69c30fef9a586e0ff929d589f', class: {
                'digi-navigation-context-menu__list': true,
                'digi-navigation-context-menu__list--active': this.visible
            } }, h("div", { key: 'c31531d586d8214c2287f9c5d98902a0bd98c0a2', onKeyDown: (e) => {
                this.handleKey(e);
            }, id: `${this.afId}-dropdown`, style: {
                visibility: this.visible ? 'visible' : 'hidden'
            }, role: this.isLink() ? 'list' : 'listbox', "aria-labelledby": `${this.afId}-trigger`, class: {
                'dropdown-wrapper': true,
                'dropdown-wrapper--visible': this.visible,
                'dropdown-wrapper--position-right': this.afMenuPosition === 'right-bottom',
                'dropdown-wrapper--position-center': this.afMenuPosition === 'center-bottom'
            } }, menuItems &&
            menuItems.map((item, idx) => {
                const menuItem = menuItems[idx];
                if (menuItem.type && (menuItem === null || menuItem === void 0 ? void 0 : menuItem.type) === 'link') {
                    return this.renderLink(item, idx);
                }
                return this.renderDiv(item, idx);
            }))))));
    }
    static get is() { return "digi-context-menu"; }
    static get encapsulation() { return "scoped"; }
    static get originalStyleUrls() {
        return {
            "$": ["navigation-context-menu.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["navigation-context-menu.css"]
        };
    }
    static get properties() {
        return {
            "afId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Sets a unique Id. If not set, one will be created"
                        }],
                    "text": "(Frivillig) Om du vill att komponenten ska ha ett unikt ID, kan du skicka in detta h\u00E4r, annars genereras ett automatiskt"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-id",
                "reflect": false,
                "defaultValue": "randomIdGenerator('digi-context-menu')"
            },
            "afIcon": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Sets which icon that should be shown"
                        }],
                    "text": "Anv\u00E4nds till att v\u00E4lja ikon som visas, skriv i namnet p\u00E5 ikonen"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-icon",
                "reflect": false
            },
            "afTitle": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Sets the title of the button"
                        }],
                    "text": "S\u00E4tter titeln p\u00E5 knappen"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-title",
                "reflect": false
            },
            "afMenuItems": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string | ContextMenuItem[]",
                    "resolved": "ContextMenuItem[] | string",
                    "references": {
                        "ContextMenuItem": {
                            "location": "import",
                            "path": "./navigation-context-menu.types",
                            "id": "src/components/_navigation/navigation-context-menu/navigation-context-menu.types.ts::ContextMenuItem"
                        }
                    }
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Sets the title of the button"
                        }],
                    "text": "Lista av typen ContextMenuItem som"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-menu-items",
                "reflect": false
            },
            "afDir": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "HTMLDir",
                    "resolved": "\"auto\" | \"ltr\" | \"rtl\"",
                    "references": {
                        "HTMLDir": {
                            "location": "import",
                            "path": "./navigation-context-menu.types",
                            "id": "src/components/_navigation/navigation-context-menu/navigation-context-menu.types.ts::HTMLDir"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Sets dir-attribute"
                        }],
                    "text": "S\u00E4tter dir-attributet"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-dir",
                "reflect": false
            },
            "afLang": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Sets lang-attribute"
                        }],
                    "text": "S\u00E4tter lang-attributet"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-lang",
                "reflect": false
            },
            "afAriaLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Sets aria-label on expandable button"
                        }],
                    "text": "S\u00E4tter aria-label p\u00E5 expanderbar knapp"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-aria-label",
                "reflect": false
            },
            "afMenuPosition": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "ContextMenuPosition",
                    "resolved": "\"center-bottom\" | \"left-bottom\" | \"right-bottom\"",
                    "references": {
                        "ContextMenuPosition": {
                            "location": "import",
                            "path": "./navigation-context-menu.types",
                            "id": "src/components/_navigation/navigation-context-menu/navigation-context-menu.types.ts::ContextMenuPosition"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "When menu item is activated"
                        }],
                    "text": "N\u00E4r menyalternativ \u00E4r valt"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-menu-position",
                "reflect": false,
                "defaultValue": "'left-bottom'"
            },
            "afActiveItem": {
                "type": "any",
                "mutable": false,
                "complexType": {
                    "original": "ContextMenuItem['id']",
                    "resolved": "number | string",
                    "references": {
                        "ContextMenuItem": {
                            "location": "import",
                            "path": "./navigation-context-menu.types",
                            "id": "src/components/_navigation/navigation-context-menu/navigation-context-menu.types.ts::ContextMenuItem"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Sets a preselected value. In React this has to be of the type string."
                        }],
                    "text": "S\u00E4tter ett f\u00F6rvalt v\u00E4rde. I React m\u00E5ste detta vara av typen string."
                },
                "getter": false,
                "setter": false,
                "attribute": "af-active-item",
                "reflect": false
            }
        };
    }
    static get states() {
        return {
            "visible": {},
            "activeItemIdx": {},
            "selectItemIdx": {}
        };
    }
    static get events() {
        return [{
                "method": "afChangeItem",
                "name": "afChangeItem",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "When menu item is activated"
                        }],
                    "text": "N\u00E4r menyalternativ \u00E4r valt"
                },
                "complexType": {
                    "original": "ContextMenuEventItem",
                    "resolved": "ContextMenuEventItem",
                    "references": {
                        "ContextMenuEventItem": {
                            "location": "import",
                            "path": "./navigation-context-menu.types",
                            "id": "src/components/_navigation/navigation-context-menu/navigation-context-menu.types.ts::ContextMenuEventItem"
                        }
                    }
                }
            }, {
                "method": "afFocusItem",
                "name": "afFocusItem",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "When focus change between menu items"
                        }],
                    "text": "N\u00E4r fokus flyttar mellan menyalternativ"
                },
                "complexType": {
                    "original": "ContextMenuEventItem",
                    "resolved": "ContextMenuEventItem",
                    "references": {
                        "ContextMenuEventItem": {
                            "location": "import",
                            "path": "./navigation-context-menu.types",
                            "id": "src/components/_navigation/navigation-context-menu/navigation-context-menu.types.ts::ContextMenuEventItem"
                        }
                    }
                }
            }, {
                "method": "afToggleMenu",
                "name": "afToggleMenu",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "When the menu opens / closes"
                        }],
                    "text": "N\u00E4r menyn \u00F6ppnas / st\u00E4ngs"
                },
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                }
            }, {
                "method": "afBlur",
                "name": "afBlur",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "When focus moves on to another element"
                        }],
                    "text": "N\u00E4r fokus g\u00E5r \u00F6ver till ett annat element"
                },
                "complexType": {
                    "original": "any",
                    "resolved": "any",
                    "references": {}
                }
            }];
    }
    static get watchers() {
        return [{
                "propName": "afActiveItem",
                "methodName": "syncActiveItem"
            }, {
                "propName": "afMenuItems",
                "methodName": "syncItems"
            }];
    }
    static get listeners() {
        return [{
                "name": "click",
                "method": "clickHandler",
                "target": "window",
                "capture": false,
                "passive": false
            }, {
                "name": "focusin",
                "method": "focusoutHandler",
                "target": "document",
                "capture": false,
                "passive": false
            }];
    }
}
