import { h, Host } from "@stencil/core";
import { Direction, OverflowMode } from "./navigation-tablist.types";
/**
 * @slot default - <digi-tablist-panel /> för varje flik
 * @swedishName Flikfält
 */
export class NavigationTablist {
    constructor() {
        this.tabRefs = {};
        this.handleResize = () => {
            if (!this.tablistRef)
                return;
            // Ensure we measure after any layout/paint from the resize
            if (this._requestAnimationFrame)
                cancelAnimationFrame(this._requestAnimationFrame);
            this._requestAnimationFrame = requestAnimationFrame(() => {
                var _a, _b;
                const el = this.tablistRef;
                const containerWidth = el.clientWidth;
                const contentWidth = el.scrollWidth;
                // Tolerance ≈ 1 physical pixel to absorb zoom/subpixel jitter
                const tolerance = 1 / ((window === null || window === void 0 ? void 0 : window.devicePixelRatio) || 1);
                // Guard against div-by-zero
                const tabsCount = Math.max((_b = (_a = this.tabs) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0, 1);
                const avgTabWidth = contentWidth / tabsCount;
                // How many whole tabs fit? Nudge by tolerance to avoid off-by-one at zoom edges
                const tabsPerWindow = Math.floor((containerWidth + tolerance) / avgTabWidth);
                this.tabsPerWindow = Math.max(1, Math.min(tabsPerWindow, tabsCount));
                // Ensure windowTab stays within valid bounds after resize
                const maxValidWindowTab = Math.max(0, tabsCount - this.tabsPerWindow);
                if (this.windowTab > maxValidWindowTab) {
                    this.windowTab = maxValidWindowTab;
                }
                // Overflow check with tolerance
                this.listOverflows = contentWidth - containerWidth > tolerance;
                // (Optional) if you have left/right “handles”, compute visibility too:
                this.showPrev = el.scrollLeft > tolerance;
                this.showNext =
                    el.scrollLeft + el.clientWidth < el.scrollWidth - tolerance;
            });
        };
        this.activeTab = 0;
        this.selectedTab = 0;
        this.windowTab = 0;
        this.tabsPerWindow = undefined;
        this.tabs = [];
        this.listOverflows = false;
        this.showPrev = false;
        this.showNext = false;
        this.afTabs = undefined;
        this.afOverflowMode = OverflowMode.Controls;
        this.afAriaLabelledby = undefined;
        this.afAriaLabel = undefined;
        this.afInitialTab = undefined;
        this.afActiveTab = undefined;
    }
    handleKey(e) {
        if (this.focusCaptured()) {
            let captureKey = true;
            switch (e.key) {
                case ' ':
                case 'Enter':
                    return this.setActiveTabAndFocus(this.selectedTab);
                case 'ArrowLeft':
                    if (e.shiftKey) {
                        this.handleTabControl(Direction.Previous);
                    }
                    else {
                        this.focusTab(this.selectedTab - 1);
                    }
                    break;
                case 'ArrowRight':
                    if (e.shiftKey) {
                        this.handleTabControl(Direction.Next);
                    }
                    else {
                        this.focusTab(this.selectedTab + 1);
                    }
                    break;
                case 'Home':
                    if (e.shiftKey) {
                        return this.focusTab(0);
                    }
                    else {
                        return this.moveWindow(0);
                    }
                case 'End':
                    if (e.shiftKey) {
                        return this.focusTab(this.tabs.length - 1);
                    }
                    else {
                        return this.moveWindow(this.tabs.length - 1);
                    }
                default:
                    captureKey = false;
            }
            if (captureKey) {
                e.preventDefault();
            }
        }
    }
    syncPanels() {
        // side-effect
        if (this.panelsRef != null) {
            const panels = this.panelsRef.querySelectorAll(':scope>digi-tablist-panel');
            for (let i = 0; i < panels.length; i++) {
                const panel = panels[i];
                const showPanel = panel.tab === this.tabs[this.activeTab].id;
                panel.isVisible = showPanel;
            }
        }
    }
    handleTabPropChange(tabId) {
        this.setActiveTabById(tabId);
    }
    syncControls() {
        const tabGroup = Math.floor(this.windowTab / this.tabsPerWindow);
        const numberOfGroups = Math.ceil(this.tabs.length / this.tabsPerWindow);
        this.showPrev = tabGroup > 0;
        this.showNext = tabGroup < numberOfGroups - 1;
    }
    syncWindow(tabIdx) {
        const tab = this.tabs[tabIdx];
        const tabRef = this.tabRefs[tab.id];
        const listBox = this.tablistRef.getBoundingClientRect();
        const tabBox = tabRef.getBoundingClientRect();
        const centeredOffset = tabRef.offsetLeft - listBox.width / 2 + tabBox.width / 2;
        const maxLeft = this.tablistRef.scrollWidth - listBox.width;
        const left = Math.max(Math.min(centeredOffset, maxLeft), 0);
        this.tablistRef.scrollTo({
            left,
            behavior: 'smooth'
        });
    }
    syncFocus(tabIdx) {
        const tabRef = this.tabRefs[this.tabs[tabIdx].id];
        tabRef.focus({ preventScroll: true });
        this.windowTab = tabIdx;
    }
    setupTabs(tabs) {
        if (typeof tabs === 'string') {
            this.tabs = JSON.parse(tabs);
        }
        else if (Array.isArray(tabs)) {
            this.tabs = tabs;
        }
        else {
            throw new Error('Invalid format or no tabs supplied');
        }
    }
    setActiveTabById(id) {
        const tabIdx = this.tabs.findIndex((tab) => tab.id === id);
        if (tabIdx > -1) {
            this.activeTab = tabIdx;
        }
    }
    setupInitialTab() {
        if (this.afActiveTab != null) {
            return this.setActiveTabById(this.afActiveTab);
        }
        else if (this.afInitialTab != null) {
            return this.setActiveTabById(this.afInitialTab);
        }
    }
    setupResizeHandler() {
        this.resizeObserver = new ResizeObserver(() => this.handleResize());
        this.resizeObserver.observe(this.tablistRef);
    }
    handleTabChange(tab) {
        const idx = this.tabs.findIndex(({ id }) => id === tab.id);
        this.setActiveTabAndFocus(idx);
        this.afTabChange.emit(tab);
    }
    handleTabControl(direction) {
        // Calculate the current window group
        const currentGroup = Math.floor(this.windowTab / this.tabsPerWindow);
        const totalGroups = Math.ceil(this.tabs.length / this.tabsPerWindow);
        let newGroup;
        if (direction === Direction.Next) {
            newGroup = Math.min(currentGroup + 1, totalGroups - 1);
        }
        else {
            newGroup = Math.max(currentGroup - 1, 0);
        }
        // Move to the first tab of the target group
        const newWindowTab = newGroup * this.tabsPerWindow;
        this.moveWindow(newWindowTab);
    }
    setActiveTabAndFocus(tabIdx) {
        this.activeTab = tabIdx;
        this.focusTab(tabIdx);
    }
    focusTab(tabIdx) {
        this.selectedTab = this.nextTabIdx(tabIdx);
        const currentTab = this.tabs[this.selectedTab];
        this.afTabFocusChange.emit(currentTab);
    }
    moveWindow(tabIdx) {
        tabIdx = Math.max(0, Math.min(tabIdx, this.tabs.length - 1));
        this.windowTab = tabIdx;
    }
    nextTabIdx(tabIdx) {
        if (tabIdx >= this.tabs.length) {
            return 0;
        }
        else if (tabIdx < 0) {
            return this.tabs.length - 1;
        }
        return tabIdx;
    }
    focusCaptured() {
        return this.tabs.some((tab) => this.tabRefs[tab.id] === document.activeElement);
    }
    componentWillLoad() {
        this.setupTabs(this.afTabs);
        this.setupInitialTab();
    }
    componentDidLoad() {
        var _a, _b, _c;
        // Also listen to window resize for viewport zoom changes
        if (window) {
            window.addEventListener('resize', this.handleResize, { passive: true });
        }
        // Recalculate once fonts finish loading (text width changes with webfonts)
        (_c = (_b = (_a = document.fonts) === null || _a === void 0 ? void 0 : _a.ready) === null || _b === void 0 ? void 0 : _b.then) === null || _c === void 0 ? void 0 : _c.call(_b, () => this.handleResize());
        this.setupResizeHandler();
        this.handleResize();
        this.syncPanels();
        this.syncControls();
    }
    disconnectedCallback() {
        var _a;
        if (window) {
            window.removeEventListener('resize', this.handleResize);
        }
        (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
        if (this._requestAnimationFrame)
            cancelAnimationFrame(this._requestAnimationFrame);
    }
    render() {
        return (h(Host, { key: 'e22f722a4c757ec957c64d5449820e684763bb65' }, h("div", { key: '55bbc66dcc0ffb5eaa57a8e940bb6905848d2521', class: {
                'digi-tablist': true,
                'digi-tablist--overflow-scroll': this.afOverflowMode === OverflowMode.Scroll,
                'digi-tablist--overflow-controls': this.afOverflowMode === OverflowMode.Controls
            } }, h("div", { key: '154ea8adad1a5b5214ccf8d612e4abf12990954e', class: "control-wrapper", style: {
                left: '0',
                visibility: this.showPrev ? 'visible' : 'hidden'
            } }, h("button", { key: '8e892d55eeb0a2c0a2de93349a79aa7d1875f0ea', tabIndex: -1, type: "button", "aria-hidden": "true", class: { 'tab-control-button': true }, onClick: () => this.handleTabControl(Direction.Previous) }, h("digi-icon-chevron-left", { key: 'f6233af64182b94ccce487c3e86fde611ed3b034' }))), h("div", { key: 'dee9d980df6972bdcc8adb73dce382ecdf3fe678', role: "tablist", ref: (ref) => (this.tablistRef = ref), "aria-labelledby": this.afAriaLabelledby, "aria-label": this.afAriaLabel }, this.tabs.map((tab) => {
            const focusable = tab.id === this.tabs[this.selectedTab].id;
            const isActive = tab.id === this.tabs[this.activeTab].id;
            const Icon = `digi-icon-${tab.icon}`;
            const badgeValue = tab.badgeValue;
            return (h("button", { ref: (ref) => (this.tabRefs[tab.id] = ref), class: {
                    'digi-tab': true,
                    'is-active': isActive
                }, id: `tab-${tab.id}`, role: "tab", type: "button", tabindex: focusable ? '0' : '-1', "aria-label": tab.ariaLabel, "aria-selected": isActive.toString(), "aria-controls": `tabpanel-${tab.id}`, onClick: () => this.handleTabChange(tab) }, h("div", { class: "content-wrapper" }, h("span", { class: "tablist-content" }, tab.icon && h(Icon, { "aria-hidden": "true" }), h("span", { class: "title", "data-text": tab.title }, tab.title), tab.badgeValue && (h("digi-badge-notification", { afValue: badgeValue, "aria-hidden": "true" }))), h("div", { class: "indicator" }))));
        })), h("div", { key: '57eada501609bc43a04ad550faaf8ba3ea438fdb', class: "control-wrapper", style: {
                right: '0',
                visibility: this.showNext ? 'visible' : 'hidden'
            } }, h("button", { key: 'a6fe0443e2ecdd5f5287ccb230ce4920cbb6dfed', tabIndex: -1, type: "button", "aria-hidden": "true", class: { 'tab-control-button': true }, onClick: () => this.handleTabControl(Direction.Next) }, h("digi-icon-chevron-right", { key: '3fd2841059d9f5459a8e649c5c80c3d2a665ad0f' })))), h("div", { key: '908fae2fd08df7ad97ef997165c60d189cd2dcb3', ref: (ref) => (this.panelsRef = ref), role: "presentation" }, h("slot", { key: '90ef134162054396c99986d74585689b176364c3' }))));
    }
    static get is() { return "digi-tablist"; }
    static get encapsulation() { return "scoped"; }
    static get originalStyleUrls() {
        return {
            "$": ["navigation-tablist.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["navigation-tablist.css"]
        };
    }
    static get properties() {
        return {
            "afTabs": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "TabItem[] | string",
                    "resolved": "TabItem[] | string",
                    "references": {
                        "TabItem": {
                            "location": "import",
                            "path": "./navigation-tablist.types",
                            "id": "src/components/_navigation/navigation-tablist/navigation-tablist.types.ts::TabItem"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Set tabs"
                        }],
                    "text": "Best\u00E4mmer flikar"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-tabs",
                "reflect": false
            },
            "afOverflowMode": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "OverflowMode",
                    "resolved": "OverflowMode.Controls | OverflowMode.Scroll",
                    "references": {
                        "OverflowMode": {
                            "location": "import",
                            "path": "./navigation-tablist.types",
                            "id": "src/components/_navigation/navigation-tablist/navigation-tablist.types.ts::OverflowMode"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Set overflow behaviour"
                        }],
                    "text": "Best\u00E4mmer beteende d\u00E5 flikar \u00F6verfl\u00F6dar\n*"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-overflow-mode",
                "reflect": false,
                "defaultValue": "OverflowMode.Controls"
            },
            "afAriaLabelledby": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Set aria-labelledby for tablist"
                        }],
                    "text": "Best\u00E4mmer aria-label p\u00E5 listan av flikar"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-aria-labelledby",
                "reflect": false
            },
            "afAriaLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Set aria-label for tablist"
                        }],
                    "text": "Best\u00E4mmer aria-label p\u00E5 listan av flikar"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-aria-label",
                "reflect": false
            },
            "afInitialTab": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Active tab at start, using tab id"
                        }],
                    "text": "Flik som \u00E4r aktiv vid start, anv\u00E4nder flikens id"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-initial-tab",
                "reflect": false
            },
            "afActiveTab": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Active tab, using tab id"
                        }],
                    "text": "Flik som \u00E4r aktiv, anv\u00E4nder flikens id"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-active-tab",
                "reflect": false
            }
        };
    }
    static get states() {
        return {
            "activeTab": {},
            "selectedTab": {},
            "windowTab": {},
            "tabsPerWindow": {},
            "tabs": {},
            "listOverflows": {},
            "showPrev": {},
            "showNext": {}
        };
    }
    static get events() {
        return [{
                "method": "afTabChange",
                "name": "afTabChange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Emitted when a tab is activated"
                        }],
                    "text": "Skickas n\u00E4r en flik aktiveras, dvs vid klick eller med space/enter\u2010tangentklick p\u00E5 markerad flik. Fliken som aktiveras finns under event.detail"
                },
                "complexType": {
                    "original": "TabItem",
                    "resolved": "TabItem",
                    "references": {
                        "TabItem": {
                            "location": "import",
                            "path": "./navigation-tablist.types",
                            "id": "src/components/_navigation/navigation-tablist/navigation-tablist.types.ts::TabItem"
                        }
                    }
                }
            }, {
                "method": "afTabFocusChange",
                "name": "afTabFocusChange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Emitted when a tab is focus\u2010marked"
                        }],
                    "text": "Skickas n\u00E4r en flik fokusmarkeras samt vid klick. Fliken som markeras finns under event.detail"
                },
                "complexType": {
                    "original": "TabItem",
                    "resolved": "TabItem",
                    "references": {
                        "TabItem": {
                            "location": "import",
                            "path": "./navigation-tablist.types",
                            "id": "src/components/_navigation/navigation-tablist/navigation-tablist.types.ts::TabItem"
                        }
                    }
                }
            }];
    }
    static get watchers() {
        return [{
                "propName": "activeTab",
                "methodName": "syncPanels"
            }, {
                "propName": "afActiveTab",
                "methodName": "handleTabPropChange"
            }, {
                "propName": "windowTab",
                "methodName": "syncControls"
            }, {
                "propName": "listOverflows",
                "methodName": "syncControls"
            }, {
                "propName": "windowTab",
                "methodName": "syncWindow"
            }, {
                "propName": "selectedTab",
                "methodName": "syncFocus"
            }, {
                "propName": "afTabs",
                "methodName": "setupTabs"
            }];
    }
    static get listeners() {
        return [{
                "name": "keydown",
                "method": "handleKey",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
