import { h, Host } from "@stencil/core";
import { validateProp } from "../../helpers/Validate/props";
import { TabColors, TabsClass, TabsItemClass, TabSizes, TabTypes } from "./constants";
import { booleanString, govHost, toBoolAttr } from "../../helpers/Dom/template";
import { hasOwnProperty } from "../../utils/helpers.types";
import { prepareIconFormat } from "../gov-icon/helpers";
import { AttributeObserver } from "../../helpers/Dom/attribute";
import { ariaAttributes } from "../../helpers/Accessibility/attributes";
import { inheritAriaAttributes } from "../../helpers/Accessibility/accessibility";
export class GovTabs {
    constructor() {
        this.triggerRefs = {};
        /**
         * Tabs type
         */
        this.type = "text";
        /**
         * Tabs size.
         */
        this.size = 'm';
        /**
         * Style variation of the tab chips.
         */
        this.color = "primary";
        /**
         * Tabs orientation
         */
        this.orientation = "horizontal";
        /**
         * Icon and description display direction
         */
        this.direction = 'row';
        this.controllers = [];
        this.focusIndex = 0;
        this.inheritedAttributes = {};
        this.h = govHost(this.host);
    }
    validateType(newValue) {
        validateProp(TabTypes, newValue, TabsClass.root);
    }
    validateColor(newValue) {
        validateProp(TabColors, newValue, TabsClass.root);
    }
    validateSize(newValue) {
        validateProp(TabSizes, newValue, TabsClass.root);
    }
    componentDidLoad() {
        this.attributeObserver = new AttributeObserver(this.host, (attributeName, newValue) => {
            this.onAriaAttributeChange(attributeName, newValue);
        });
        this.attributeObserver.startObserving(ariaAttributes);
    }
    componentWillLoad() {
        this.prepareControllers();
        this.validateSize(this.size);
        this.inheritedAttributes = inheritAriaAttributes(this.host);
    }
    disconnectedCallback() {
        var _a;
        (_a = this.attributeObserver) === null || _a === void 0 ? void 0 : _a.stopObserving();
    }
    onAriaAttributeChange(attributeName, newValue) {
        this.host.removeAttribute(attributeName);
        this.inheritedAttributes = Object.assign(Object.assign({}, this.inheritedAttributes), { [attributeName]: newValue });
    }
    prepareControllers(skipDefault = false) {
        this.controllers = [];
        const promises = [];
        this.host.querySelectorAll(':scope > ' + TabsItemClass.root).forEach((tab) => {
            const controlItem = Promise.all([
                tab.getIdentifier(),
                tab.getTriggerIdentifier(),
                tab.getDisableState()
            ]).then(([identifier, triggerIdentifier, disabled]) => {
                const isDefault = typeof tab.getAttribute("default") === "string";
                const iconStart = prepareIconFormat(tab.getAttribute('icon-start'));
                const iconEnd = prepareIconFormat(tab.getAttribute('icon-end'));
                return {
                    label: tab.getAttribute("label"),
                    direction: tab.getAttribute("direction"),
                    contentIdentifier: identifier,
                    disabled: disabled,
                    triggerIdentifier: triggerIdentifier,
                    element: tab,
                    active: false,
                    default: isDefault,
                    iconStart,
                    iconEnd
                };
            });
            promises.push(controlItem);
        });
        Promise.all(promises).then(controllers => {
            if (skipDefault === false) {
                let defaultTabIndex = controllers.findIndex(controller => controller.default);
                if (defaultTabIndex === -1)
                    defaultTabIndex = 0;
                this.focusIndex = defaultTabIndex;
                controllers[defaultTabIndex].active = true;
            }
            else if (this.focusIndex > -1 && hasOwnProperty(controllers, this.focusIndex)) {
                controllers[this.focusIndex].active = true;
            }
            const isWrongCombination = controllers.findIndex((controller) => controller.active && controller.disabled);
            if (isWrongCombination > -1) {
                controllers[isWrongCombination].active = false;
                const firstGoodTab = controllers.findIndex((controller) => !controller.disabled);
                if (firstGoodTab > -1) {
                    controllers[firstGoodTab].active = true;
                    this.focusIndex = firstGoodTab;
                }
            }
            this.controllers = [...controllers];
            this.reRender();
        });
    }
    setActiveByIdentifier(identifier) {
        const temp = [];
        this.controllers.map(item => {
            item.active = identifier === item.triggerIdentifier || identifier === item.contentIdentifier;
            temp.push(item);
        });
        this.controllers = [...temp];
    }
    reRender() {
        this.controllers.map(control => {
            control.element.setActiveStatus(control.active).catch();
        });
    }
    render() {
        return (h(Host, { key: '0b339dda9cd002b5548650f0f996d349842f4c8b', class: this.h.classes(TabsClass.root), size: this.size, color: this.color, type: this.type, direction: this.direction, onKeyDown: this.onKeydownHandler.bind(this) }, h("div", Object.assign({ key: '683da4323be50ee97c0f2b666423308b2feb6ff3', class: TabsClass.tabs, role: "tablist" }, this.inheritedAttributes), h("ul", { key: '0a255d6a8a57744c0636a41e567661775d450dee', class: TabsClass.list }, this.controllers.map(control => (h("li", { class: TabsClass.item }, this.type == "text" ? (h("button", { class: TabsClass.btn, id: control.triggerIdentifier, role: "tab", type: "button", onClick: () => this.onSelectHandler(control), disabled: control.disabled, "aria-disabled": toBoolAttr(control.disabled), "aria-selected": toBoolAttr(control.active), "aria-controls": control.contentIdentifier, tabindex: control.active && !control.disabled ? 0 : -1, ref: el => (this.triggerRefs[control.triggerIdentifier] = el) }, control.iconStart ? (h("gov-icon", { name: control.iconStart.name, type: control.iconStart.type })) : null, control.label, control.iconEnd ? (h("gov-icon", { name: control.iconEnd.name, type: control.iconEnd.type })) : null)) : (h("gov-chip", { role: "tab", tag: 'button', identifier: control.triggerIdentifier, "aria-selected": booleanString(control.active), "aria-controls": control.contentIdentifier, focusable: control.active, disabled: control.disabled, color: this.color, size: this.size === "xs" ? "xs" : (this.size === "s" ? "s" : "m"), type: control.active ? "solid" : "outlined", ref: el => (this.triggerRefs[control.triggerIdentifier] = el), "on-gov-click": () => this.onSelectHandler(control) }, control.iconStart ? (h("gov-icon", { name: control.iconStart.name, type: control.iconStart.type, slot: "icon-start" })) : null, control.label, control.iconEnd ? (h("gov-icon", { name: control.iconEnd.name, type: control.iconEnd.type, slot: "icon-end" })) : null))))))), h("slot", { key: '367950fe8ebba21bbe73c51a0d4c33efbb33e093' })));
    }
    getCurrentTab() {
        return this.controllers.find(control => control.active) || null;
    }
    onSelectHandler(control) {
        const index = this.controllers.findIndex(t => t.triggerIdentifier === control.triggerIdentifier);
        this.focusIndex = index;
        this.setActiveByIdentifier(control.triggerIdentifier);
        this.reRender();
        this.govChange.emit(this.getCurrentTab().element);
    }
    onKeydownHandler(e) {
        const keyCode = e.keyCode;
        e.stopPropagation();
        this.goToPrevNext(keyCode);
    }
    goToPrevNext(keyCode) {
        if ([37, 38, 39, 40].includes(keyCode)) {
            if (false === (this.focusIndex >= 0 && this.focusIndex <= this.controllers.length - 1)) {
                return;
            }
            this.controllers[this.focusIndex].active = false;
            if (keyCode === 39 || keyCode === 40) {
                this.focusIndex++;
                if (this.focusIndex >= this.controllers.length) {
                    this.focusIndex = 0;
                }
                if (this.controllers[this.focusIndex].disabled) {
                    this.goToPrevNext(40);
                }
            }
            else if (keyCode === 37 || keyCode === 38) {
                this.focusIndex--;
                if (this.focusIndex < 0) {
                    this.focusIndex = this.controllers.length - 1;
                }
                if (this.controllers[this.focusIndex].disabled) {
                    this.goToPrevNext(38);
                }
            }
            if (this.focusIndex >= 0 && this.focusIndex <= this.controllers.length - 1) {
                const current = this.controllers[this.focusIndex];
                current.active = true;
                const trigger = this.triggerRefs[current.triggerIdentifier];
                if (trigger.nodeName.toLowerCase() === 'gov-chip') {
                    this.triggerRefs[current.triggerIdentifier].setFocus();
                }
                else {
                    this.triggerRefs[current.triggerIdentifier].focus();
                }
                this.controllers = [...this.controllers];
                this.reRender();
                this.govChange.emit(this.getCurrentTab().element);
            }
        }
    }
    /**
     * Regenerate tabs controllers
     */
    async refresh() {
        this.prepareControllers();
    }
    /**
     * Returns the currently selected tabs-item
     */
    async currentTab() {
        return this.getCurrentTab().element || null;
    }
    /**
     * Regenerate tabs controllers
     */
    async setActiveTab(identifier) {
        this.setActiveByIdentifier(identifier);
        this.reRender();
    }
    /**
     * Regenerate tabs controllers
     */
    async rerender() {
        this.prepareControllers(true);
    }
    static get is() { return "gov-tabs"; }
    static get properties() {
        return {
            "type": {
                "type": "string",
                "attribute": "type",
                "mutable": false,
                "complexType": {
                    "original": "TabType",
                    "resolved": "\"chip\" | \"text\"",
                    "references": {
                        "TabType": {
                            "location": "import",
                            "path": "./constants",
                            "id": "../../../packages/core/src/components/gov-tabs/constants.ts::TabType"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Tabs type"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "\"text\""
            },
            "size": {
                "type": "string",
                "attribute": "size",
                "mutable": false,
                "complexType": {
                    "original": "TabSizeType",
                    "resolved": "\"l\" | \"m\" | \"s\" | \"xl\" | \"xs\"",
                    "references": {
                        "TabSizeType": {
                            "location": "import",
                            "path": "./constants",
                            "id": "../../../packages/core/src/components/gov-tabs/constants.ts::TabSizeType"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Tabs size."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'m'"
            },
            "color": {
                "type": "string",
                "attribute": "color",
                "mutable": false,
                "complexType": {
                    "original": "ColorType",
                    "resolved": "\"neutral\" | \"primary\"",
                    "references": {
                        "ColorType": {
                            "location": "import",
                            "path": "./constants",
                            "id": "../../../packages/core/src/components/gov-tabs/constants.ts::ColorType"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Style variation of the tab chips."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "\"primary\""
            },
            "orientation": {
                "type": "string",
                "attribute": "orientation",
                "mutable": false,
                "complexType": {
                    "original": "TabOrientationType",
                    "resolved": "\"horizontal\" | \"vertical\"",
                    "references": {
                        "TabOrientationType": {
                            "location": "import",
                            "path": "./constants",
                            "id": "../../../packages/core/src/components/gov-tabs/constants.ts::TabOrientationType"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Tabs orientation"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "\"horizontal\""
            },
            "direction": {
                "type": "string",
                "attribute": "direction",
                "mutable": false,
                "complexType": {
                    "original": "'row' | 'column'",
                    "resolved": "\"column\" | \"row\"",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Icon and description display direction"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "'row'"
            }
        };
    }
    static get states() {
        return {
            "controllers": {},
            "focusIndex": {},
            "inheritedAttributes": {}
        };
    }
    static get events() {
        return [{
                "method": "govChange",
                "name": "gov-change",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the tab is changed."
                },
                "complexType": {
                    "original": "HTMLGovTabsItemElement",
                    "resolved": "HTMLGovTabsItemElement",
                    "references": {
                        "HTMLGovTabsItemElement": {
                            "location": "global",
                            "id": "global::HTMLGovTabsItemElement"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "refresh": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Regenerate tabs controllers",
                    "tags": []
                }
            },
            "currentTab": {
                "complexType": {
                    "signature": "() => Promise<Nullable<HTMLGovTabsItemElement>>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "HTMLGovTabsItemElement": {
                            "location": "global",
                            "id": "global::HTMLGovTabsItemElement"
                        },
                        "Nullable": {
                            "location": "import",
                            "path": "../../types/interfaces",
                            "id": "../../../packages/core/src/types/interfaces.ts::Nullable"
                        }
                    },
                    "return": "Promise<HTMLGovTabsItemElement>"
                },
                "docs": {
                    "text": "Returns the currently selected tabs-item",
                    "tags": []
                }
            },
            "setActiveTab": {
                "complexType": {
                    "signature": "(identifier: string) => Promise<void>",
                    "parameters": [{
                            "name": "identifier",
                            "type": "string",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Regenerate tabs controllers",
                    "tags": []
                }
            },
            "rerender": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Regenerate tabs controllers",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "host"; }
    static get watchers() {
        return [{
                "propName": "type",
                "methodName": "validateType"
            }, {
                "propName": "color",
                "methodName": "validateColor"
            }, {
                "propName": "size",
                "methodName": "validateSize"
            }];
    }
}
//# sourceMappingURL=gov-tabs.js.map
