import { __esDecorate, __runInitializers } from "tslib";
import { LitElement, html, nothing } from 'lit';
import { property, state, query } from 'lit/decorators.js';
import { repeat } from 'lit/directives/repeat.js';
import '../../../md/chip/ui-chip-set.js';
import '../../../md/chip/ui-chip.js';
import '../../../md/select/ui-select.js';
import '../../../md/select/ui-option.js';
let CurrencyPicker = (() => {
    let _classSuper = LitElement;
    let _selected_decorators;
    let _selected_initializers = [];
    let _selected_extraInitializers = [];
    let _allowedCurrencies_decorators;
    let _allowedCurrencies_initializers = [];
    let _allowedCurrencies_extraInitializers = [];
    let _label_decorators;
    let _label_initializers = [];
    let _label_extraInitializers = [];
    let _name_decorators;
    let _name_initializers = [];
    let _name_extraInitializers = [];
    let _supportingText_decorators;
    let _supportingText_initializers = [];
    let _supportingText_extraInitializers = [];
    let _required_decorators;
    let _required_initializers = [];
    let _required_extraInitializers = [];
    let _disabled_decorators;
    let _disabled_initializers = [];
    let _disabled_extraInitializers = [];
    let _multi_decorators;
    let _multi_initializers = [];
    let _multi_extraInitializers = [];
    let _showErrors_decorators;
    let _showErrors_initializers = [];
    let _showErrors_extraInitializers = [];
    let _selectableCurrencies_decorators;
    let _selectableCurrencies_initializers = [];
    let _selectableCurrencies_extraInitializers = [];
    let _selectElement_decorators;
    let _selectElement_initializers = [];
    let _selectElement_extraInitializers = [];
    return class CurrencyPicker extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _selected_decorators = [property({ type: Array })];
            _allowedCurrencies_decorators = [property({ type: Array })];
            _label_decorators = [property({ type: String })];
            _name_decorators = [property({ type: String })];
            _supportingText_decorators = [property({ type: String })];
            _required_decorators = [property({ type: Boolean })];
            _disabled_decorators = [property({ type: Boolean })];
            _multi_decorators = [property({ type: Boolean })];
            _showErrors_decorators = [property({ type: Boolean })];
            _selectableCurrencies_decorators = [state()];
            _selectElement_decorators = [query('ui-select')];
            __esDecorate(this, null, _selected_decorators, { kind: "accessor", name: "selected", static: false, private: false, access: { has: obj => "selected" in obj, get: obj => obj.selected, set: (obj, value) => { obj.selected = value; } }, metadata: _metadata }, _selected_initializers, _selected_extraInitializers);
            __esDecorate(this, null, _allowedCurrencies_decorators, { kind: "accessor", name: "allowedCurrencies", static: false, private: false, access: { has: obj => "allowedCurrencies" in obj, get: obj => obj.allowedCurrencies, set: (obj, value) => { obj.allowedCurrencies = value; } }, metadata: _metadata }, _allowedCurrencies_initializers, _allowedCurrencies_extraInitializers);
            __esDecorate(this, null, _label_decorators, { kind: "accessor", name: "label", static: false, private: false, access: { has: obj => "label" in obj, get: obj => obj.label, set: (obj, value) => { obj.label = value; } }, metadata: _metadata }, _label_initializers, _label_extraInitializers);
            __esDecorate(this, null, _name_decorators, { kind: "accessor", name: "name", static: false, private: false, access: { has: obj => "name" in obj, get: obj => obj.name, set: (obj, value) => { obj.name = value; } }, metadata: _metadata }, _name_initializers, _name_extraInitializers);
            __esDecorate(this, null, _supportingText_decorators, { kind: "accessor", name: "supportingText", static: false, private: false, access: { has: obj => "supportingText" in obj, get: obj => obj.supportingText, set: (obj, value) => { obj.supportingText = value; } }, metadata: _metadata }, _supportingText_initializers, _supportingText_extraInitializers);
            __esDecorate(this, null, _required_decorators, { kind: "accessor", name: "required", static: false, private: false, access: { has: obj => "required" in obj, get: obj => obj.required, set: (obj, value) => { obj.required = value; } }, metadata: _metadata }, _required_initializers, _required_extraInitializers);
            __esDecorate(this, null, _disabled_decorators, { kind: "accessor", name: "disabled", static: false, private: false, access: { has: obj => "disabled" in obj, get: obj => obj.disabled, set: (obj, value) => { obj.disabled = value; } }, metadata: _metadata }, _disabled_initializers, _disabled_extraInitializers);
            __esDecorate(this, null, _multi_decorators, { kind: "accessor", name: "multi", static: false, private: false, access: { has: obj => "multi" in obj, get: obj => obj.multi, set: (obj, value) => { obj.multi = value; } }, metadata: _metadata }, _multi_initializers, _multi_extraInitializers);
            __esDecorate(this, null, _showErrors_decorators, { kind: "accessor", name: "showErrors", static: false, private: false, access: { has: obj => "showErrors" in obj, get: obj => obj.showErrors, set: (obj, value) => { obj.showErrors = value; } }, metadata: _metadata }, _showErrors_initializers, _showErrors_extraInitializers);
            __esDecorate(this, null, _selectableCurrencies_decorators, { kind: "accessor", name: "selectableCurrencies", static: false, private: false, access: { has: obj => "selectableCurrencies" in obj, get: obj => obj.selectableCurrencies, set: (obj, value) => { obj.selectableCurrencies = value; } }, metadata: _metadata }, _selectableCurrencies_initializers, _selectableCurrencies_extraInitializers);
            __esDecorate(this, null, _selectElement_decorators, { kind: "accessor", name: "selectElement", static: false, private: false, access: { has: obj => "selectElement" in obj, get: obj => obj.selectElement, set: (obj, value) => { obj.selectElement = value; } }, metadata: _metadata }, _selectElement_initializers, _selectElement_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        /**
         * Indicates that this custom element is form-associated and can participate in form submission.
         * This enables the component to work with native HTML forms and use ElementInternals.
         */
        static formAssociated = true;
        /**
         * Private ElementInternals instance for form integration and validation.
         * Provides access to form APIs like setFormValue, setValidity, etc.
         */
        internals;
        /**
         * Shadow root configuration for the component.
         * Uses 'open' mode for accessibility and delegates focus to enable proper focus management.
         */
        static shadowRootOptions = {
            mode: 'open',
            delegatesFocus: true,
        };
        #selected_accessor_storage = __runInitializers(this, _selected_initializers, []
        /**
         * The currencies that should be available for selection.
         * If not specified, all supported currencies will be available.
         * This is an array of ISO 4217 currency codes (e.g., 'USD', 'EUR').
         */
        );
        /**
         * The currently selected currency codes.
         * This is an array of ISO 4217 currency codes (e.g., 'USD', 'EUR').
         */
        get selected() { return this.#selected_accessor_storage; }
        set selected(value) { this.#selected_accessor_storage = value; }
        #allowedCurrencies_accessor_storage = (__runInitializers(this, _selected_extraInitializers), __runInitializers(this, _allowedCurrencies_initializers, []
        /**
         * The label for the currency selection dropdown.
         * This is displayed as the label for the select input.
         * @attribute
         */
        ));
        /**
         * The currencies that should be available for selection.
         * If not specified, all supported currencies will be available.
         * This is an array of ISO 4217 currency codes (e.g., 'USD', 'EUR').
         */
        get allowedCurrencies() { return this.#allowedCurrencies_accessor_storage; }
        set allowedCurrencies(value) { this.#allowedCurrencies_accessor_storage = value; }
        #label_accessor_storage = (__runInitializers(this, _allowedCurrencies_extraInitializers), __runInitializers(this, _label_initializers, 'Add Currency'
        /**
         * The name attribute for the currency selection dropdown.
         * This is used when submitting forms that include this component.
         * @attribute
         */
        ));
        /**
         * The label for the currency selection dropdown.
         * This is displayed as the label for the select input.
         * @attribute
         */
        get label() { return this.#label_accessor_storage; }
        set label(value) { this.#label_accessor_storage = value; }
        #name_accessor_storage = (__runInitializers(this, _label_extraInitializers), __runInitializers(this, _name_initializers, void 0));
        /**
         * The name attribute for the currency selection dropdown.
         * This is used when submitting forms that include this component.
         * @attribute
         */
        get name() { return this.#name_accessor_storage; }
        set name(value) { this.#name_accessor_storage = value; }
        #supportingText_accessor_storage = (__runInitializers(this, _name_extraInitializers), __runInitializers(this, _supportingText_initializers, void 0));
        /**
         * Supporting text for the currency selection dropdown.
         * This is displayed below the select input.
         * @attribute
         */
        get supportingText() { return this.#supportingText_accessor_storage; }
        set supportingText(value) { this.#supportingText_accessor_storage = value; }
        #required_accessor_storage = (__runInitializers(this, _supportingText_extraInitializers), __runInitializers(this, _required_initializers, false
        /**
         * Whether the currency selection is disabled.
         * If true, the component will not allow any changes to the selected currencies.
         * @attribute
         */
        ));
        /**
         * Whether the currency selection is required.
         * If true, the component will enforce at least one currency to be selected.
         * @attribute
         */
        get required() { return this.#required_accessor_storage; }
        set required(value) { this.#required_accessor_storage = value; }
        #disabled_accessor_storage = (__runInitializers(this, _required_extraInitializers), __runInitializers(this, _disabled_initializers, false
        /**
         * Whether multiple currencies can be selected.
         * If true, the component allows selecting multiple currencies.
         * If false, only one currency can be selected at a time.
         * @attribute
         */
        ));
        /**
         * Whether the currency selection is disabled.
         * If true, the component will not allow any changes to the selected currencies.
         * @attribute
         */
        get disabled() { return this.#disabled_accessor_storage; }
        set disabled(value) { this.#disabled_accessor_storage = value; }
        #multi_accessor_storage = (__runInitializers(this, _disabled_extraInitializers), __runInitializers(this, _multi_initializers, false
        /**
         * Whether to show errors inline within the component.
         * If true, errors will be displayed below the component.
         * If false, errors will only be dispatched as events.
         * @attribute
         */
        ));
        /**
         * Whether multiple currencies can be selected.
         * If true, the component allows selecting multiple currencies.
         * If false, only one currency can be selected at a time.
         * @attribute
         */
        get multi() { return this.#multi_accessor_storage; }
        set multi(value) { this.#multi_accessor_storage = value; }
        #showErrors_accessor_storage = (__runInitializers(this, _multi_extraInitializers), __runInitializers(this, _showErrors_initializers, true
        /**
         * The currently selectable currencies (filtered based on selection and allowed currencies).
         * This is automatically updated based on the selected currencies and allowedCurrencies property.
         */
        ));
        /**
         * Whether to show errors inline within the component.
         * If true, errors will be displayed below the component.
         * If false, errors will only be dispatched as events.
         * @attribute
         */
        get showErrors() { return this.#showErrors_accessor_storage; }
        set showErrors(value) { this.#showErrors_accessor_storage = value; }
        #selectableCurrencies_accessor_storage = (__runInitializers(this, _showErrors_extraInitializers), __runInitializers(this, _selectableCurrencies_initializers, []
        /**
         * Reference to the Material Design outlined select element.
         * Used to manage the select's internal state and keep it synchronized with the component's selected property.
         */
        ));
        /**
         * The currently selectable currencies (filtered based on selection and allowed currencies).
         * This is automatically updated based on the selected currencies and allowedCurrencies property.
         */
        get selectableCurrencies() { return this.#selectableCurrencies_accessor_storage; }
        set selectableCurrencies(value) { this.#selectableCurrencies_accessor_storage = value; }
        #selectElement_accessor_storage = (__runInitializers(this, _selectableCurrencies_extraInitializers), __runInitializers(this, _selectElement_initializers, void 0));
        /**
         * Reference to the Material Design outlined select element.
         * Used to manage the select's internal state and keep it synchronized with the component's selected property.
         */
        get selectElement() { return this.#selectElement_accessor_storage; }
        set selectElement(value) { this.#selectElement_accessor_storage = value; }
        /**
         * Returns the form element that contains this component, if any.
         * Part of the ElementInternals API for form-associated custom elements.
         */
        get form() {
            return this.internals.form;
        }
        /**
         * Returns the validity state of the component.
         * Part of the ElementInternals API for form-associated custom elements.
         */
        get validity() {
            return this.internals.validity;
        }
        /**
         * Returns the validation message for the component.
         * Part of the ElementInternals API for form-associated custom elements.
         */
        get validationMessage() {
            return this.internals.validationMessage;
        }
        /**
         * Returns whether the component will be validated when the form is submitted.
         * Part of the ElementInternals API for form-associated custom elements.
         */
        get willValidate() {
            return this.internals.willValidate;
        }
        /**
         * Checks the validity of the component without displaying validation UI.
         * Part of the ElementInternals API for form-associated custom elements.
         * @returns True if the component is valid, false otherwise
         */
        checkValidity() {
            return this.internals.checkValidity();
        }
        /**
         * Checks the validity of the component and displays validation UI if invalid.
         * Part of the ElementInternals API for form-associated custom elements.
         * @returns True if the component is valid, false otherwise
         */
        reportValidity() {
            return this.internals.reportValidity();
        }
        /**
         * Master list of supported currencies with their display information.
         * This includes popular currencies with their ISO codes, names, symbols, countries, and flag emojis.
         * Private and readonly to ensure data integrity.
         */
        currencies = (__runInitializers(this, _selectElement_extraInitializers), [
            { code: 'USD', name: 'US Dollar', symbol: '$', country: 'United States', flag: '🇺🇸' },
            { code: 'EUR', name: 'Euro', symbol: '€', country: 'European Union', flag: '🇪🇺' },
            { code: 'GBP', name: 'British Pound', symbol: '£', country: 'United Kingdom', flag: '🇬🇧' },
            { code: 'JPY', name: 'Japanese Yen', symbol: '¥', country: 'Japan', flag: '🇯🇵' },
            { code: 'CAD', name: 'Canadian Dollar', symbol: 'C$', country: 'Canada', flag: '🇨🇦' },
            { code: 'AUD', name: 'Australian Dollar', symbol: 'A$', country: 'Australia', flag: '🇦🇺' },
            { code: 'CHF', name: 'Swiss Franc', symbol: 'Fr', country: 'Switzerland', flag: '🇨🇭' },
            { code: 'CNY', name: 'Chinese Yuan', symbol: '¥', country: 'China', flag: '🇨🇳' },
            { code: 'INR', name: 'Indian Rupee', symbol: '₹', country: 'India', flag: '🇮🇳' },
            { code: 'KRW', name: 'South Korean Won', symbol: '₩', country: 'South Korea', flag: '🇰🇷' },
            { code: 'BRL', name: 'Brazilian Real', symbol: 'R$', country: 'Brazil', flag: '🇧🇷' },
            { code: 'MXN', name: 'Mexican Peso', symbol: '$', country: 'Mexico', flag: '🇲🇽' },
            { code: 'SGD', name: 'Singapore Dollar', symbol: 'S$', country: 'Singapore', flag: '🇸🇬' },
            { code: 'HKD', name: 'Hong Kong Dollar', symbol: 'HK$', country: 'Hong Kong', flag: '🇭🇰' },
            { code: 'NOK', name: 'Norwegian Krone', symbol: 'kr', country: 'Norway', flag: '🇳🇴' },
            { code: 'SEK', name: 'Swedish Krona', symbol: 'kr', country: 'Sweden', flag: '🇸🇪' },
            { code: 'DKK', name: 'Danish Krone', symbol: 'kr', country: 'Denmark', flag: '🇩🇰' },
            { code: 'PLN', name: 'Polish Zloty', symbol: 'zł', country: 'Poland', flag: '🇵🇱' },
            { code: 'RUB', name: 'Russian Ruble', symbol: '₽', country: 'Russia', flag: '🇷🇺' },
            { code: 'ZAR', name: 'South African Rand', symbol: 'R', country: 'South Africa', flag: '🇿🇦' },
            { code: 'TRY', name: 'Turkish Lira', symbol: '₺', country: 'Turkey', flag: '🇹🇷' },
            { code: 'NZD', name: 'New Zealand Dollar', symbol: 'NZ$', country: 'New Zealand', flag: '🇳🇿' },
            { code: 'THB', name: 'Thai Baht', symbol: '฿', country: 'Thailand', flag: '🇹🇭' },
            { code: 'ILS', name: 'Israeli Shekel', symbol: '₪', country: 'Israel', flag: '🇮🇱' },
            { code: 'AED', name: 'UAE Dirham', symbol: 'د.إ', country: 'United Arab Emirates', flag: '🇦🇪' },
        ]);
        constructor() {
            super();
            this.internals = this.attachInternals();
        }
        connectedCallback() {
            super.connectedCallback();
            this.updateSelectableCurrencies();
            this.updateFormValue();
        }
        /**
         * Updates the form value using ElementInternals.
         */
        updateFormValue() {
            const value = this.selected.length > 0 ? this.selected.join(',') : null;
            this.internals.setFormValue(value);
        }
        willUpdate(changed) {
            super.willUpdate(changed);
            // Validate selected currencies with error handling
            if (changed.has('selected')) {
                this.selected = this.safeCurrencyValidation(this.selected, 'selected');
                // Also validate against allowedCurrencies if specified
                if (this.allowedCurrencies.length > 0) {
                    const allowedSet = new Set(this.allowedCurrencies);
                    const invalidSelectedCodes = this.selected.filter((code) => !allowedSet.has(code));
                    if (invalidSelectedCodes.length > 0) {
                        this.setError({
                            type: 'validation',
                            message: `Selected currencies not in allowed list: ${invalidSelectedCodes.join(', ')}`,
                            details: {
                                property: 'selected',
                                invalidCodes: invalidSelectedCodes,
                                allowedCurrencies: this.allowedCurrencies,
                            },
                        });
                        // Filter out invalid codes
                        this.selected = this.selected.filter((code) => allowedSet.has(code));
                    }
                }
                // Also validate selection constraints when property changes
                if (!this.multi && this.selected.length > 1) {
                    // In single-select mode, keep only the first valid selection
                    this.selected = this.selected.slice(0, 1);
                    this.setError({
                        type: 'selection',
                        message: 'Multiple currency selection is not allowed when multi=false. Only first selection kept.',
                        details: { multi: this.multi, originalSelection: changed.get('selected') },
                    });
                }
                // Validate required constraint
                if (this.required && this.selected.length === 0) {
                    this.internals.setValidity({ valueMissing: true }, 'At least one currency must be selected');
                    this.setAttribute('aria-invalid', 'true');
                    this.dispatchErrorEvent({
                        type: 'selection',
                        message: 'At least one currency must be selected when required=true',
                        details: { required: this.required, currentSelection: this.selected },
                    });
                }
                else if (!this.required || this.selected.length > 0) {
                    // Clear validation if not required or has selection
                    this.internals.setValidity({});
                    this.setAttribute('aria-invalid', 'false');
                }
            }
            // Validate allowed currencies with error handling
            if (changed.has('allowedCurrencies')) {
                this.allowedCurrencies = this.safeCurrencyValidation(this.allowedCurrencies, 'allowedCurrencies');
                // Filter selected currencies to only include allowed ones
                if (this.allowedCurrencies.length > 0) {
                    const allowedSet = new Set(this.allowedCurrencies);
                    const filteredSelected = this.selected.filter((code) => allowedSet.has(code));
                    if (filteredSelected.length !== this.selected.length) {
                        this.selected = filteredSelected;
                    }
                }
            }
            if (changed.has('selected') || changed.has('allowedCurrencies') || changed.has('multi')) {
                this.updateSelectableCurrencies();
            }
            // Update form value when selected changes
            if (changed.has('selected')) {
                this.updateFormValue();
            }
            // Synchronize the select element's value with the component's selected state
            if (changed.has('selected') && this.selectElement) {
                // In single-select mode, set the select value to the first selected currency or empty
                // In multi-select mode, always clear the select after selection to allow adding more
                if (!this.multi) {
                    this.selectElement.value = this.selected.length > 0 ? this.selected[0] : '';
                }
                else {
                    // For multi-select, always keep the select cleared to allow adding more currencies
                    this.selectElement.value = '';
                }
            }
        }
        /**
         * Called after the component has been updated and rendered.
         * Ensures the select element's value stays synchronized with the component's selected state.
         */
        updated(changed) {
            super.updated(changed);
            // Ensure select element is synchronized after rendering
            if (this.selectElement && (changed.has('selected') || changed.has('multi'))) {
                if (!this.multi) {
                    // In single-select mode, show the selected currency or clear the select
                    this.selectElement.value = this.selected.length > 0 ? this.selected[0] : '';
                }
                else {
                    // In multi-select mode, always keep the select cleared to allow adding more currencies
                    this.selectElement.value = '';
                }
            }
        }
        /**
         * Sets an error state using ElementInternals and optionally dispatches an error event.
         * @param error The error to set
         * @param dispatch Whether to dispatch an error event (default: true)
         */
        setError(error, dispatch = true) {
            // Use ElementInternals for native form validation
            this.internals.setValidity({ customError: true }, error.message);
            this.setAttribute('aria-invalid', 'true');
            if (dispatch) {
                this.dispatchErrorEvent(error);
            }
        }
        /**
         * Dispatches an error event.
         * @param error The error to dispatch
         */
        dispatchErrorEvent(error) {
            this.dispatchEvent(new CustomEvent('error', {
                detail: { error },
                bubbles: false,
            }));
        }
        /**
         * Clears the current error state using ElementInternals.
         */
        clearError() {
            this.internals.setValidity({});
            this.setAttribute('aria-invalid', 'false');
        }
        /**
         * Validates currency codes against the supported currencies.
         * @param codes Array of currency codes to validate
         * @returns Array of invalid currency codes
         */
        validateCurrencyCodes(codes) {
            return codes.filter((code) => !this.currencies.some((c) => c.code === code));
        }
        /**
         * Safely validates and filters currency codes, setting errors for invalid codes.
         * @param codes Array of currency codes to validate
         * @param property Name of the property being validated
         * @returns Array of valid currency codes
         */
        safeCurrencyValidation(codes, property) {
            if (!Array.isArray(codes)) {
                this.setError({
                    type: 'validation',
                    message: `Invalid ${property}: expected array of currency codes`,
                    details: { property, value: codes },
                });
                return [];
            }
            const invalidCodes = this.validateCurrencyCodes(codes);
            if (invalidCodes.length > 0) {
                this.setError({
                    type: 'validation',
                    message: `Invalid currency codes in ${property}: ${invalidCodes.join(', ')}`,
                    details: { property, invalidCodes, validCodes: this.currencies.map((c) => c.code) },
                }); // Dispatch error event for validation errors
                // Return only valid codes
                return codes.filter((code) => !invalidCodes.includes(code));
            }
            // Clear any previous validation errors for this property
            if (!this.internals.validity.valid) {
                this.clearError();
            }
            return codes;
        }
        /**
         * Validates selection constraints using ElementInternals.
         * @param newSelection The new selection to validate
         * @returns Whether the selection is valid
         */
        validateSelectionConstraints(newSelection) {
            if (!this.multi && newSelection.length > 1) {
                this.setError({
                    type: 'selection',
                    message: 'Multiple currency selection is not allowed when multi=false',
                    details: { multi: this.multi, attemptedSelection: newSelection },
                });
                return false;
            }
            if (this.required && newSelection.length === 0) {
                this.internals.setValidity({ valueMissing: true }, 'At least one currency must be selected');
                this.setAttribute('aria-invalid', 'true');
                this.dispatchErrorEvent({
                    type: 'selection',
                    message: 'At least one currency must be selected when required=true',
                    details: { required: this.required, currentSelection: newSelection },
                });
                return false;
            }
            return true;
        }
        updateSelectableCurrencies() {
            const selectedCodes = new Set(this.selected);
            // If allowedCurrencies is specified, filter the master list by it
            let availableCurrencies = this.currencies;
            if (this.allowedCurrencies.length > 0) {
                const allowedSet = new Set(this.allowedCurrencies);
                availableCurrencies = this.currencies.filter((c) => allowedSet.has(c.code));
            }
            if (this.multi) {
                // Then filter out already selected currencies
                this.selectableCurrencies = availableCurrencies.filter((c) => !selectedCodes.has(c.code));
            }
            else {
                // If single-select, just use the available currencies
                this.selectableCurrencies = availableCurrencies;
            }
        }
        handleCurrencySelect(event) {
            event.stopPropagation();
            try {
                const select = event.target;
                const selectedCode = select.value;
                if (!selectedCode)
                    return;
                const currency = this.currencies.find((c) => c.code === selectedCode);
                if (!currency) {
                    this.setError({
                        type: 'selection',
                        message: `Currency not found: ${selectedCode}`,
                        details: { attemptedCode: selectedCode },
                    });
                    return;
                }
                let newSelection;
                if (this.multi) {
                    // If multi-select, add the currency to the selection
                    if (!this.selected.includes(currency.code)) {
                        newSelection = [...this.selected, currency.code];
                    }
                    else {
                        // Currency already selected, clear any selection errors but don't add duplicate
                        if (!this.internals.validity.valid) {
                            this.clearError();
                        }
                        return;
                    }
                }
                else {
                    // If single-select, replace the current selection
                    newSelection = [currency.code];
                }
                // Validate the new selection
                if (!this.validateSelectionConstraints(newSelection)) {
                    return; // Error was set in validateSelectionConstraints
                }
                this.selected = newSelection;
                this.updateSelectableCurrencies();
                // Reset the select for multi-select mode
                if (this.multi) {
                    select.value = '';
                }
                // Clear any previous errors on successful selection
                this.clearError();
                this.dispatchChangeEvent();
            }
            catch (error) {
                this.setError({
                    type: 'internal',
                    message: `Internal error during currency selection: ${error instanceof Error ? error.message : String(error)}`,
                    details: { originalError: error },
                });
            }
        }
        handleRemoveCurrency(event) {
            try {
                const chip = event.target;
                const currencyCode = chip.dataset.code;
                if (!currencyCode) {
                    this.setError({
                        type: 'internal',
                        message: 'Unable to determine currency code from chip element',
                        details: { chipElement: chip },
                    });
                    return;
                }
                const newSelection = this.selected.filter((code) => code !== currencyCode);
                // Validate the new selection (e.g., required constraint)
                if (!this.validateSelectionConstraints(newSelection)) {
                    return; // Error was set in validateSelectionConstraints
                }
                this.selected = newSelection;
                this.updateSelectableCurrencies();
                // Clear any previous errors on successful removal
                this.clearError();
                this.dispatchChangeEvent();
            }
            catch (error) {
                this.setError({
                    type: 'internal',
                    message: `Internal error during currency removal: ${error instanceof Error ? error.message : String(error)}`,
                    details: { originalError: error },
                });
            }
        }
        dispatchChangeEvent() {
            const selectedCurrencies = this.getSelectedCurrencies();
            // Update form value using ElementInternals
            this.updateFormValue();
            this.dispatchEvent(new CustomEvent('change', {
                detail: {
                    currencies: selectedCurrencies,
                    codes: this.selected,
                },
                bubbles: false,
            }));
        }
        /**
         * Get the currently selected currency codes as a copy of the array.
         * This is a read-only getter that returns a shallow copy to prevent external modification.
         * @returns Array of selected ISO 4217 currency codes
         */
        get selectedCurrencyCodes() {
            return [...this.selected];
        }
        /**
         * Get the full currency objects for currently selected currencies.
         * This method looks up each selected currency code in the master currencies list
         * and returns the complete currency information including name, symbol, country, and flag.
         * @returns Array of complete Currency objects for selected currencies
         */
        getSelectedCurrencies() {
            const result = [];
            for (const code of this.selected) {
                const currency = this.currencies.find((c) => c.code === code);
                if (currency) {
                    result.push(currency);
                }
            }
            return result;
        }
        /**
         * Clear all selected currencies.
         * This method removes all selections, validates constraints (such as required),
         * updates the UI, and dispatches a change event. If validation fails (e.g.,
         * component is required), the operation will be cancelled and an error will be set.
         * @throws Will dispatch an error event if validation fails or an internal error occurs
         */
        clearSelection() {
            try {
                const newSelection = [];
                // Validate clearing selection (e.g., required constraint)
                if (!this.validateSelectionConstraints(newSelection)) {
                    return; // Error was set in validateSelectionConstraints
                }
                this.selected = newSelection;
                this.updateSelectableCurrencies();
                // Clear any previous errors on successful clear
                this.clearError();
                this.dispatchChangeEvent();
                // Synchronize the select element to show no selection
                if (this.selectElement) {
                    this.selectElement.value = '';
                }
            }
            catch (error) {
                this.setError({
                    type: 'internal',
                    message: `Internal error during selection clear: ${error instanceof Error ? error.message : String(error)}`,
                    details: { originalError: error },
                });
            }
            finally {
                this.requestUpdate();
            }
        }
        /**
         * Form state restore callback for ElementInternals.
         * This method is called by the browser when form state is being restored
         * (e.g., browser back/forward navigation, form autofill).
         * It parses a comma-separated string of currency codes and restores the selection.
         * @param state The state to restore - typically a comma-separated string of currency codes
         * @param _mode The restore mode (unused in this implementation)
         */
        formStateRestoreCallback(state) {
            if (typeof state === 'string' && state) {
                this.selected = state.split(',').filter(Boolean);
                this.updateSelectableCurrencies();
                // Synchronize the select element with restored state
                if (this.selectElement) {
                    if (!this.multi && this.selected.length > 0) {
                        this.selectElement.value = this.selected[0];
                    }
                    else {
                        this.selectElement.value = '';
                    }
                }
            }
        }
        /**
         * Form reset callback for ElementInternals.
         * This method is called by the browser when the containing form is reset.
         * It clears all selections, updates the UI, clears any errors, and updates the form value.
         */
        formResetCallback() {
            this.selected = [];
            this.updateSelectableCurrencies();
            this.clearError();
            this.updateFormValue();
            // Synchronize the select element to show no selection
            if (this.selectElement) {
                this.selectElement.value = '';
            }
            this.requestUpdate();
        }
        /**
         * Main render method for the component.
         * Renders the currency selector with dropdown, selected chips (if multi-select), and error display.
         * Updates ARIA attributes and error states based on current component state.
         * @returns TemplateResult containing the complete component HTML
         */
        render() {
            const ariaLabel = this.multi
                ? `Currency selector. ${this.selected.length} currencies selected.`
                : `Currency selector. ${this.selected.length > 0 ? this.selected[0] + ' selected' : 'No currency selected'}.`;
            const hasError = !this.internals.validity.valid;
            return html `
      <div class="currency-picker" role="group" aria-label="${ariaLabel}">
        <ui-select
          label="${this.label}"
          @change="${this.handleCurrencySelect}"
          ?disabled="${this.disabled}"
          ?required="${this.required}"
          .supportingText="${this.supportingText || ''}"
          .name="${this.name || ''}"
          aria-describedby="${this.supportingText ? 'supporting-text' : ''}"
          aria-invalid="${hasError ? 'true' : 'false'}"
        >
          <ui-option value="">
            <div>Select a currency...</div>
          </ui-option>
          ${repeat(this.selectableCurrencies, (currency) => currency.code, (currency) => html `
              <ui-option value="${currency.code}">
                <div slot="overline">${currency.country}</div>
                <div slot="supporting-text">${currency.name}</div>
                <div slot="end-text" class="currency-symbol">${currency.symbol}</div>
                <div slot="start" class="flag">${currency.flag}</div>
                <div>${currency.code}</div>
              </ui-option>
            `)}
        </ui-select>
        ${this.renderSelected()}${this.renderError()}
      </div>
    `;
        }
        /**
         * Renders error messages when showErrors is true and the component is invalid.
         * The error display uses ARIA live regions for accessibility.
         * @returns TemplateResult with error display or nothing if no errors should be shown
         */
        renderError() {
            if (!this.showErrors || this.internals.validity.valid) {
                return nothing;
            }
            return html `
      <div class="error" role="alert" aria-live="polite">
        <span class="error-message">${this.internals.validationMessage}</span>
      </div>
    `;
        }
        /**
         * Renders the selected currencies as removable chips in multi-select mode.
         * Only renders when multi=true and there are selected currencies.
         * Each chip displays the currency flag and code, and can be removed by the user.
         * @returns TemplateResult with chip display or nothing if not applicable
         */
        renderSelected() {
            if (!this.multi) {
                return nothing;
            }
            const selected = this.getSelectedCurrencies();
            if (selected.length === 0)
                return nothing;
            return html `
      <ui-chip-set>
        ${repeat(selected, (currency) => currency.code, (currency) => html `
            <ui-chip
              data-code="${currency.code}"
              type="input"
              @remove="${this.handleRemoveCurrency}"
              ?removable="${true}"
            >
              <span slot="icon" class="chip-flag">${currency.flag}</span>
              <span class="chip-code">${currency.code}</span>
            </ui-chip>
          `)}
      </ui-chip-set>
    `;
        }
    };
})();
/**
 * A web component for selecting currencies with chips display.
 * Provides a searchable interface with country flags and currency information.
 *
 * This component uses ElementInternals for native form integration and
 * follows web standards for error handling and validation.
 *
 * ## Features
 * - Single or multi-select currency selection
 * - Visual chips display for selected currencies
 * - Native form integration with ElementInternals
 * - Comprehensive validation and error handling
 * - Accessibility support with ARIA attributes
 * - Keyboard navigation support
 * - Currency filtering based on allowed currencies
 *
 * ## Usage
 * ```html
 * <!-- Basic usage -->
 * <currency-picker></currency-picker>
 *
 * <!-- Multi-select with allowed currencies -->
 * <currency-picker multi .allowedCurrencies="${['USD', 'EUR', 'GBP']}"></currency-picker>
 *
 * <!-- Form integration -->
 * <form>
 *   <currency-picker name="currencies" required></currency-picker>
 * </form>
 * ```
 *
 * @fires change - Dispatched when selected currencies change due to user interaction.
 *                 Contains {currencies: Currency[], codes: string[]} in event.detail
 * @fires error - Dispatched when validation or other errors occur.
 *                Contains {error: CurrencyPickerError} in event.detail
 *
 * @example
 * ```typescript
 * const picker = document.querySelector('currency-picker');
 * picker.addEventListener('change', (e) => {
 *   console.log('Selected currencies:', e.detail.currencies);
 * });
 * picker.addEventListener('error', (e) => {
 *   console.error('Picker error:', e.detail.error.message);
 * });
 * ```
 */
export default CurrencyPicker;
//# sourceMappingURL=Picker.js.map