import { library } from '@fortawesome/fontawesome-svg-core';
import { faCaretDown } from '@fortawesome/free-solid-svg-icons';
import { h } from "@stencil/core";
import { HEIGHT_HEADER } from '../../utils/constants';
import { ripple } from '../../utils/ripple';
library.add(faCaretDown);
export class Link {
    constructor() {
        // #endregion
        this._height = 0;
        this._links = 0;
        this.handleClick = (event) => {
            // Toggle self
            if (this._links)
                this.toggle();
            // A custom navigate function can be passed and allows client-side routing
            // without a page refresh.
            if (this.navigate &&
                event.button === 0 &&
                (!this.target || this.target === '_self') &&
                !this.isModifiedEvent(event)) {
                event.preventDefault();
                this.navigate(event);
            }
        };
        this.handleKeyDown = (event) => {
            const sub = this.el.getAttribute('slot') === 'menu';
            switch (event.keyCode) {
                // Enter & Space
                case 13:
                case 32:
                    return this.moveIntoFirst();
                // Escape
                case 27:
                    return sub ? this.moveOut() : this.toggle(false);
                // End
                case 35:
                    return this.focusOther(this.getSiblings().pop());
                // Home
                case 36:
                    return this.focusOther(this.getSiblings()[0]);
                // Arrow Left
                case 37:
                    return sub ? this.moveOutPrev() : this.movePrev();
                // Arrow Up
                case 38:
                    return sub ? this.movePrev() : this.moveIntoLast();
                // Arrow Right
                case 39:
                    return sub ? this.moveOutNext() : this.moveNext();
                // Arrow Down
                case 40:
                    return sub ? this.moveNext() : this.moveIntoFirst();
            }
        };
        this.handleMouseDown = (event) => {
            ripple(this.el.shadowRoot.querySelector('a'), event);
        };
        this.handleSlotChange = () => {
            this._links = this.getChildren(this.el).length;
            if (this._links)
                this.toggle(!!this.open);
        };
    }
    watchHref() {
        const { href } = this;
        const hash = href && href.indexOf('#') >= 0 && '#' + href.split('#').pop();
        this.hash = hash || undefined;
    }
    async toggle(active) {
        this.open = active != undefined ? active : !this.open;
        this._height = this.open ? (this._links || 0) * HEIGHT_HEADER : 0;
    }
    focusOther(el) {
        el.shadowRoot.querySelector('a').focus();
        this.tab = false;
        el.tab = true;
    }
    getChildren(el) {
        const nodes = Array.from(el.childNodes);
        return nodes.filter(node => node.nodeName === 'BCE-LINK');
    }
    getParent(grand = false) {
        const query = grand ? 'bce-link:not([slot="menu"])' : 'bce-link';
        return this.el.parentElement.closest(query);
    }
    getSiblings(el = this.el) {
        return this.getChildren(el.parentElement);
    }
    moveIntoFirst() {
        if (!this._links)
            return;
        this.toggle(true);
        this.focusOther(this.getChildren(this.el)[0]);
    }
    moveIntoLast() {
        if (!this._links)
            return;
        this.toggle(true);
        this.focusOther(this.getChildren(this.el).pop());
    }
    moveNext(el = this.el) {
        const siblings = this.getSiblings(el);
        const index = siblings.indexOf(el);
        const next = siblings[this.modulo(index + 1, siblings.length)];
        this.focusOther(next);
        next.toggle(el.open);
        el.toggle(false);
    }
    moveOut() {
        const parent = this.getParent();
        if (!parent)
            return;
        this.focusOther(parent);
        parent.toggle(false);
    }
    moveOutNext() {
        const parent = this.getParent();
        if (parent)
            this.moveNext(parent);
    }
    moveOutPrev() {
        const parent = this.getParent();
        if (parent)
            this.movePrev(parent);
    }
    movePrev(el = this.el) {
        const siblings = this.getSiblings(el);
        const index = siblings.indexOf(el);
        const prev = siblings[this.modulo(index - 1, siblings.length)];
        this.focusOther(prev);
        prev.toggle(el.open);
        el.toggle(false);
    }
    modulo(i1, i2) {
        return ((i1 % i2) + i2) % i2;
    }
    isModifiedEvent(event) {
        return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
    }
    componentWillLoad() {
        this.handleSlotChange();
        this.watchHref();
    }
    componentDidLoad() {
        const root = this.el.shadowRoot;
        const query = "slot[name='menu']";
        const slot = root.querySelector(query);
        slot === null || slot === void 0 ? void 0 : slot.addEventListener('slotchange', this.handleSlotChange);
    }
    renderCaret() {
        return h("bce-icon", { "data-toggle": true, pre: "fas", name: "caret-down", "fixed-width": true });
    }
    render() {
        return (h("li", { role: "none" },
            h("a", { download: this.download, href: this.href, hreflang: this.hreflang, media: this.media, rel: this.rel, role: "menuitem", target: this.target, tabIndex: this.tab ? 0 : -1, onClick: this.handleClick, onKeyDown: this.handleKeyDown, onMouseDown: this.handleMouseDown, "aria-expanded": !!this._links && this.open, "aria-haspopup": !!this._links },
                this.icon && h("bce-icon", { raw: this.icon, "fixed-width": true }),
                h("span", null,
                    h("slot", null)),
                !!this._links && this.renderCaret()),
            h("ul", { role: "menu", style: { height: `${this._height}px` } },
                h("slot", { name: "menu" }))));
    }
    static get is() { return "bce-link"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() { return {
        "bce-header": ["bce-link.header.scss"],
        "bce-link": ["bce-link.link.scss"],
        "default": ["bce-link.scss"]
    }; }
    static get styleUrls() { return {
        "bce-header": ["bce-link.header.css"],
        "bce-link": ["bce-link.link.css"],
        "default": ["bce-link.css"]
    }; }
    static get properties() { return {
        "color": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "color",
            "reflect": true
        },
        "hash": {
            "type": "string",
            "mutable": true,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "hash",
            "reflect": false
        },
        "icon": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "icon",
            "reflect": true
        },
        "tab": {
            "type": "boolean",
            "mutable": true,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "tab",
            "reflect": false
        },
        "navigate": {
            "type": "unknown",
            "mutable": false,
            "complexType": {
                "original": "(event: MouseEvent) => void",
                "resolved": "(event: MouseEvent) => void",
                "references": {
                    "MouseEvent": {
                        "location": "global"
                    }
                }
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            }
        },
        "open": {
            "type": "boolean",
            "mutable": true,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "open",
            "reflect": true
        },
        "download": {
            "type": "boolean",
            "mutable": false,
            "complexType": {
                "original": "boolean",
                "resolved": "boolean",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "download",
            "reflect": true
        },
        "href": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "href",
            "reflect": true
        },
        "hreflang": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "hreflang",
            "reflect": true
        },
        "media": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "media",
            "reflect": true
        },
        "rel": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "rel",
            "reflect": true
        },
        "target": {
            "type": "string",
            "mutable": false,
            "complexType": {
                "original": "string",
                "resolved": "string",
                "references": {}
            },
            "required": false,
            "optional": true,
            "docs": {
                "tags": [],
                "text": ""
            },
            "attribute": "target",
            "reflect": true
        }
    }; }
    static get states() { return {
        "_height": {},
        "_links": {}
    }; }
    static get methods() { return {
        "toggle": {
            "complexType": {
                "signature": "(active?: boolean) => Promise<void>",
                "parameters": [{
                        "tags": [],
                        "text": ""
                    }],
                "references": {
                    "Promise": {
                        "location": "global"
                    }
                },
                "return": "Promise<void>"
            },
            "docs": {
                "text": "",
                "tags": []
            }
        }
    }; }
    static get elementRef() { return "el"; }
    static get watchers() { return [{
            "propName": "href",
            "methodName": "watchHref"
        }]; }
}
