import { h, Host } from "@stencil/core";
import { cls, getId } from "../../utils/helpers";
import { autoUpdate, computePosition, flip, offset, shift, size } from "@floating-ui/dom";
export class XSelect {
    constructor() {
        /**
         * Element ID for internal reference
         */
        this.inputId = getId('select');
        this.label = undefined;
        this.name = undefined;
        this.placeholder = undefined;
        this.info = undefined;
        this.validate = undefined;
        this.required = undefined;
        this.loading = undefined;
        this.autofocus = undefined;
        this.multiple = undefined;
        this.size = undefined;
        this.autocomplete = 'off';
        this.value = '';
        this.isValid = true;
        this.isFocused = undefined;
        this.isLoading = undefined;
        this.isDisabled = undefined;
        this.isFiltered = undefined;
        this.computedValue = [];
        this.computedText = [];
        this.filteredCount = undefined;
        this.filteredTotal = undefined;
    }
    /**
     * This is called when the component updated the value attribute
     */
    valueChanged(newValue) {
        this.selectOptionByValue(newValue);
    }
    /**
     * Validate the input and get the validation result
    */
    async checkValidity() {
        this.onValidate();
        return this.isValid;
    }
    /**
     * on child option element is triggered the selection
     */
    onOptionSelected(ev) {
        if (this.multiple) {
            this.computedValue.includes(ev.detail.value) ?
                this.computedValue.splice(this.computedValue.indexOf(ev.detail.value), 1) :
                this.computedValue.push(ev.detail.value);
            this.computedText.includes(ev.detail.text) ?
                this.computedText.splice(this.computedText.indexOf(ev.detail.text), 1) :
                this.computedText.push(ev.detail.text);
        }
        else {
            this.computedValue = this.computedValue.includes(ev.detail.value) ? [] : [ev.detail.value];
            this.computedText = this.computedText.includes(ev.detail.text) ? [] : [ev.detail.text];
        }
        this.el.querySelectorAll('x-select-option').forEach(async (el) => {
            el.selected = this.computedValue.includes(await el.getValue());
        });
        const input = this.el.querySelector('.select-input');
        input.value = '';
        input.dispatchEvent(new InputEvent('input'));
        this.setFormValue();
    }
    /**
     * Set the actual value to internals
     */
    setFormValue() {
        var _a;
        if (this.multiple) {
            if (!((_a = this.name) === null || _a === void 0 ? void 0 : _a.length)) {
                setTimeout(() => {
                    Array.from(new Set(this.computedValue));
                    this.el.dispatchEvent(new InputEvent('input'));
                }, 50);
                return;
            }
            const data = new FormData();
            this.computedValue.forEach((value) => {
                data.append(this.name, value);
            });
            this.internals.setFormValue(data);
        }
        else {
            this.value = this.computedValue[0];
            this.internals.setFormValue(this.computedValue[0]);
        }
        this.el.dispatchEvent(new InputEvent('input'));
    }
    /**
     * This is called on component did load
     */
    componentDidLoad() {
        this.selectOptionByValue(this.value);
    }
    /**
     * This is called on component did update the element space
     */
    computePositionCustomSelect() {
        if (this.isAdvancedSelect()) {
            const container = this.el.querySelector('.select-items');
            computePosition(this.el, container, {
                placement: 'bottom-start',
                middleware: [size({
                        apply({ availableWidth, availableHeight, elements }) {
                            const items = elements;
                            container.style.maxWidth = `${Math.max(200, availableWidth > items.reference.offsetWidth ? items.reference.offsetWidth : availableWidth)}px`;
                            container.style.maxHeight = `${Math.max(200, availableHeight - 4)}px`;
                        }
                    }), flip(), shift(), offset(4)],
            }).then(({ x, y }) => {
                container.style.left = `${x}px`;
                container.style.top = `${y}px`;
            });
        }
    }
    /**
     * This is called when the 'disabled' attribute of the element or or an ancestor <fieldset> is updated
     *
     * @param disabled
     */
    formDisabledCallback(disabled) {
        this.isDisabled = disabled;
    }
    /**
     * This is called when the parent/owner form is reset
     */
    formResetCallback() {
        this.isValid = true;
        this.internals.setFormValue('');
    }
    /**
     * Set element value by event
     *
     * @param event
     */
    onInput(event) {
        this.value = event.target.value;
        this.internals && this.internals.setFormValue(event.target.value);
        this.el.dispatchEvent(new InputEvent('input'));
        setTimeout(() => this.onValidate(), 50);
    }
    /**
     * This called on input field is unfocused
     */
    onBlurInput() {
        setTimeout(() => {
            this.isFocused = false;
            this.onValidate();
            this.cleanup();
        }, 20);
    }
    /**
     * This called on input field is focused
     */
    onFocusInput() {
        this.isFocused = true;
        if (this.isAdvancedSelect()) {
            this.cleanup = autoUpdate(this.el, this.el.querySelector('.select-items'), this.computePositionCustomSelect.bind(this));
        }
    }
    /**
     * This called on search input have results
     */
    onFilterInput(ev) {
        this.isFiltered = ev.target.value.length > 0;
        setTimeout(() => {
            this.filteredTotal = this.el.querySelectorAll('x-select-option').length;
            this.filteredCount = this.el.querySelectorAll('x-select-option[matched]').length;
        }, 50);
    }
    /**
     * Validate the field input
     *
     * @returns
     */
    onValidate() {
        if (!this.validate) {
            return;
        }
        const selectors = ["input", "select", "textarea"];
        let input = null;
        selectors.forEach((selector) => {
            if (input === null) {
                input = this.el.querySelector(selector);
            }
        });
        this.isValid = (input === null || input === void 0 ? void 0 : input.validity) ? input.validity.valid : true;
        this.onValidateInputEvent.emit(input);
    }
    /**
     * Return validation of showing the input label
     *
     * @returns
     */
    showLabel() {
        var _a;
        return (this.label && this.placeholder) || (this.label && (((_a = this.value.toString()) !== null && _a !== void 0 ? _a : '').length > 0 || this.computedValue.length > 0 || this.isFocused || (this.multiple && !this.isAdvancedSelect())));
    }
    /**
     * Compute the placeholder value
     *
     * @returns
     */
    placeholderValue() {
        if (this.label) {
            if (this.placeholder) {
                return this.placeholder;
            }
            else if (!this.showLabel() || (this.multiple && this.isAdvancedSelect())) {
                return this.label;
            }
        }
        return this.placeholder;
    }
    /**
     * Focus the select input
     */
    focusSelect() {
        const event = new MouseEvent("mousedown", {
            bubbles: true,
            cancelable: true,
            view: window,
        });
        if (this.isAdvancedSelect()) {
            this.isFocused = !this.isFocused;
            setTimeout(() => {
                this.el.querySelector('.select-input').focus();
            }, 20);
        }
        else {
            this.el.querySelector("select").dispatchEvent(event);
        }
    }
    /**
     * Select the option element by value
     */
    selectOptionByValue(value) {
        const select = this.el.querySelector("select");
        select && select.querySelectorAll("option").forEach((option) => {
            if (Array.isArray(value) ? value.includes(option.value) : option.value === value.toString()) {
                option.selected = true;
            }
        });
        if (this.isAdvancedSelect) {
            const selected = this.el.querySelectorAll('x-select-option');
            this.computedValue = [];
            this.computedText = [];
            selected && selected.forEach(async (el) => {
                if (Array.isArray(value) ? value.includes(await el.getValue()) : value == await el.getValue()) {
                    el.selected = true;
                }
                if (el.selected) {
                    this.computedValue.push(await el.getValue());
                    this.computedText.push(await el.getElementOptionText());
                }
            });
        }
    }
    /**
     * Check if the select use not native options
     */
    isAdvancedSelect() {
        return this.el.querySelector("x-select-option") !== null;
    }
    /**
     * Render component
     */
    render() {
        return h(Host, { key: 'e4adde7fedfc23beede6492d0356883e6796e7e8', "data-for": this.name }, h("div", { key: '9a9d121a16075a20a2a73539c89810b09ada13de', class: cls("input-container", {
                "focus": this.isFocused,
                "loading": this.loading || this.isLoading,
                "disabled": this.isDisabled,
                "invalid": !this.isValid,
                "required": this.required,
                "multiple": this.multiple,
                "advanced": this.isAdvancedSelect(),
            }) }, h("div", { key: '2d7e94b3cb8e8c5b4f0ee788768fbe2bbed62c5d', class: "indicator" }, h("slot", { key: '3be1c8b4000bed8d36c48c1bd4921bf5de543646', name: "indicator" })), h("div", { key: 'd897a477b0bd05cc4edd369fa23a8e27329f373f', class: "separator" }), h("div", { key: 'bbe21a99ffda042f5331c85e5d4b83080d5ff5f7', class: "wrap" }, this.showLabel() && h("label", { key: '51efa97e3ea85e62b9584b1e021077ce98b73ec2', htmlFor: this.inputId }, this.label), this.isAdvancedSelect() ?
            h("div", null, h("input", { id: this.inputId, onFocus: () => this.focusSelect(), style: { width: '0.1px', flex: 'none' }, value: this.computedText.join(', '), required: this.required, disabled: this.isDisabled || this.loading || this.isLoading }), (!this.isFocused || this.multiple) && h("p", { style: { width: this.isFocused ? 'max-content' : '100%' }, onClick: () => this.focusSelect() }, this.computedText.join(', ')), h("input", { tabindex: "-1", id: this.inputId, style: { display: this.isFocused || this.computedValue.length < 1 ? 'block' : 'none' }, class: "select-input", type: "text", autoFocus: this.autofocus, placeholder: this.placeholderValue(), onInput: (ev) => this.onFilterInput(ev), onBlur: () => this.onBlurInput(), onFocus: () => this.onFocusInput() }))
            : h("select", { id: this.inputId, required: this.required, disabled: this.isDisabled || this.loading || this.isLoading, autoComplete: this.autocomplete, autoFocus: this.autofocus, multiple: this.multiple, size: this.size, onInput: (e) => this.onInput(e), onBlur: () => this.onBlurInput(), onFocus: () => this.onFocusInput() }, this.placeholder && h("option", { value: "", selected: true, disabled: true }, this.placeholder), h("slot", null))), h("div", { key: 'd0a7c879debad58c3e350aadd56e6b7d8e981547', class: "field-float-components" }, this.loading && h("div", { key: '534094e9b2b2ad64ddb7820fb78941c139cfbd84', class: "loading-indicator" }), h("div", { key: '12041f1e744096fb0b5e57ee12c613562767a2c9', class: "buttons" }, !(this.multiple && !this.isAdvancedSelect()) && h("x-button", { key: '19b1a84c9de67725a078bd19a974a159fb5fab62', tabindex: "-1", icon: "dropdown", onClick: () => this.focusSelect() }), h("slot", { key: '1acbfb9ab721641f083fe93b021e863cbc1f0f65', name: "buttons" })), this.info && h("div", { key: '1c634f17fb8f546c569756bc6249f80be7134d64', class: "info" }, h("x-tooltip", { key: '3f9376051d1a20b8dd5ea4a61f87c81a94de11b3', content: this.info }, h("x-icon", { key: '58dac64addc054807dd571ebfcfaed7093d88a46', name: "info" }))))), this.isAdvancedSelect() && h("div", { key: '44f84320e508eccc2d7ccd3655531d023f60ddf7', class: cls('select-items', {
                'focused': this.isFocused,
                'filtered': this.isFiltered,
            }) }, h("slot", { key: '71dd15236995b58880c3b53c2a8cd8e6391521e0' }), this.isFiltered && h("div", { key: '2bb4b57fcdaa9c7f79a84badab6c63f09a5b19bc', class: "select-results" }, h("span", { key: '40f92da651b8b0c71681d42acb5fb95e3fd1f390' }, "Mostrando ", h("strong", { key: '89860ca9f5aca113866d012527fd6cfca1464e3d' }, this.filteredCount), " recomendacion(es) de ", h("strong", { key: '8f269af64366d3352520696d6a79f10e49e2a675' }, this.filteredTotal)))));
    }
    static get is() { return "x-select"; }
    static get formAssociated() { return true; }
    static get originalStyleUrls() {
        return {
            "$": ["./style.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["style.css"]
        };
    }
    static get properties() {
        return {
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input label text"
                },
                "attribute": "label",
                "reflect": false
            },
            "name": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input name for forms keys"
                },
                "attribute": "name",
                "reflect": false
            },
            "placeholder": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input placeholder text"
                },
                "attribute": "placeholder",
                "reflect": false
            },
            "info": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input information block"
                },
                "attribute": "info",
                "reflect": false
            },
            "validate": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element enable internal validation"
                },
                "attribute": "validate",
                "reflect": false
            },
            "required": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element input required for forms validations"
                },
                "attribute": "required",
                "reflect": false
            },
            "loading": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element show loading and block for edit"
                },
                "attribute": "loading",
                "reflect": false
            },
            "autofocus": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element autofocus on render"
                },
                "attribute": "autofocus",
                "reflect": false
            },
            "multiple": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element multiple selection"
                },
                "attribute": "multiple",
                "reflect": false
            },
            "size": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element rows size on multiple selection"
                },
                "attribute": "size",
                "reflect": false
            },
            "autocomplete": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "InputAutocompleteTypes",
                    "resolved": "\"name\" | \"url\" | \"on\" | \"off\" | \"email\" | \"tel\" | \"honorific-prefix\" | \"given-name\" | \"additional-name\" | \"family-name\" | \"honorific-suffix\" | \"nickname\" | \"username\" | \"new-password\" | \"current-password\" | \"one-time-code\" | \"organization-title\" | \"organization\" | \"street-address\" | \"address-line1\" | \"address-line2\" | \"address-line3\" | \"address-level4\" | \"address-level3\" | \"address-level2\" | \"address-level1\" | \"country\" | \"country-name\" | \"postal-code\" | \"cc-name\" | \"cc-given-name\" | \"cc-additional-name\" | \"cc-family-name\" | \"cc-number\" | \"cc-exp\" | \"cc-exp-month\" | \"cc-exp-year\" | \"cc-csc\" | \"cc-type\" | \"transaction-currency\" | \"transaction-amount\" | \"language\" | \"bday\" | \"bday-day\" | \"bday-month\" | \"bday-year\" | \"sex\" | \"tel-country-code\" | \"tel-national\" | \"tel-area-code\" | \"tel-local\" | \"tel-extension\" | \"impp\" | \"photo\"",
                    "references": {
                        "InputAutocompleteTypes": {
                            "location": "import",
                            "path": "../x-input/component",
                            "id": "src/components/x-input/component.tsx::InputAutocompleteTypes"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Element input value of the control can be automatically completed by the browser"
                },
                "attribute": "autocomplete",
                "reflect": false,
                "defaultValue": "'off'"
            },
            "value": {
                "type": "any",
                "mutable": true,
                "complexType": {
                    "original": "string | string[] | number | null",
                    "resolved": "number | string | string[]",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Element input value"
                },
                "attribute": "value",
                "reflect": false,
                "defaultValue": "''"
            }
        };
    }
    static get states() {
        return {
            "isValid": {},
            "isFocused": {},
            "isLoading": {},
            "isDisabled": {},
            "isFiltered": {},
            "computedValue": {},
            "computedText": {},
            "filteredCount": {},
            "filteredTotal": {}
        };
    }
    static get events() {
        return [{
                "method": "onValidateInputEvent",
                "name": "validated",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "On validate input event"
                },
                "complexType": {
                    "original": "HTMLObjectElement",
                    "resolved": "HTMLObjectElement",
                    "references": {
                        "HTMLObjectElement": {
                            "location": "global",
                            "id": "global::HTMLObjectElement"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "checkValidity": {
                "complexType": {
                    "signature": "() => Promise<boolean>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<boolean>"
                },
                "docs": {
                    "text": "Validate the input and get the validation result",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "value",
                "methodName": "valueChanged"
            }];
    }
    static get listeners() {
        return [{
                "name": "option-selected",
                "method": "onOptionSelected",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
    static get attachInternalsMemberName() { return "internals"; }
}
