import { Host, h } from "@stencil/core";
import { isSpecTest, messageId, exposeTypeProperty } from "../../utils/form";
import { danger, enlarge } from "@pine-ds/icons/icons";
/**
 * @slot action - Content to be displayed in the label area, typically for help icons or links
 */
export class PdsSelect {
    constructor() {
        this._type = 'select-one';
        /**
         * Indicates whether or not the select field is disabled.
         * @defaultValue false
         */
        this.disabled = false;
        /**
         * Indicates whether multiple options can be selected.
         * @defaultValue false
         */
        this.multiple = false;
        /**
         * Indicates whether or not the select field is required.
         * @defaultValue false
         */
        this.required = false;
        /**
         * Emits an event on input change.
        */
        this.onSelectUpdate = (e) => {
            const target = e.target;
            const values = Array.from(target.options)
                .filter((option) => (option.selected))
                .map((option) => (option.value));
            if (values.length === 1 && !this.multiple) {
                this.value = values[0];
            }
            else {
                this.value = values;
            }
            this.pdsSelectChange.emit(e);
        };
        this.onBlur = (ev) => {
            this.pdsBlur.emit(ev);
        };
        this.onFocus = (ev) => {
            this.pdsFocus.emit(ev);
        };
        this.onKeyDown = (ev) => {
            this.pdsKeyDown.emit(ev);
        };
        /**
         * Handles the change event for the slot element.
         * This method is triggered when the slot content changes.
         * It updates the inner HTML of the select element by cloning and appending
         * the assigned <option> elements from the slot.
         */
        this.handleSlotChange = () => {
            const slot = this.slotContainer.querySelector('slot');
            this.selectEl.innerHTML = '';
            const assignedElements = slot.assignedElements({ flatten: true });
            assignedElements.forEach((item) => {
                if (['OPTION', 'OPTGROUP'].includes(item.tagName)) {
                    const clonedItem = item.cloneNode(true);
                    if (clonedItem.tagName === 'OPTION' && clonedItem.value === this.value) {
                        clonedItem.selected = true;
                    }
                    this.selectEl.appendChild(clonedItem);
                }
            });
            this.updateSelectedOption();
        };
    }
    /**
     * Handles the change in the value of the select component.
     * This method is called whenever the value of the select component changes.
     * It updates the selected option accordingly.
     */
    valueChanged() {
        this.updateSelectedOption();
        this.updateFormValue();
    }
    /**
     * Updates the type property when multiple changes to match native select behavior.
     */
    multipleChanged() {
        this.updateType();
    }
    updateType() {
        this._type = this.multiple ? 'select-multiple' : 'select-one';
    }
    connectedCallback() {
        // Initialize ElementInternals for form association (only once per element instance)
        if (this.el.attachInternals && !this.internals) {
            this.internals = this.el.attachInternals();
        }
        // Expose type property on the element instance to match native form element behavior
        exposeTypeProperty(this.el, () => this._type);
    }
    componentWillLoad() {
        // Set initial type based on multiple prop
        this.updateType();
        this.updateSelectedOption();
    }
    componentDidLoad() {
        // Set initial form value
        this.updateFormValue();
    }
    /**
     * Updates the selected option in the select element based on the current value.
     *
     * This method iterates through all the options of the select element and sets the
     * 'selected' attribute on the option that matches the current value. If an option
     * does not match the current value, the 'selected' attribute is removed.
     *
     * @private
     * @returns {void}
     */
    updateSelectedOption() {
        if (this.selectEl) {
            const options = this.selectEl.options;
            // Update the selected attribute for all options.
            Array.from(options).map((option) => {
                if (Array.isArray(this.value)) {
                    option.selected = this.value.includes(option.value);
                }
                else {
                    option.selected = this.value === option.value;
                }
            });
        }
        ;
    }
    getHelperMessage() {
        return this.helperMessage && (h("p", { class: "pds-select__helper-message", id: messageId(this.componentId, 'helper') }, this.helperMessage));
    }
    getErrorMessage() {
        return this.errorMessage && (h("p", { class: "pds-select__error-message", id: messageId(this.componentId, 'error'), "aria-live": "assertive" }, h("pds-icon", { icon: danger, size: "small" }), this.errorMessage));
    }
    renderMessages() {
        if (!this.helperMessage && !this.errorMessage)
            return null;
        return (h("div", { class: "pds-select__message" }, this.getHelperMessage(), this.getErrorMessage()));
    }
    classNames() {
        const classNames = [];
        if (this.invalid) {
            classNames.push('is-invalid');
        }
        if (this.disabled) {
            classNames.push('is-disabled');
        }
        return classNames.join('  ');
    }
    renderAction() {
        const hasAction = this.el.querySelector('[slot="action"]') !== null;
        if (hasAction) {
            return (h("div", { class: "pds-select__action", part: "action" }, h("slot", { name: "action" })));
        }
        return null;
    }
    /**
     * Updates the form value using ElementInternals API
     */
    updateFormValue() {
        if (isSpecTest())
            return;
        if (this.internals && this.internals.setFormValue) {
            const value = this.value;
            // Handle multi-select arrays by converting to FormData or comma-separated string
            if (Array.isArray(value)) {
                if (value.length > 1) {
                    // For multiple values, create FormData with multiple entries
                    const formData = new FormData();
                    value.forEach(val => formData.append(this.name || '', val));
                    this.internals.setFormValue(formData);
                }
                else {
                    // Single value in array, use the string value
                    this.internals.setFormValue(value[0] || null);
                }
            }
            else {
                // Single string value
                this.internals.setFormValue(value || null);
            }
            // Set validity based on native select validation
            if (this.selectEl && this.internals && this.internals.setValidity) {
                this.internals.setValidity(this.selectEl.validity, this.selectEl.validationMessage, this.selectEl);
            }
        }
    }
    /**
     * Form Associated Custom Elements API: Called when the form is reset
     */
    formResetCallback() {
        this.value = '';
        this.updateFormValue();
    }
    /**
     * Form Associated Custom Elements API: Called when the form is disabled
     */
    formDisabledCallback(disabled) {
        this.disabled = disabled;
    }
    /**
     * Form Associated Custom Elements API: Called to restore form state
     */
    formStateRestoreCallback(state) {
        if (typeof state === 'string') {
            this.value = state;
        }
        else if (state instanceof FormData && this.name) {
            // Extract value(s) from FormData using the select's name
            const values = state.getAll(this.name);
            if (values.length > 1) {
                // Multi-select: convert to string array
                this.value = values.filter(v => typeof v === 'string');
            }
            else if (values.length === 1 && typeof values[0] === 'string') {
                // Single select: use string value
                this.value = values[0];
            }
        }
    }
    render() {
        const hasAction = this.el.querySelector('[slot="action"]') !== null;
        return (h(Host, { key: '28292440973cbb60c63a296415a617e05fc9c5ce', "aria-disabled": this.disabled ? 'true' : null, class: this.classNames(), "has-action": hasAction && !this.hideLabel ? 'true' : null }, h("div", { key: '4a0f255ecc75c9fcedfc933c0a728d26918d9a9c', class: "pds-select" }, !this.hideLabel && (h("div", { key: '1f0b2a9ccf4ce2b79d5bb4dd40ff076b415bc6ac', class: "pds-select__label-wrapper" }, h("label", { key: '9e30b1b0266981f73f0821c05e833cb66a3caf3c', htmlFor: this.componentId }, h("span", { key: '7790be41907be6c5e3b460aa84b7ea54773cc14d', class: this.hideLabel ? 'visually-hidden' : '' }, this.label)), hasAction && this.renderAction())), h("select", { key: 'd66b39ee412bfbf3c6dfff722cb061f24ba82df6', "aria-label": this.hideLabel ? this.label : undefined, autocomplete: this.autocomplete || undefined, class: "pds-select__field", disabled: this.disabled, id: this.componentId, multiple: this.multiple, name: this.name, onBlur: this.onBlur, onChange: this.onSelectUpdate, onFocus: this.onFocus, onKeyDown: this.onKeyDown, part: "select", required: this.required, ref: (el) => (this.selectEl = el) }), h("div", { key: 'daf4846494666ebade54249c8d925423e71e7d33', "aria-hidden": "true", class: "hidden", ref: (el) => (this.slotContainer = el) }, h("slot", { key: '545f421fd2679d4bb6ee34658f7dd4089ece4f81', onSlotchange: this.handleSlotChange })), this.renderMessages(), !this.multiple && h("pds-icon", { key: '0b3bcd3ceee6e6b2ab24b52f16f6cbd89ae88322', class: "pds-select__select-icon", icon: enlarge }))));
    }
    static get is() { return "pds-select"; }
    static get encapsulation() { return "shadow"; }
    static get formAssociated() { return true; }
    static get originalStyleUrls() {
        return {
            "$": ["pds-select.tokens.scss", "../../global/styles/utils/label.scss", "pds-select.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["pds-select.tokens.css", "../../global/styles/utils/label.css", "pds-select.css"]
        };
    }
    static get properties() {
        return {
            "autocomplete": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Specifies if and how the browser provides `autocomplete` assistance for the field."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "autocomplete"
            },
            "componentId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "A unique identifier used for the underlying component `id` attribute."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "component-id"
            },
            "disabled": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "defaultValue",
                            "text": "false"
                        }],
                    "text": "Indicates whether or not the select field is disabled."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disabled",
                "defaultValue": "false"
            },
            "errorMessage": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Displays error message text describing an invalid state."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "error-message"
            },
            "hideLabel": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Visually hides the label text for instances where only the select should be displayed. Label remains accessible to assistive technology such as screen readers.\nNote: When true, the action slot is also hidden to maintain a minimal UI."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "hide-label"
            },
            "helperMessage": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Displays helper message text below select."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "helper-message"
            },
            "invalid": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Determines whether or not the select is invalid."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "invalid"
            },
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Text to be displayed as the select label."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "label"
            },
            "multiple": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "defaultValue",
                            "text": "false"
                        }],
                    "text": "Indicates whether multiple options can be selected."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "multiple",
                "defaultValue": "false"
            },
            "name": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Specifies the name. Submitted with the form name/value pair."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "name"
            },
            "required": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "defaultValue",
                            "text": "false"
                        }],
                    "text": "Indicates whether or not the select field is required."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "required",
                "defaultValue": "false"
            },
            "highlight": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "Applies highlight styling to the select field."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "highlight"
            },
            "value": {
                "type": "string",
                "mutable": true,
                "complexType": {
                    "original": "string | string[]",
                    "resolved": "string | string[]",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The value(s) of the selected option(s)."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "value"
            }
        };
    }
    static get events() {
        return [{
                "method": "pdsSelectChange",
                "name": "pdsSelectChange",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the select value changes."
                },
                "complexType": {
                    "original": "InputEvent",
                    "resolved": "InputEvent",
                    "references": {
                        "InputEvent": {
                            "location": "global",
                            "id": "global::InputEvent"
                        }
                    }
                }
            }, {
                "method": "pdsBlur",
                "name": "pdsBlur",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the select loses focus."
                },
                "complexType": {
                    "original": "FocusEvent",
                    "resolved": "FocusEvent",
                    "references": {
                        "FocusEvent": {
                            "location": "global",
                            "id": "global::FocusEvent"
                        }
                    }
                }
            }, {
                "method": "pdsFocus",
                "name": "pdsFocus",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the select gains focus."
                },
                "complexType": {
                    "original": "FocusEvent",
                    "resolved": "FocusEvent",
                    "references": {
                        "FocusEvent": {
                            "location": "global",
                            "id": "global::FocusEvent"
                        }
                    }
                }
            }, {
                "method": "pdsKeyDown",
                "name": "pdsKeyDown",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when a key is pressed down in the select."
                },
                "complexType": {
                    "original": "KeyboardEvent",
                    "resolved": "KeyboardEvent",
                    "references": {
                        "KeyboardEvent": {
                            "location": "global",
                            "id": "global::KeyboardEvent"
                        }
                    }
                }
            }];
    }
    static get elementRef() { return "el"; }
    static get watchers() {
        return [{
                "propName": "value",
                "methodName": "valueChanged"
            }, {
                "propName": "multiple",
                "methodName": "multipleChanged"
            }];
    }
}
//# sourceMappingURL=pds-select.js.map
