/**
 * @license
 * Copyright Tyler Technologies, Inc. 
 * License: Apache-2.0
 */
/**
 * @license
 * Copyright 2023 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 *
 * Adapted and influenced from [Material Web](https://github.com/material-components/material-web).
 * The original source code can be found at: [GitHub](https://github.com/material-components/material-web/blob/main/labs/behaviors/form-associated.ts)
 */
import { toggleAttribute } from '@tylertech/forge-core';
import { getFormState, getFormValue, getValidationMessage, inputType, internals } from '../../../constants';
/**
 * Mixes in form functionality into a base component.
 *
 * @param base The base component to mix into.
 * @returns The mixed-in base component.
 */
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function WithFormAssociation(base) {
    class FormAssociatedComponent extends base {
        get form() {
            return this[internals].form;
        }
        get labels() {
            return this[internals].labels;
        }
        get name() {
            return this.getAttribute('name') ?? '';
        }
        set name(value) {
            toggleAttribute(this, !!value, 'name', value);
        }
        [getFormState]() {
            return this[getFormValue]();
        }
        formDisabledCallback(disabled) {
            this.disabled = disabled;
        }
        set [inputType](type) {
            // Create a detached input to retrieve localized validation messages from
            const inputElement = type === 'select' ? document.createElement('select') : document.createElement('input');
            inputElement.setAttribute('type', type);
            inputElement.name = 'internal';
            this._inputElement = inputElement;
        }
        [getValidationMessage](props) {
            // If the input element hasn't been created yet return `undefined`
            if (!this._inputElement) {
                return undefined;
            }
            // A custom error message overrides all other messages
            if (this[internals].validity.customError) {
                return this[internals].validationMessage;
            }
            // Apply validation-affecting props to the input element to get the correct validation
            // message
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            Object.entries(props).forEach(([key, value]) => (this._inputElement[key] = value));
            return this._inputElement.validationMessage;
        }
    }
    FormAssociatedComponent.formAssociated = true;
    return FormAssociatedComponent;
}
