/*!
 * KoliBri - The accessible HTML-Standard
 */
import { __decorate } from "tslib";
import { h } from "@stencil/core";
import { devHint, koliBriQuerySelector, setState, uiUxHintMillerscheZahl, validateAlign, validateLabel, validateTabBehavior, watchJsonArrayString, watchNumber, } from "../../schema";
import { KolButtonWcTag } from "../../core/component-names";
import { translate } from "../../i18n";
import { KeyboardKey } from "../../schema/enums";
import { validateHasCreateButton } from "../../schema/props/has-create-button";
import clsx from "../../utils/clsx";
import { createCtaRef, delegateClick, delegateFocus } from "../../utils/element-interaction";
import { dispatchDomEvent, KolEvent } from "../../utils/events";
export class KolTabs {
    constructor() {
        this.onCreateLabel = `${translate('kol-new')} …`;
        this.ctaRef = createCtaRef();
        this.nextPossibleTabIndex = (tabs, offset, step = 1) => {
            const nextOffset = offset + step;
            if (nextOffset < tabs.length) {
                if (tabs[nextOffset]._disabled) {
                    return this.nextPossibleTabIndex(tabs, offset, step + 1);
                }
                return nextOffset;
            }
            return offset;
        };
        this.prevPossibleTabIndex = (tabs, offset, step = 1) => {
            const nextOffset = offset - step;
            if (nextOffset >= 0) {
                if (tabs[nextOffset]._disabled) {
                    return this.prevPossibleTabIndex(tabs, offset, step + 1);
                }
                return nextOffset;
            }
            return offset;
        };
        this.onKeyDown = (event) => {
            switch (event.key) {
                case KeyboardKey.ArrowRight:
                    this.goToNextTab(event);
                    break;
                case KeyboardKey.ArrowLeft:
                    this.goToPreviousTab(event);
                    break;
                case KeyboardKey.Space:
                case KeyboardKey.Enter:
                    this.activateFocusedTab(event);
                    break;
            }
        };
        this.onClickSelect = (event, index) => {
            this.selectNextTabEvent(event, index);
        };
        this.onMouseDown = (event) => {
            event.preventDefault();
        };
        this.callbacks = {
            onClick: this.onClickSelect,
            onMouseDown: this.onMouseDown,
        };
        this.catchTabPanelHost = (el) => {
            this.tabPanelHost = el;
        };
        this._align = 'top';
        this._hasCreateButton = false;
        this._selected = 0;
        this.state = {
            _align: 'top',
            _label: '',
            _selected: 0,
            _tabs: [],
        };
        this.selectNextNotDisabledTab = (selected, tabs, upOrDown = true, initialSelected) => {
            if (selected > tabs.length - 1) {
                selected = tabs.length - 1;
            }
            if (selected < 0) {
                selected = 0;
            }
            if (Array.isArray(tabs) && tabs[selected]) {
                if (tabs[selected]._disabled) {
                    if (upOrDown === true) {
                        if (selected < tabs.length - 1) {
                            return this.selectNextNotDisabledTab(selected + 1, tabs, true, initialSelected || selected);
                        }
                        else {
                            selected = initialSelected || selected;
                            upOrDown = false;
                        }
                    }
                    if (upOrDown === false) {
                        if (selected > 0) {
                            return this.selectNextNotDisabledTab(selected - 1, tabs, false, initialSelected || selected);
                        }
                        else {
                            devHint(`[KolTabs] All tabs are disabled, and therefore no tab can be displayed.`);
                        }
                    }
                }
            }
            return selected;
        };
        this.syncSelectedAndTabs = (nextValue, nextState, _component, key) => {
            let selected;
            if (key === '_selected') {
                selected = nextValue;
            }
            else {
                selected = this.state._selected;
            }
            let tabs;
            if (key === '_tabs') {
                tabs = nextValue;
            }
            else {
                tabs = this.state._tabs;
            }
            if (tabs.length > 0) {
                nextState.set('_selected', this.selectNextNotDisabledTab(selected, tabs));
            }
        };
        this.refreshTabPanels = () => {
            var _a, _b, _c, _d;
            if (!this.tabPanelHost)
                return;
            while (this.tabPanelHost.firstChild) {
                this.tabPanelHost.removeChild(this.tabPanelHost.firstChild);
            }
            for (let i = 0; i < ((_a = this.state._tabs) === null || _a === void 0 ? void 0 : _a.length); i++) {
                const div = document.createElement('div');
                div.setAttribute('aria-labelledby', `${this.state._label.replace(/\s/g, '-')}-tab-${i}`);
                div.setAttribute('id', `tabpanel-${i}`);
                div.setAttribute('role', 'tabpanel');
                div.setAttribute('hidden', '');
                div.setAttribute('tabindex', '0');
                const slot = document.createElement('slot');
                slot.setAttribute('name', `tabpanel-slot-${i}`);
                div.appendChild(slot);
                (_b = this.tabPanelHost) === null || _b === void 0 ? void 0 : _b.appendChild(div);
                if (typeof HTMLCollection !== 'undefined' && ((_c = this.host) === null || _c === void 0 ? void 0 : _c.children) instanceof HTMLCollection && ((_d = this.host) === null || _d === void 0 ? void 0 : _d.children[i])) {
                    this.host.children[i].setAttribute('slot', `tabpanel-slot-${i}`);
                }
            }
            this.updateVisiblePanel();
        };
        this.updateVisiblePanel = () => {
            if (!this.tabPanelHost)
                return;
            Array.from(this.tabPanelHost.children).forEach((child, i) => {
                if (i === this.state._selected) {
                    child.removeAttribute('hidden');
                }
                else {
                    child.setAttribute('hidden', '');
                }
            });
        };
        this.onCreate = (event) => {
            var _a, _b;
            event.preventDefault();
            (_b = (_a = this.state._on) === null || _a === void 0 ? void 0 : _a.onCreate) === null || _b === void 0 ? void 0 : _b.call(_a, event);
            if (this.host) {
                dispatchDomEvent(this.host, KolEvent.create);
            }
        };
        this.onBlur = () => {
            this.currentFocusIndex = undefined;
        };
    }
    getCurrentFocusIndex() {
        if (typeof this.currentFocusIndex === 'number') {
            return this.currentFocusIndex;
        }
        return this.state._selected;
    }
    getKeyboardTabChangeMode() {
        if (this._behavior === 'select-manual') {
            return 'selectFocusOnly';
        }
        return 'activateCompletely';
    }
    goToNextTab(event) {
        const nextFocusIndex = this.nextPossibleTabIndex(this.state._tabs, this.getCurrentFocusIndex());
        this.selectNextTabEvent(event, nextFocusIndex, this.getKeyboardTabChangeMode());
    }
    goToPreviousTab(event) {
        const nextFocusIndex = this.prevPossibleTabIndex(this.state._tabs, this.getCurrentFocusIndex());
        this.selectNextTabEvent(event, nextFocusIndex, this.getKeyboardTabChangeMode());
    }
    activateFocusedTab(event) {
        if (typeof this.currentFocusIndex === 'number') {
            this.onSelect(event, this.currentFocusIndex);
        }
    }
    selectNextTabEvent(event, nextTabIndex, changeMode = 'activateCompletely') {
        var _a, _b;
        this.currentFocusIndex = nextTabIndex;
        this.focusTabById(nextTabIndex);
        if (changeMode === 'activateCompletely') {
            this._selected = nextTabIndex;
            const tab = this.state._tabs[nextTabIndex];
            (_b = (_a = tab._on) === null || _a === void 0 ? void 0 : _a.onSelect) === null || _b === void 0 ? void 0 : _b.call(_a, event, nextTabIndex);
            this.onSelect(event, nextTabIndex);
        }
    }
    async focus(options) { }
    async click() { }
    renderButtonGroup() {
        return (h("div", { "aria-label": this.state._label, class: "kol-tabs__button-group", role: "tablist", onKeyDown: this.onKeyDown, onBlur: this.onBlur }, this.state._tabs.map((button, index) => (h(KolButtonWcTag, { ref: this.state._selected === index ? this.ctaRef : undefined, _disabled: button._disabled, _icons: button._icons, _hideLabel: button._hideLabel, _label: button._label, _on: this.callbacks, _tabIndex: this.state._selected === index ? 0 : -1, _tooltipAlign: button._tooltipAlign, _variant: this.state._selected === index ? 'custom' : undefined, _customClass: this.state._selected === index ? 'selected' : '', _ariaControls: `tabpanel-${index}`, _ariaSelected: this.state._selected === index, _id: `${this.state._label.replace(/\s/g, '-')}-tab-${index}`, _role: "tab", _value: index }))), this.state._hasCreateButton && (h(KolButtonWcTag, { class: "kol-tabs__button-create", _label: this.onCreateLabel, _on: {
                onClick: this.onCreate,
            }, _icons: "kolicon-plus", "data-testid": "tabs-create-button" }))));
    }
    render() {
        return (h("div", { key: 'cbac3f2cf4f389e4bdcd4a83c463a339a4f587c4', ref: (el) => {
                this.tabPanelsElement = el;
            }, class: clsx('kol-tabs', `kol-tabs--align-${this.state._align}`) }, this.renderButtonGroup(), h("div", { key: 'cd0aa9f1a4e1e5dc5facdf0d1d6e58013bf4bc40', class: "kol-tabs__content", ref: this.catchTabPanelHost })));
    }
    validateAlign(value) {
        validateAlign(this, value);
    }
    validateBehavior(value) {
        validateTabBehavior(this, value);
    }
    validateHasCreateButton(value) {
        validateHasCreateButton(this, value);
    }
    validateLabel(value) {
        validateLabel(this, value, {
            required: true,
        });
    }
    validateOn(value) {
        if (typeof value === 'object' && value !== null) {
            const callbacks = {};
            if (typeof value.onCreate === 'function') {
                callbacks.onCreate = value.onCreate;
            }
            if (typeof value.onSelect === 'function') {
                callbacks.onSelect = value.onSelect;
            }
            setState(this, '_on', callbacks);
        }
    }
    validateSelected(value) {
        watchNumber(this, '_selected', value, {
            hooks: {
                beforePatch: this.syncSelectedAndTabs,
            },
        });
    }
    validateTabs(value) {
        watchJsonArrayString(this, '_tabs', (item) => typeof item === 'object' && item !== null && typeof item._label === 'string' && item._label.length > 0, value, undefined, {
            hooks: {
                beforePatch: this.syncSelectedAndTabs,
                afterPatch: this.refreshTabPanels,
            },
        });
        uiUxHintMillerscheZahl('KolTabs', this.state._tabs.length);
    }
    componentWillLoad() {
        this.validateAlign(this._align);
        this.validateLabel(this._label);
        this.validateOn(this._on);
        this.validateSelected(this._selected);
        this.validateTabs(this._tabs);
        this.validateBehavior(this._behavior);
        this.validateHasCreateButton(this._hasCreateButton);
    }
    componentDidRender() {
        this.refreshTabPanels();
    }
    focusTabById(index) {
        if (this.tabPanelsElement) {
            const button = koliBriQuerySelector(`button#${this.state._label.replace(/\s/g, '-')}-tab-${index}`, this.tabPanelsElement);
            button === null || button === void 0 ? void 0 : button.focus();
        }
    }
    onSelect(event, index) {
        var _a, _b;
        (_b = (_a = this._on) === null || _a === void 0 ? void 0 : _a.onSelect) === null || _b === void 0 ? void 0 : _b.call(_a, event, index);
        if (this.host) {
            dispatchDomEvent(this.host, KolEvent.select, index);
        }
        this.focusTabById(index);
    }
    static get is() { return "kol-tabs"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "default": ["./style.scss"]
        };
    }
    static get styleUrls() {
        return {
            "default": ["style.css"]
        };
    }
    static get properties() {
        return {
            "_align": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "AlignPropType",
                    "resolved": "\"bottom\" | \"left\" | \"right\" | \"top\" | undefined",
                    "references": {
                        "AlignPropType": {
                            "location": "import",
                            "path": "../../schema",
                            "id": "src/schema/index.ts::AlignPropType"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Defines the visual orientation of the component."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "_align",
                "defaultValue": "'top'"
            },
            "_behavior": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "TabBehaviorPropType",
                    "resolved": "\"select-automatic\" | \"select-manual\" | undefined",
                    "references": {
                        "TabBehaviorPropType": {
                            "location": "import",
                            "path": "../../schema",
                            "id": "src/schema/index.ts::TabBehaviorPropType"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Defines which behavior is active."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "_behavior"
            },
            "_hasCreateButton": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "HasCreateButtonPropType",
                    "resolved": "boolean | undefined",
                    "references": {
                        "HasCreateButtonPropType": {
                            "location": "import",
                            "path": "../../schema/props/has-create-button",
                            "id": "src/schema/props/has-create-button.ts::HasCreateButtonPropType"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Defines whether the element has a create button."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "_has-create-button",
                "defaultValue": "false"
            },
            "_label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "LabelPropType",
                    "resolved": "string",
                    "references": {
                        "LabelPropType": {
                            "location": "import",
                            "path": "../../schema",
                            "id": "src/schema/index.ts::LabelPropType"
                        }
                    }
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Defines the visible or semantic label of the component (e.g. aria-label, label, headline, caption, summary, etc.)."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "_label"
            },
            "_on": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "KoliBriTabsCallbacks",
                    "resolved": "undefined | { onCreate?: EventCallback<Event> | undefined; } & { onSelect?: EventValueOrEventCallback<MouseEvent | KeyboardEvent | CustomEvent<any> | PointerEvent, number> | undefined; }",
                    "references": {
                        "KoliBriTabsCallbacks": {
                            "location": "import",
                            "path": "../../schema",
                            "id": "src/schema/index.ts::KoliBriTabsCallbacks"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Gibt die Liste der Callback-Funktionen an, die auf Events aufgerufen werden sollen."
                },
                "getter": false,
                "setter": false
            },
            "_selected": {
                "type": "number",
                "mutable": true,
                "complexType": {
                    "original": "number",
                    "resolved": "number | undefined",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Defines which tab is active."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "_selected",
                "defaultValue": "0"
            },
            "_tabs": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "Stringified<TabButtonProps[]>",
                    "resolved": "TabButtonProps[] | string",
                    "references": {
                        "Stringified": {
                            "location": "import",
                            "path": "../../schema",
                            "id": "src/schema/index.ts::Stringified"
                        },
                        "TabButtonProps": {
                            "location": "import",
                            "path": "../../schema",
                            "id": "src/schema/index.ts::TabButtonProps"
                        }
                    }
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Defines the tab captions."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "_tabs"
            }
        };
    }
    static get states() {
        return {
            "state": {}
        };
    }
    static get methods() {
        return {
            "focus": {
                "complexType": {
                    "signature": "(options?: KolFocusOptions) => Promise<void>",
                    "parameters": [{
                            "name": "options",
                            "type": "KolFocusOptions | undefined",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "KolFocusOptions": {
                            "location": "import",
                            "path": "../../schema",
                            "id": "src/schema/index.ts::KolFocusOptions"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Sets focus on the current tab button.",
                    "tags": []
                }
            },
            "click": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Triggers a click on the currently selected tab.",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "host"; }
    static get watchers() {
        return [{
                "propName": "_align",
                "methodName": "validateAlign"
            }, {
                "propName": "_behavior",
                "methodName": "validateBehavior"
            }, {
                "propName": "_hasCreateButton",
                "methodName": "validateHasCreateButton"
            }, {
                "propName": "_label",
                "methodName": "validateLabel"
            }, {
                "propName": "_on",
                "methodName": "validateOn"
            }, {
                "propName": "_selected",
                "methodName": "validateSelected"
            }, {
                "propName": "_tabs",
                "methodName": "validateTabs"
            }];
    }
}
__decorate([
    delegateFocus('ctaRef')
], KolTabs.prototype, "focus", null);
__decorate([
    delegateClick('ctaRef')
], KolTabs.prototype, "click", null);
//# sourceMappingURL=shadow.js.map
