import { h, Host } from "@stencil/core";
import { randomIdGenerator } from "../../../global/utils/randomIdGenerator";
import { logger } from "../../../global/utils/logger";
import { detectClickOutside } from "../../../global/utils/detectClickOutside";
import { detectFocusOutside } from "../../../global/utils/detectFocusOutside";
import { _t } from "../../../text";
/**
 * @slot default - Ska vara formulärselement. Till exempel digi-form-checkbox.
 * @swedishName Multifilter
 */
export class FormFilter {
    constructor() {
        this.refs = {};
        this.listItems = [];
        this.checkedItems = [];
        this.tabItems = [];
        this.isActive = false;
        this.activeListItemIndex = 0;
        this.afId = randomIdGenerator('digi-form-filter');
        this.afFilterButtonText = undefined;
        this.afSubmitButtonText = undefined;
        this.afSubmitButtonTextAriaLabel = undefined;
        this.afResetButtonText = _t.clear;
        this.afResetButtonTextAriaLabel = undefined;
        this.afHideResetButton = false;
        this.afAlignRight = undefined;
        this.afName = undefined;
        this.afFilterButtonAriaLabel = undefined;
        this.afFilterButtonAriaDescribedby = undefined;
        this.afAutofocus = undefined;
        this.afListItems = undefined;
        this.afCheckItems = [];
    }
    syncCheckItems() {
        this.checkedItems = this.afCheckItems;
    }
    handleListItems() {
        if (this.afListItems) {
            // via props
            this.setupListProps(this.afListItems);
        }
        else {
            // child elements
            this.setupListElements(this.slotRef.children);
        }
    }
    setupAccessibility() {
        // set default tabIndex to first filter
        if (this.tabItems.length === 0 && this.listItems.length > 0) {
            this.tabItems = [this.listItems.at(0).id];
        }
    }
    setupListProps(userItems) {
        try {
            if (Array.isArray(userItems)) {
                this.listItems = userItems;
            }
            else if (typeof userItems === 'string') {
                this.listItems = JSON.parse(userItems);
            }
            else {
                throw `Invalid type in "af-list-items" attribute`;
            }
        }
        catch (e) {
            logger.warn(`Invalid JSON in "af-list-items" attribute`, this.hostElement, e);
            return;
        }
    }
    clickHandler(e) {
        var _a;
        const target = e.target;
        const rootId = (_a = this.refs.root) === null || _a === void 0 ? void 0 : _a.id;
        if (rootId) {
            if (detectClickOutside(target, `#${rootId}`) && this.isActive) {
                this.hideMenu();
            }
        }
    }
    focusoutHandler(e) {
        var _a;
        const target = e.target;
        const rootId = (_a = this.refs.root) === null || _a === void 0 ? void 0 : _a.id;
        const focusOutsideFilter = detectFocusOutside(target, `#${rootId}`);
        if (focusOutsideFilter && this.isActive) {
            this.hideMenu();
        }
        else {
            this.afBlurFilter.emit({
                filterName: this.afName
            });
        }
    }
    setupListElements(collection) {
        if (!collection || collection.length <= 0) {
            logger.warn(`The slot contains no filter elements.`, this.slotRef);
            return;
        }
        this.listItems = [...collection].map((element, i) => ({
            id: element.afId || i.toString(),
            label: element.afLabel
        }));
    }
    componentWillLoad() {
        this.syncCheckItems();
    }
    componentDidLoad() {
        this.handleListItems();
        this.setupSlot();
    }
    setupSlot() {
        if (!window.MutationObserver) {
            return;
        } // for tests
        const observer = new window.MutationObserver(() => {
            this.setupListElements(this.slotRef.children);
        });
        observer.observe(this.slotRef, { childList: true });
    }
    incrementFocus() {
        if (this.activeListItemIndex < this.listItems.length - 1) {
            this.focusItem(this.activeListItemIndex + 1);
        }
    }
    decrementFocus() {
        if (this.activeListItemIndex > 0) {
            this.focusItem(this.activeListItemIndex - 1);
        }
    }
    handleKey(e) {
        switch (e.key) {
            case 'ArrowDown':
                return this.incrementFocus();
            case 'ArrowUp':
                return this.decrementFocus();
            case 'Home':
                return this.focusItem(0);
            case 'End':
                return this.focusItem(this.listItems.length - 1);
            case 'Enter':
                e.target.click();
                break;
            case 'Escape':
                return this.hideMenu();
        }
    }
    focusItem(idx) {
        var _a;
        this.activeListItemIndex = idx;
        const currentItem = this.listItems.at(idx);
        if (currentItem && this.refs.filter) {
            (_a = this.refs.filter[currentItem.id]) === null || _a === void 0 ? void 0 : _a.focus();
        }
        this.tabItems = [currentItem === null || currentItem === void 0 ? void 0 : currentItem.id];
    }
    hideMenu() {
        var _a;
        this.isActive = false;
        (_a = this.refs.toggle) === null || _a === void 0 ? void 0 : _a.focus();
        this.afCloseFilter.emit({
            filterName: this.afName,
            listItems: this.listItems,
            checked: this.checkedItems
        });
    }
    showMenu() {
        this.isActive = true;
        setTimeout(() => this.focusItem(0), 10);
    }
    handleToggle() {
        if (this.isActive) {
            this.hideMenu();
        }
        else {
            this.showMenu();
        }
    }
    handleCheckItem(item) {
        const isCurrentlyChecked = this.checkedItems.includes(item.id);
        if (isCurrentlyChecked) {
            this.checkedItems = this.checkedItems.filter((id) => id !== item.id);
        }
        else {
            this.checkedItems = [...this.checkedItems, item.id];
        }
        const idx = this.listItems.findIndex(({ id }) => id === item.id);
        this.focusItem(idx);
        this.afChangeFilter.emit({
            filterName: this.afName,
            id: item.id,
            isChecked: !isCurrentlyChecked
        });
    }
    handleSubmit() {
        this.hideMenu();
        this.afSubmitFilter.emit({
            filterName: this.afName,
            listItems: this.listItems,
            checked: this.checkedItems
        });
    }
    handleReset() {
        this.checkedItems = [];
        this.afResetFilter.emit({
            filterName: this.afName
        });
    }
    render() {
        return (h(Host, { key: '629ed6c227116a5fa43e0e2e4c90da6f15310b46' }, h("div", { key: '60e8979ca12ea06f48dac9103fed77a25a895b64', id: `${this.afId}-identifier`, ref: (el) => (this.refs.root = el), class: {
                'digi-form-filter': true,
                'digi-form-filter--open': this.isActive
            } }, h("digi-button", { key: 'f91142adf06d5320b5bd18f7e057ba3db67982a4', id: `${this.afId}-toggle-button`, afInputRef: (el) => (this.refs.toggle = el), class: "digi-form-filter__toggle-button", onAfOnClick: () => this.handleToggle(), "af-aria-haspopup": "true", "af-variation": "secondary", "af-aria-label": this.afFilterButtonAriaLabel, "af-aria-labelledby": this.afFilterButtonAriaDescribedby, "af-aria-controls": `${this.afId}-dropdown-menu`, "af-aria-expanded": this.isActive, "af-autofocus": this.afAutofocus ? this.afAutofocus : null }, h("i", { key: '06b3942b320859323c70bef9a48b0170e62494b1', class: {
                'digi-form-filter__toggle-button-indicator': true,
                'digi-form-filter__toggle-button-indicator--active': this.checkedItems.length > 0
            } }), h("span", { key: '72654121dd476fde27a6dfc8dac7e0fa308da60a', class: "digi-form-filter__toggle-button-text" }, this.afFilterButtonText), h("digi-icon-chevron-down", { key: 'a1d0c0155b0c5017cc85315134130b41697a6d54', class: "digi-form-filter__toggle-icon", slot: "icon-secondary" })), h("div", { key: '930be23958d57a8ec6b40e027f9729cb3297bc6c', id: `${this.afId}-dropdown-menu`, ref: (el) => (this.refs.menu = el), class: {
                'digi-form-filter__dropdown': true,
                'digi-form-filter__dropdown--right': this.afAlignRight,
                'digi-form-filter__dropdown--hidden': !this.isActive
            } }, h("div", { key: 'be2ff919debc13ccae9b55443b6ede7b20584a62', class: "digi-form-filter__scroll" }, h("fieldset", { key: 'e8e95989e36cefe37dc8d9ea35f733b721ba0925' }, this.afName ? (h("legend", { class: "digi-form-filter__legend" }, this.afName)) : (h("legend", { class: "legend-hidden" }, this.afFilterButtonText)), h("ul", { key: 'ad8e66517cee5fe0c6ed26c016e23a00e62ee9ff', class: "digi-form-filter__list", "aria-label": this.afFilterButtonAriaLabel, id: `${this.afId}-filter-list` }, this.listItems.map((item) => {
            const isChecked = this.checkedItems.includes(item.id);
            const isTabbable = this.tabItems.includes(item.id);
            return (h("li", { class: "digi-form-filter__item", key: item.id }, h("digi-form-checkbox", { afInputRef: (ref) => (this.refs.filter = Object.assign(Object.assign({}, this.refs.filter), { [item.id]: ref })), afTabIndex: isTabbable ? 0 : -1, afLabel: item.label, afValue: item.id, afChecked: isChecked, onClick: (e) => {
                    e.preventDefault();
                    this.handleCheckItem(item);
                } })));
        })))), h("div", { key: '79448216684afafd5746362f923ca6cda0b3a136', class: "digi-form-filter__footer" }, h("digi-button", { key: '891b9ba1f286b1c9fc11c42855c41612fb3b84f4', class: "digi-form-filter__submit-button", "af-variation": "primary", "af-aria-label": this.afSubmitButtonTextAriaLabel, onClick: () => this.handleSubmit(), afInputRef: (ref) => (this.refs.submit = ref) }, this.afSubmitButtonText), !this.afHideResetButton && (h("digi-button", { key: '11fa710bab35b7709c8063f143da9af0da6daaef', "af-variation": "secondary", "af-aria-label": this.afResetButtonTextAriaLabel, onClick: () => this.handleReset(), class: "digi-form-filter__reset-button", afInputRef: (ref) => (this.refs.reset = ref) }, this.afResetButtonText))))), h("div", { key: '29f9d7299f89d564a616c302d9965e8431cbc3f8', ref: (ref) => (this.slotRef = ref), id: `${this.afId}-children`, style: { display: 'none' } }, h("slot", { key: 'a4b103b33602a14617884e95a28db8b958fcbbcd' }))));
    }
    static get is() { return "digi-form-filter"; }
    static get encapsulation() { return "scoped"; }
    static get originalStyleUrls() {
        return {
            "$": ["form-filter.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["form-filter.css"]
        };
    }
    static get properties() {
        return {
            "afId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Prefix for all id attributes inside the component. Example: 'my-cool-id' generates 'my-cool-id-filter-list', 'my-cool-id-dropdown-menu' and so on. Defaults to random string."
                        }],
                    "text": "Prefixet f\u00F6r alla komponentens olika interna 'id'-attribut p\u00E5 dropdowns, filterlistor etc. Ex. 'my-cool-id' genererar 'my-cool-id-filter-list', 'my-cool-id-dropdown-menu' och s\u00E5 vidare. Ges inget v\u00E4rde s\u00E5 genereras ett slumpm\u00E4ssigt."
                },
                "getter": false,
                "setter": false,
                "attribute": "af-id",
                "reflect": false,
                "defaultValue": "randomIdGenerator('digi-form-filter')"
            },
            "afFilterButtonText": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Set the filter button text"
                        }],
                    "text": "Texten i filterknappen"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-filter-button-text",
                "reflect": false
            },
            "afSubmitButtonText": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Set the submit button text"
                        }],
                    "text": "Texten i submitknappen"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-submit-button-text",
                "reflect": false
            },
            "afSubmitButtonTextAriaLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Set the submit button aria-label text"
                        }],
                    "text": "Sk\u00E4rml\u00E4sartext f\u00F6r submitknappen"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-submit-button-text-aria-label",
                "reflect": false
            },
            "afResetButtonText": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Set the reset button text"
                        }],
                    "text": "Texten i rensaknappen"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-reset-button-text",
                "reflect": false,
                "defaultValue": "_t.clear"
            },
            "afResetButtonTextAriaLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Set the reset button aria-label text"
                        }],
                    "text": "Sk\u00E4rml\u00E4sartext f\u00F6r resetknappen"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-reset-button-text-aria-label",
                "reflect": false
            },
            "afHideResetButton": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Hides the reset button when set to true"
                        }],
                    "text": "D\u00F6ljer rensaknappen n\u00E4r v\u00E4rdet s\u00E4tts till true"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-hide-reset-button",
                "reflect": false,
                "defaultValue": "false"
            },
            "afAlignRight": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Align dropdown from right to left"
                        }],
                    "text": "Justera dropdown fr\u00E5n h\u00F6ger till v\u00E4nster"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-align-right",
                "reflect": false
            },
            "afName": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Binding name of filterlist selected filters on submit. Also used by the legend element."
                        }],
                    "text": "Namnet p\u00E5 filterlistans valda filter vid submit. Anv\u00E4nds \u00E4ven av legendelementet inne i filterlistan."
                },
                "getter": false,
                "setter": false,
                "attribute": "af-name",
                "reflect": false
            },
            "afFilterButtonAriaLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Input aria-label attribute on filter button"
                        }],
                    "text": "S\u00E4tter attributet 'aria-label' p\u00E5 filterknappen"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-filter-button-aria-label",
                "reflect": false
            },
            "afFilterButtonAriaDescribedby": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Input aria-describedby attribute on filter button"
                        }],
                    "text": "S\u00E4tter attributet 'aria-describedby' p\u00E5 filterknappen"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-filter-button-aria-describedby",
                "reflect": false
            },
            "afAutofocus": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Input autofocus attribute"
                        }],
                    "text": "S\u00E4tter attributet 'autofocus'."
                },
                "getter": false,
                "setter": false,
                "attribute": "af-autofocus",
                "reflect": false
            },
            "afListItems": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string | FormFilterItem[]",
                    "resolved": "FormFilterItem[] | string",
                    "references": {
                        "FormFilterItem": {
                            "location": "import",
                            "path": "./form-filter.types",
                            "id": "src/components/_form/form-filter/form-filter.types.ts::FormFilterItem"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "List with option"
                        }],
                    "text": "Lista med val"
                },
                "getter": false,
                "setter": false,
                "attribute": "af-list-items",
                "reflect": false
            },
            "afCheckItems": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "FilterItemId[]",
                    "resolved": "string[]",
                    "references": {
                        "FilterItemId": {
                            "location": "import",
                            "path": "./form-filter.types",
                            "id": "src/components/_form/form-filter/form-filter.types.ts::FilterItemId"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "Defines which checkboxes are checked, expects the `id` of the filter"
                        }],
                    "text": "Definiera vilka kryssrutor som ska vara ikryssade, f\u00F6rv\u00E4ntar sig filtrets `id`"
                },
                "getter": false,
                "setter": false,
                "defaultValue": "[]"
            }
        };
    }
    static get states() {
        return {
            "listItems": {},
            "checkedItems": {},
            "tabItems": {},
            "isActive": {},
            "activeListItemIndex": {}
        };
    }
    static get events() {
        return [{
                "method": "afBlurFilter",
                "name": "afBlurFilter",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "When focus moves on to another element"
                        }],
                    "text": "N\u00E4r fokus g\u00E5r \u00F6ver till ett annat element"
                },
                "complexType": {
                    "original": "{ filterName?: string }",
                    "resolved": "{ filterName?: string; }",
                    "references": {}
                }
            }, {
                "method": "afSubmitFilter",
                "name": "afSubmitFilter",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "At filter submit"
                        }],
                    "text": "Vid uppdatering av filtret"
                },
                "complexType": {
                    "original": "FormFilterState & { filterName?: string }",
                    "resolved": "FormFilterState & { filterName?: string; }",
                    "references": {
                        "FormFilterState": {
                            "location": "import",
                            "path": "./form-filter.types",
                            "id": "src/components/_form/form-filter/form-filter.types.ts::FormFilterState"
                        }
                    }
                }
            }, {
                "method": "afCloseFilter",
                "name": "afCloseFilter",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "When the filter is closed without confirming the selected options"
                        }],
                    "text": "N\u00E4r filtret st\u00E4ngs utan att valda alternativ bekr\u00E4ftats"
                },
                "complexType": {
                    "original": "FormFilterState & { filterName?: string }",
                    "resolved": "FormFilterState & { filterName?: string; }",
                    "references": {
                        "FormFilterState": {
                            "location": "import",
                            "path": "./form-filter.types",
                            "id": "src/components/_form/form-filter/form-filter.types.ts::FormFilterState"
                        }
                    }
                }
            }, {
                "method": "afResetFilter",
                "name": "afResetFilter",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "At filter reset"
                        }],
                    "text": "Vid reset av filtret"
                },
                "complexType": {
                    "original": "{ filterName?: string }",
                    "resolved": "{ filterName?: string; }",
                    "references": {}
                }
            }, {
                "method": "afChangeFilter",
                "name": "afChangeFilter",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "en",
                            "text": "When a filter is changed"
                        }],
                    "text": "N\u00E4r ett filter \u00E4ndras"
                },
                "complexType": {
                    "original": "FilterChange & { filterName?: string }",
                    "resolved": "FilterChange & { filterName?: string; }",
                    "references": {
                        "FilterChange": {
                            "location": "import",
                            "path": "./form-filter.types",
                            "id": "src/components/_form/form-filter/form-filter.types.ts::FilterChange"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "hostElement"; }
    static get watchers() {
        return [{
                "propName": "afCheckItems",
                "methodName": "syncCheckItems"
            }, {
                "propName": "afListItems",
                "methodName": "handleListItems"
            }, {
                "propName": "listItems",
                "methodName": "setupAccessibility"
            }];
    }
    static get listeners() {
        return [{
                "name": "click",
                "method": "clickHandler",
                "target": "window",
                "capture": false,
                "passive": false
            }, {
                "name": "focusin",
                "method": "focusoutHandler",
                "target": "document",
                "capture": false,
                "passive": false
            }, {
                "name": "keydown",
                "method": "handleKey",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
