import { Host, h, } from "@stencil/core";
import { DEVICE_SIZES, getCurrentDeviceSize, getBrandForegroundAppearance, getNavItemParentDetails, } from "../../utils/helpers";
import chevronIcon from "../../assets/chevron-icon.svg";
const IC_NAVIGATION_ITEM = "ic-navigation-item";
const DYNAMIC_GROUPED_LINKS_HEIGHT_MS = 100;
const NODE_NAME = "IC-NAVIGATION-GROUP";
export class NavigationGroup {
    constructor() {
        this.allGroupedNavigationItemHeights = "";
        this.collapsedNavItemsHeight = null;
        this.expandedNavItemsHeight = null;
        this.mouseGate = false;
        this.deviceSize = DEVICE_SIZES.XL;
        this.dropdownOpen = false;
        this.focusStyle = getBrandForegroundAppearance();
        this.inTopNavSideMenu = false;
        this.isSideNavExpanded = false;
        /**
         *  If `true`, the group will be expandable when in an ic-side-navigation component, or, when in an ic-top-navigation component, in the side menu displayed at small screen sizes.
         */
        this.expandable = false;
        /**
         * If `true`, the expandable group will be expanded by default when in an ic-side-navigation component. To enable this prop, `expandable` must also be set to `true`.
         */
        this.expanded = true;
        /**
         * Sets the theme color to the dark or light theme color. "inherit" will set the color based on the system settings or ic-theme component.
         */
        this.theme = "inherit";
        this.sideNavExpandHandler = (event) => {
            this.isSideNavExpanded = event.detail.sideNavExpanded;
            if (!this.linkWrapper || !this.expanded)
                return;
            const navItemsHeight = this.isSideNavExpanded
                ? this.expandedNavItemsHeight
                : this.collapsedNavItemsHeight;
            if (navItemsHeight) {
                this.setGroupedLinksElementHeight(navItemsHeight);
            }
            else {
                setTimeout(() => {
                    if (this.isSideNavExpanded) {
                        this.expandedNavItemsHeight = this.allGroupedNavigationItemHeights;
                    }
                    else {
                        this.collapsedNavItemsHeight = this.allGroupedNavigationItemHeights;
                    }
                    this.setGroupedLinksElementHeight(this.allGroupedNavigationItemHeights);
                }, DYNAMIC_GROUPED_LINKS_HEIGHT_MS);
            }
        };
        this.topNavResizedHandler = ({ detail: { size }, }) => {
            var _a;
            if (size === this.deviceSize)
                return;
            this.deviceSize = size;
            this.inTopNavSideMenu =
                size <=
                    (((_a = this.parentEl) === null || _a === void 0 ? void 0 : _a.customMobileBreakpoint) ||
                        DEVICE_SIZES.L);
        };
        this.toggleExpanded = () => {
            this.expanded = !this.expanded;
            if (!this.linkWrapper)
                return;
            this.setGroupedLinksElementHeight(!this.expanded
                ? "0"
                : this.isSideNavExpanded
                    ? this.expandedNavItemsHeight
                    : this.collapsedNavItemsHeight);
            this.el.querySelectorAll(IC_NAVIGATION_ITEM).forEach((navigationItem) => {
                var _a;
                const navItem = ((_a = navigationItem.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector("a")) ||
                    navigationItem.querySelector("a");
                navItem === null || navItem === void 0 ? void 0 : navItem.setAttribute("tabindex", this.expanded ? "0" : "-1");
            });
        };
        this.handleClick = (ev) => {
            if (this.navigationType === "top" && ev.detail) {
                this.toggleDropdown();
            }
            else {
                this.toggleExpanded();
            }
        };
        this.handleBlur = (ev) => {
            if (!this.el.contains(ev.relatedTarget)) {
                this.hideDropdown();
            }
        };
        this.handleKeydown = (ev) => {
            const { key } = ev;
            if (key !== "Enter" && key !== " " && key !== "Escape")
                return;
            switch (this.navigationType) {
                case "top":
                    if (key === " " || key === "Enter") {
                        this.toggleDropdown();
                    }
                    else if (!this.inTopNavSideMenu) {
                        this.hideDropdown();
                    }
                    break;
                case "side":
                    this.toggleExpanded();
                    ev.preventDefault();
                    break;
                default:
                    this.toggleExpanded();
                    break;
            }
        };
        this.handleMouseLeave = (ev) => {
            const relTarget = ev.relatedTarget;
            this.mouseGate = false;
            if (this.el.contains(relTarget) ||
                relTarget === this.dropdown ||
                this.el.contains(document.activeElement))
                return;
            if (document.activeElement !== this.el &&
                (relTarget === null || relTarget === void 0 ? void 0 : relTarget.nodeName) === NODE_NAME &&
                this.dropdownOpen) {
                this.mouseGate = true;
                this.hideDropdown();
            }
            else {
                this.mouseGate = false;
                setTimeout(() => {
                    this.dropdownOpen ? this.hideDropdown() : null;
                }, 500);
            }
        };
        this.handleMouseEnter = (ev) => {
            const relTarget = ev.relatedTarget;
            document.addEventListener("keydown", this.handleKeydown);
            if ((relTarget === null || relTarget === void 0 ? void 0 : relTarget.nodeName) === NODE_NAME && this.mouseGate) {
                this.showDropdown();
            }
            else if (!this.dropdownOpen && !this.mouseGate) {
                this.mouseGate = true;
                setTimeout(() => {
                    if (this.mouseGate)
                        this.showDropdown();
                }, 500);
            }
        };
        this.renderGroupTitleText = () => (h("ic-typography", { id: "nav-group-title", variant: this.navigationType === "side" ? "caption" : "label" }, this.label));
        this.renderNavigationItems = () => {
            if (this.dropdownOpen || (this.inTopNavSideMenu && !this.expandable)) {
                return (h("div", { class: {
                        [this.inTopNavSideMenu
                            ? "navigation-group-dropdown-side-menu"
                            : "navigation-group-dropdown"]: true,
                        selected: this.dropdownOpen && !this.inTopNavSideMenu,
                    }, onMouseLeave: !this.inTopNavSideMenu ? this.handleMouseLeave : undefined, ref: (el) => (this.dropdown = el) }, h("nav", { class: {
                        "navigation-group-dropdown-items": !this.inTopNavSideMenu,
                    }, "aria-labelledby": "nav-group-title" }, h("ul", null, h("slot", null)))));
            }
            if (this.navigationType !== "top") {
                return (h("ul", { ref: (el) => (this.linkWrapper = el), class: "grouped-links-wrapper" }, h("slot", null)));
            }
            return null;
        };
        this.setGroupedLinksElementHeight = (height) => {
            var _a;
            (_a = this.linkWrapper) === null || _a === void 0 ? void 0 : _a.style.setProperty("--navigation-child-items-height", height);
        };
    }
    disconnectedCallback() {
        var _a, _b;
        if (this.navigationType === "side") {
            (_a = this.parentEl) === null || _a === void 0 ? void 0 : _a.removeEventListener("icSideNavExpanded", this.sideNavExpandHandler);
        }
        else if (this.navigationType === "top") {
            (_b = this.parentEl) === null || _b === void 0 ? void 0 : _b.removeEventListener("icTopNavResized", this.topNavResizedHandler);
        }
    }
    componentWillLoad() {
        var _a, _b;
        this.deviceSize = getCurrentDeviceSize();
        const { navType, parent } = getNavItemParentDetails(this.el);
        this.navigationType = navType;
        this.parentEl = parent;
        if (this.navigationType === "side") {
            (_a = this.parentEl) === null || _a === void 0 ? void 0 : _a.addEventListener("icSideNavExpanded", this.sideNavExpandHandler);
        }
        else if (this.navigationType === "top") {
            (_b = this.parentEl) === null || _b === void 0 ? void 0 : _b.addEventListener("icTopNavResized", this.topNavResizedHandler);
            if (this.deviceSize <=
                this.parentEl.customMobileBreakpoint)
                this.inTopNavSideMenu = true;
        }
    }
    componentDidLoad() {
        this.allGroupedNavigationItemHeights = `${Array.from(this.el.querySelectorAll(IC_NAVIGATION_ITEM)).reduce((childrenHeights, { offsetHeight }) => childrenHeights + offsetHeight, 0)}px`;
        /**
         * debounce is required as the incorrect height was retrieved instantly after
         * componentDidLoad is invoked.
         */
        setTimeout(() => {
            if (!this.linkWrapper || !this.expanded)
                return;
            if (!this.isSideNavExpanded)
                this.collapsedNavItemsHeight = this.allGroupedNavigationItemHeights;
            else
                this.expandedNavItemsHeight = this.allGroupedNavigationItemHeights;
            this.setGroupedLinksElementHeight(this.allGroupedNavigationItemHeights);
        }, DYNAMIC_GROUPED_LINKS_HEIGHT_MS);
    }
    childBlurHandler() {
        this.hideDropdown();
    }
    handleNavigationGroupOpened(event) {
        if (event.detail.source !== this.el) {
            this.hideDropdown();
        }
    }
    navItemClickHandler() {
        this.hideDropdown();
    }
    brandChangeHandler(ev) {
        this.focusStyle = ev.detail.mode;
    }
    /**
     * Sets focus on the nav item.
     */
    async setFocus() {
        var _a;
        (_a = this.groupEl) === null || _a === void 0 ? void 0 : _a.focus();
    }
    toggleDropdown() {
        this.dropdownOpen = !this.dropdownOpen;
        if (this.inTopNavSideMenu) {
            this.navigationGroupExpanded.emit({ expanded: this.dropdownOpen });
        }
    }
    showDropdown() {
        if (!this.dropdownOpen) {
            this.navigationGroupOpened.emit({
                source: this.el,
            });
            this.toggleDropdown();
        }
    }
    hideDropdown() {
        document.removeEventListener("keydown", this.handleKeydown);
        if (this.dropdownOpen) {
            this.toggleDropdown();
        }
    }
    render() {
        const { dropdownOpen, expanded, inTopNavSideMenu, expandable, theme, isSideNavExpanded, focusStyle, } = this;
        const getExpandedClassSuffix = (prop) => prop ? "expanded" : "collapsed";
        const navGroupTitleClassNames = {
            "navigation-group": true,
            [focusStyle]: !inTopNavSideMenu,
            [`navigation-group-side-menu-${getExpandedClassSuffix(dropdownOpen)}`]: inTopNavSideMenu && expandable,
            selected: dropdownOpen && !inTopNavSideMenu,
        };
        const isSideNav = this.navigationType === "side";
        const isTopNav = this.navigationType === "top";
        const isTopNavDesktop = !inTopNavSideMenu && isTopNav;
        const ariaExpanded = (isSideNav && expanded) || (isTopNav && dropdownOpen);
        return (h(Host, { key: '8beae9a83bf5800290e744c9f0ede4b3136d9d44', class: {
                "in-side-menu": inTopNavSideMenu,
                "ic-navigation-group-expandable": expandable,
                "ic-navigation-group-side-nav": isSideNav,
                [`ic-navigation-group-${getExpandedClassSuffix(expanded)}`]: true,
                [`ic-theme-${theme}`]: theme !== "inherit",
            }, role: "listitem" }, expandable || isTopNavDesktop ? (h("button", { onMouseEnter: isTopNavDesktop ? this.handleMouseEnter : undefined, onMouseLeave: isTopNav ? this.handleMouseLeave : undefined, onBlur: this.handleBlur, onClick: this.handleClick, onKeyDown: this.handleKeydown, class: navGroupTitleClassNames, ref: (el) => (this.groupEl = el), "aria-expanded": `${ariaExpanded}`, "aria-haspopup": `${isTopNavDesktop}` }, this.renderGroupTitleText(), isSideNav && expandable && (h("div", { class: {
                "chevron-toggle-icon-wrapper": true,
                "chevron-toggle-icon-closed": !!expanded,
            }, innerHTML: chevronIcon })))) : ((!isSideNav || isSideNavExpanded) && (h("div", { class: navGroupTitleClassNames }, this.renderGroupTitleText()))), this.renderNavigationItems()));
    }
    static get is() { return "ic-navigation-group"; }
    static get encapsulation() { return "shadow"; }
    static get delegatesFocus() { return true; }
    static get originalStyleUrls() {
        return {
            "$": ["ic-navigation-group.css"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["ic-navigation-group.css"]
        };
    }
    static get properties() {
        return {
            "expandable": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the group will be expandable when in an ic-side-navigation component, or, when in an ic-top-navigation component, in the side menu displayed at small screen sizes."
                },
                "getter": false,
                "setter": false,
                "attribute": "expandable",
                "reflect": false,
                "defaultValue": "false"
            },
            "expanded": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "If `true`, the expandable group will be expanded by default when in an ic-side-navigation component. To enable this prop, `expandable` must also be set to `true`."
                },
                "getter": false,
                "setter": false,
                "attribute": "expanded",
                "reflect": false,
                "defaultValue": "true"
            },
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The label to display on the group."
                },
                "getter": false,
                "setter": false,
                "attribute": "label",
                "reflect": false
            },
            "theme": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "IcThemeMode",
                    "resolved": "\"dark\" | \"inherit\" | \"light\"",
                    "references": {
                        "IcThemeMode": {
                            "location": "import",
                            "path": "../../utils/types",
                            "id": "src/utils/types.ts::IcThemeMode"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Sets the theme color to the dark or light theme color. \"inherit\" will set the color based on the system settings or ic-theme component."
                },
                "getter": false,
                "setter": false,
                "attribute": "theme",
                "reflect": false,
                "defaultValue": "\"inherit\""
            }
        };
    }
    static get states() {
        return {
            "deviceSize": {},
            "dropdownOpen": {},
            "focusStyle": {},
            "inTopNavSideMenu": {},
            "navigationType": {},
            "parentEl": {},
            "isSideNavExpanded": {}
        };
    }
    static get events() {
        return [{
                "method": "navigationGroupOpened",
                "name": "navigationGroupOpened",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "internal",
                            "text": "Emitted when a navigation group is opened - when within an ic-top-navigation at large screen sizes."
                        }],
                    "text": ""
                },
                "complexType": {
                    "original": "IcNavigationOpenEventDetail",
                    "resolved": "IcNavigationOpenEventDetail",
                    "references": {
                        "IcNavigationOpenEventDetail": {
                            "location": "import",
                            "path": "./ic-navigation-group.types",
                            "id": "src/components/ic-navigation-group/ic-navigation-group.types.ts::IcNavigationOpenEventDetail"
                        }
                    }
                }
            }, {
                "method": "navigationGroupExpanded",
                "name": "navigationGroupExpanded",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "internal",
                            "text": "Emitted when a navigation group is expanded - when within an ic-top-navigation at small screen sizes."
                        }],
                    "text": ""
                },
                "complexType": {
                    "original": "IcNavigationExpandEventDetail",
                    "resolved": "IcNavigationExpandEventDetail",
                    "references": {
                        "IcNavigationExpandEventDetail": {
                            "location": "import",
                            "path": "./ic-navigation-group.types",
                            "id": "src/components/ic-navigation-group/ic-navigation-group.types.ts::IcNavigationExpandEventDetail"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "setFocus": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Sets focus on the nav item.",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get listeners() {
        return [{
                "name": "childBlur",
                "method": "childBlurHandler",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "navigationGroupOpened",
                "method": "handleNavigationGroupOpened",
                "target": "document",
                "capture": false,
                "passive": false
            }, {
                "name": "navItemClicked",
                "method": "navItemClickHandler",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "brandChange",
                "method": "brandChangeHandler",
                "target": "document",
                "capture": false,
                "passive": false
            }];
    }
}
//# sourceMappingURL=ic-navigation-group.js.map
