import { h, Host } from "@stencil/core";
import { booleanString, toBoolAttr } from "../../../helpers/Dom/template";
import { validateProp } from "../../../helpers/Validate/props";
import { createID } from "../../../utils/string.utils";
import { delay, has, throttle } from "../../../utils/utils";
import { FormAutocompleteClass, FormAutocompleteSizes, } from "./constants";
import { propsValueToArray } from "../../../utils/array.utils";
import { AttributeObserver } from "../../../helpers/Dom/attribute";
import { ariaAttributes } from "../../../helpers/Accessibility/attributes";
import { inheritAriaAttributes } from "../../../helpers/Accessibility/accessibility";
export class GovFormAutocomplete {
    constructor() {
        this.templateResolver = item => item[this.nameKey];
        /**
         * Value of input
         */
        this.value = '';
        /**
         * Input’s size.
         */
        this.size = 'm';
        /**
         * Main key name in the object
         */
        this.nameKey = 'name';
        /**
         * Set whether the input is required or not. Please note that this is necessary for accessible inputs when the user is required to fill them.
         * When using this property you need to also set “novalidate” attribute to your form element to prevent browser from displaying its own validation errors.
         */
        this.required = false;
        /**
         * Makes the input component disabled.
         * This prevents users from being able to interact with the select, and conveys its inactive state to assistive technologies.
         */
        this.disabled = false;
        /**
         * Minimum length (number of characters) of value
         */
        this.minlength = 3;
        /**
         * Input throttle in milliseconds
         */
        this.throttleTime = 200;
        /**
         * Custom message for when there is a blank sheet
         */
        this.messageEmpty = 'Nebyly nalezeny žádné výsledky';
        this.processing = false;
        this.arrowCounter = -1;
        this.list = [];
        this.inheritedAttributes = {};
        this.listBoxId = createID('GovListBox');
    }
    validateSize(newValue) {
        validateProp(FormAutocompleteSizes, newValue, FormAutocompleteClass.root);
    }
    watchOptions(newValue) {
        this.setOptions(propsValueToArray(newValue)).catch();
    }
    onArrowUp() {
        if (this.arrowCounter > 0) {
            this.arrowCounter = this.arrowCounter - 1;
            this.moveToView().finally();
        }
    }
    onArrowDown() {
        if (this.arrowCounter < this.list.length - 1) {
            this.arrowCounter = this.arrowCounter + 1;
            this.moveToView().finally();
        }
    }
    async moveToView() {
        await delay(200);
        const heightOfList = this.listRef.offsetHeight;
        const selected = this.listRef.querySelector('li[aria-selected="true"]');
        if (selected && heightOfList) {
            const offsetTop = selected.offsetTop;
            this.listRef.scrollTo({ top: offsetTop, behavior: 'smooth' });
        }
    }
    doSearch() {
        if (Number.isInteger(this.minlength) && this.isValueAccepted === false && this.minlength) {
            this.list = [];
            this.arrowCounter = -1;
            this.processing = false;
            return;
        }
        if (this.searchCallback) {
            this.processing = true;
            this.searchCallback(this.value)
                .then(response => (this.list = response))
                .catch(() => (this.list = []))
                .finally(() => {
                this.arrowCounter = -1;
                this.processing = false;
            });
        }
    }
    clearList() {
        const areOptions = propsValueToArray(this.options);
        if (areOptions.length === 0) {
            this.list = [];
        }
    }
    get isValueAccepted() {
        if (typeof this.value === 'string') {
            return this.value.length >= this.minlength;
        }
        else {
            return false;
        }
    }
    componentDidLoad() {
        this.attributeObserver = new AttributeObserver(this.host, (attributeName, newValue) => {
            this.onAriaAttributeChange(attributeName, newValue);
        });
        this.attributeObserver.startObserving(ariaAttributes);
    }
    componentWillLoad() {
        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 });
    }
    render() {
        return (h(Host, { key: 'e702056161cca6e00f2e7753b1b07dfdeee78438', class: FormAutocompleteClass.root, size: this.size }, h("gov-form-input", Object.assign({ key: '6ba7c775e0a67486f2c10a1d972860a986e44a3d', placeholder: this.placeholder, name: this.name, disabled: this.disabled, readonly: this.readonly, autocomplete: false, size: this.size, required: this.required, invalid: this.invalid, success: this.success, role: 'searchbox', value: this.value, minlength: this.minlength, maxlength: this.maxlength, "on-gov-input": throttle(this.onInputHandler.bind(this), this.throttleTime), "on-gov-keyup": this.onKeyUpHandler.bind(this), "on-gov-keydown": this.onKeyDownHandler.bind(this), "on-gov-focus": this.onFocusHandler.bind(this), "on-gov-blur": this.onBlurHandler.bind(this) }, this.inheritedAttributes, { "aria-autocomplete": 'list', "aria-owns": [this.listBoxId, this.inheritedAttributes['aria-owns']].join(' '), "aria-expanded": booleanString(this.list.length && this.focused ? true : false), ref: el => (this.inputRef = el) }), h("slot", { key: '1f36342107c398db15ec13d8d1ecd8306dc62505', name: "validation-icon" }), h("slot", { key: '26bc01a6995f090e605677dbfbe6260c79f70d00', name: "icon-end" })), h("ul", { key: 'c42a658906dd0815e3c94aa451ee7a4fa7091bd3', class: FormAutocompleteClass.list, role: 'listbox', "aria-hidden": toBoolAttr(!this.focused), hidden: !this.focused, id: this.listBoxId, ref: el => (this.listRef = el) }, this.focused && this.list.length === 0 && this.processing === false && this.isValueAccepted && this.messageEmpty ? (h("li", { class: FormAutocompleteClass.empty }, this.messageEmpty)) : null, this.focused && this.processing === true && this.isValueAccepted ? (h("li", { class: FormAutocompleteClass.loading }, h("gov-skeleton", { size: "m" }))) : null, this.focused ? this.list.map((item, index) => {
            const isSelected = this.arrowCounter === index;
            return (h("li", { class: FormAutocompleteClass.item, innerHTML: this.templateResolver(item, isSelected), role: 'option', "aria-posinset": index, tabindex: isSelected ? 0 : -1, "aria-setsize": this.list.length, onTouchStart: (e) => this.onSelectHandler(e, index), onMouseDown: (e) => this.onSelectHandler(e, index), "aria-selected": toBoolAttr(isSelected) }, h("slot", { name: "list-item-left" }), h("slot", { name: "list-item-right" })));
        }) : null)));
    }
    onFocusHandler(e) {
        this.focused = true;
        this.arrowCounter = -1;
        if (this.isValueAccepted && this.searchCallback) {
            this.doSearch();
        }
        e.stopPropagation();
        this.govFocus.emit({
            originalEvent: e,
            component: FormAutocompleteClass.root,
            value: this.value,
            selected: null,
        });
    }
    onBlurHandler(e) {
        this.focused = false;
        this.clearList();
        this.arrowCounter = -1;
        e.stopPropagation();
        this.govBlur.emit({
            originalEvent: e,
            component: FormAutocompleteClass.root,
            value: this.value,
            selected: null,
        });
    }
    onInputHandler(e) {
        this.value = e.target.value;
        e.stopPropagation();
        this.govInput.emit({
            originalEvent: e,
            component: FormAutocompleteClass.root,
            value: this.value,
            selected: null,
        });
        this.doSearch();
    }
    onSelectHandler(e, index = -1) {
        let selected = null;
        if (index > -1) {
            selected = this.list[index];
        }
        else if (has(this.arrowCounter, this.list)) {
            selected = this.list[this.arrowCounter];
        }
        if (selected) {
            this.govSelect.emit({
                component: FormAutocompleteClass.root,
                value: this.value,
                selected: selected,
                originalEvent: e,
            });
            this.clearList();
            if (has(this.nameKey, selected) && typeof selected[this.nameKey] === 'string') {
                this.value = selected[this.nameKey];
            }
        }
    }
    onKeyUpHandler(e) {
        const event = e.detail.originalEvent;
        e.stopPropagation();
        event.stopPropagation();
        if (event.keyCode === 38)
            this.onArrowUp();
        else if (event.keyCode === 40)
            this.onArrowDown();
        else if (event.keyCode === 13) {
            e.preventDefault();
            event.preventDefault();
            this.onSelectHandler(e);
        }
    }
    onKeyDownHandler(e) {
        const event = e.detail.originalEvent;
        e.stopPropagation();
        event.stopPropagation();
        if (event.keyCode === 13) {
            e.preventDefault();
            event.preventDefault();
        }
    }
    /**
     * Focus main input element
     */
    async setFocus(options) {
        return this.inputRef.focus(options);
    }
    /**
     * Blur main input element
     */
    async setBlur() {
        return this.inputRef.blur();
    }
    /**
     * Set options for list
     */
    async setOptions(options) {
        this.list = Array.isArray(options) ? options : [];
        this.arrowCounter = -1;
    }
    /**
     * Clears whisperer value
     */
    async clearValue() {
        this.value = '';
        this.inputRef.value = '';
        await this.inputRef.clearValue();
    }
    /**
     * Clears whisperer value
     */
    async setProcessing(status) {
        this.processing = status;
    }
    /**
     * Set a custom asynchronous function for the whisperer
     */
    async setSearchCallback(callback) {
        this.searchCallback = callback;
    }
    /**
     * Setting a custom whisper result template
     * @param callback
     */
    async setTemplateResolver(callback) {
        this.templateResolver = callback;
    }
    static get is() { return "gov-form-autocomplete"; }
    static get properties() {
        return {
            "value": {
                "type": "string",
                "attribute": "value",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Value of input"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "''"
            },
            "options": {
                "type": "string",
                "attribute": "options",
                "mutable": true,
                "complexType": {
                    "original": "string | GovFormAutocompleteItem[]",
                    "resolved": "GovFormAutocompleteItem[] | string",
                    "references": {
                        "GovFormAutocompleteItem": {
                            "location": "import",
                            "path": "./gov-form-autocomplete.types",
                            "id": "../../../packages/core/src/components/gov-form/autocomplete/gov-form-autocomplete.types.ts::GovFormAutocompleteItem"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Options of autocomplete"
                },
                "getter": false,
                "setter": false,
                "reflect": true
            },
            "identifier": {
                "type": "string",
                "attribute": "identifier",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Custom input identifier."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "success": {
                "type": "boolean",
                "attribute": "success",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Indicates the entered value of child form element does conform to the format expected by the application."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "size": {
                "type": "string",
                "attribute": "size",
                "mutable": false,
                "complexType": {
                    "original": "SizesType",
                    "resolved": "\"l\" | \"m\" | \"s\" | \"xl\" | \"xs\"",
                    "references": {
                        "SizesType": {
                            "location": "import",
                            "path": "./constants",
                            "id": "../../../packages/core/src/components/gov-form/autocomplete/constants.ts::SizesType"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Input\u2019s size."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'m'"
            },
            "nameKey": {
                "type": "string",
                "attribute": "name-key",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Main key name in the object"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'name'"
            },
            "name": {
                "type": "string",
                "attribute": "name",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Name of the input."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "required": {
                "type": "boolean",
                "attribute": "required",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set whether the input is required or not. Please note that this is necessary for accessible inputs when the user is required to fill them.\r\nWhen using this property you need to also set \u201Cnovalidate\u201D attribute to your form element to prevent browser from displaying its own validation errors."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "disabled": {
                "type": "boolean",
                "attribute": "disabled",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Makes the input component disabled.\r\nThis prevents users from being able to interact with the select, and conveys its inactive state to assistive technologies."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            },
            "placeholder": {
                "type": "string",
                "attribute": "placeholder",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Text that appears in the form control when it has no value set"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "readonly": {
                "type": "boolean",
                "attribute": "readonly",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The value is not editable"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "invalid": {
                "type": "boolean",
                "attribute": "invalid",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Indicates the entered value does not conform to the format expected by the application."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "minlength": {
                "type": "number",
                "attribute": "minlength",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Minimum length (number of characters) of value"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "3"
            },
            "maxlength": {
                "type": "number",
                "attribute": "maxlength",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Maximum length (number of characters) of value"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "throttleTime": {
                "type": "number",
                "attribute": "throttle-time",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Input throttle in milliseconds"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "200"
            },
            "messageEmpty": {
                "type": "string",
                "attribute": "message-empty",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Custom message for when there is a blank sheet"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'Nebyly nalezeny \u017E\u00E1dn\u00E9 v\u00FDsledky'"
            }
        };
    }
    static get states() {
        return {
            "focused": {},
            "processing": {},
            "arrowCounter": {},
            "list": {},
            "inheritedAttributes": {}
        };
    }
    static get events() {
        return [{
                "method": "govFocus",
                "name": "gov-focus",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input has focus."
                },
                "complexType": {
                    "original": "FormAutocompleteEvent",
                    "resolved": "FormAutocompleteEvent",
                    "references": {
                        "FormAutocompleteEvent": {
                            "location": "import",
                            "path": "./gov-form-autocomplete.types",
                            "id": "../../../packages/core/src/components/gov-form/autocomplete/gov-form-autocomplete.types.ts::FormAutocompleteEvent"
                        }
                    }
                }
            }, {
                "method": "govBlur",
                "name": "gov-blur",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input loses focus."
                },
                "complexType": {
                    "original": "FormAutocompleteEvent",
                    "resolved": "FormAutocompleteEvent",
                    "references": {
                        "FormAutocompleteEvent": {
                            "location": "import",
                            "path": "./gov-form-autocomplete.types",
                            "id": "../../../packages/core/src/components/gov-form/autocomplete/gov-form-autocomplete.types.ts::FormAutocompleteEvent"
                        }
                    }
                }
            }, {
                "method": "govInput",
                "name": "gov-input",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input change value."
                },
                "complexType": {
                    "original": "FormAutocompleteEvent",
                    "resolved": "FormAutocompleteEvent",
                    "references": {
                        "FormAutocompleteEvent": {
                            "location": "import",
                            "path": "./gov-form-autocomplete.types",
                            "id": "../../../packages/core/src/components/gov-form/autocomplete/gov-form-autocomplete.types.ts::FormAutocompleteEvent"
                        }
                    }
                }
            }, {
                "method": "govSelect",
                "name": "gov-select",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input change value."
                },
                "complexType": {
                    "original": "FormAutocompleteEvent",
                    "resolved": "FormAutocompleteEvent",
                    "references": {
                        "FormAutocompleteEvent": {
                            "location": "import",
                            "path": "./gov-form-autocomplete.types",
                            "id": "../../../packages/core/src/components/gov-form/autocomplete/gov-form-autocomplete.types.ts::FormAutocompleteEvent"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "setFocus": {
                "complexType": {
                    "signature": "(options?: FocusOptions) => Promise<void>",
                    "parameters": [{
                            "name": "options",
                            "type": "FocusOptions",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "FocusOptions": {
                            "location": "global",
                            "id": "global::FocusOptions"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Focus main input element",
                    "tags": []
                }
            },
            "setBlur": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Blur main input element",
                    "tags": []
                }
            },
            "setOptions": {
                "complexType": {
                    "signature": "(options: GovFormAutocompleteItem[]) => Promise<void>",
                    "parameters": [{
                            "name": "options",
                            "type": "GovFormAutocompleteItem[]",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "GovFormAutocompleteItem": {
                            "location": "import",
                            "path": "./gov-form-autocomplete.types",
                            "id": "../../../packages/core/src/components/gov-form/autocomplete/gov-form-autocomplete.types.ts::GovFormAutocompleteItem"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Set options for list",
                    "tags": []
                }
            },
            "clearValue": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Clears whisperer value",
                    "tags": []
                }
            },
            "setProcessing": {
                "complexType": {
                    "signature": "(status: boolean) => Promise<void>",
                    "parameters": [{
                            "name": "status",
                            "type": "boolean",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Clears whisperer value",
                    "tags": []
                }
            },
            "setSearchCallback": {
                "complexType": {
                    "signature": "(callback: (value: string) => Promise<any>) => Promise<void>",
                    "parameters": [{
                            "name": "callback",
                            "type": "(value: string) => Promise<any>",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Set a custom asynchronous function for the whisperer",
                    "tags": []
                }
            },
            "setTemplateResolver": {
                "complexType": {
                    "signature": "(callback: (item: GovFormAutocompleteItem) => string) => Promise<void>",
                    "parameters": [{
                            "name": "callback",
                            "type": "(item: GovFormAutocompleteItem) => string",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "GovFormAutocompleteItem": {
                            "location": "import",
                            "path": "./gov-form-autocomplete.types",
                            "id": "../../../packages/core/src/components/gov-form/autocomplete/gov-form-autocomplete.types.ts::GovFormAutocompleteItem"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Setting a custom whisper result template",
                    "tags": [{
                            "name": "param",
                            "text": "callback"
                        }]
                }
            }
        };
    }
    static get elementRef() { return "host"; }
    static get watchers() {
        return [{
                "propName": "size",
                "methodName": "validateSize"
            }, {
                "propName": "options",
                "methodName": "watchOptions"
            }];
    }
}
//# sourceMappingURL=gov-form-autocomplete.js.map
