import { __decorate } from 'tslib';
import { queryAsync } from 'lit/decorators.js';
import { InputValidationController } from './inputValidationController.js';

/**
 * @summary The FormValidationMixin used by the form components
 * @param superClass
 * @returns
 */
const SgdsFormValidatorMixin = (superClass) => {
    class ToBeValidatedElement extends superClass {
        // TypeScript requires mixin constructors to have rest parameter of type any[]
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        constructor(...args) {
            super(...args);
            this._isTouched = false;
            this._internals = this.attachInternals();
        }
        connectedCallback() {
            var _a;
            super.connectedCallback();
            if (this._mixinShouldSkipSgdsValidation())
                return;
            /** Idempotency guarantee */
            (_a = this.inputValidationController) !== null && _a !== void 0 ? _a : (this.inputValidationController = new InputValidationController(this));
        }
        async firstUpdated(changedProperties) {
            super.firstUpdated(changedProperties);
            /* Either input or sgds-input. For example, quantity-toggle uses sgds-input */
            this.input =
                this.shadowRoot.querySelector("input") ||
                    (await this.sgdsInput) ||
                    this.shadowRoot.querySelector("textarea") ||
                    (await this.sgdsDatepickerInput);
            this._mixinSetFormValue();
            if (this._mixinShouldSkipSgdsValidation())
                return;
            this._mixinValidate(this.input);
        }
        /**
         * Native lifecycle of Form-Associated Custom Element Callbacks
         */
        formResetCallback() {
            if (this._mixinResetFormControl) {
                this._mixinResetFormControl();
            }
            else {
                this.value = this.defaultValue;
                this._mixinResetValidity(this.input);
            }
            this._mixinSetFormValue();
        }
        /**
         *
         * Methods use by classes using this mixin
         */
        /**
         * OnChange of form component
         * 1. Make value of control accessible via FormData
         * 2. Run change handler
         */
        _mixinHandleChange(e) {
            this._mixinSetFormValue();
            if (this._mixinShouldSkipSgdsValidation())
                return;
            this.inputValidationController.handleChange(e);
        }
        /**
         * OnChange of form component
         * 1. Make value of control accessible via FormData
         * 2. Run input handler
         */
        _mixinHandleInputChange(e) {
            this._mixinSetFormValue();
            if (this._mixinShouldSkipSgdsValidation())
                return;
            this.inputValidationController.handleInput(e);
        }
        /**
         * During form resetting,
         * 1. ValidityState is reset
         * 2. invalid reactive prop is updated after the reset
         * 3. Revalidates the ValidityState (but do not update invalid prop)
         * to prepare for the next validity check
         * 4. Reset touched state to false for a pristine form
         */
        _mixinResetValidity(input) {
            if (this._mixinShouldSkipSgdsValidation())
                return;
            this.inputValidationController.resetValidity();
            this.inputValidationController.updateInvalidState();
            this.inputValidationController.validateInput(input);
            this._isTouched ? (this._isTouched = false) : null;
        }
        _mixinValidate(input) {
            if (this._mixinShouldSkipSgdsValidation())
                return;
            this.inputValidationController.validateInput(input);
        }
        _mixinSetFormValue() {
            const value = this.value;
            this._internals.setFormValue(value);
        }
        _mixinCheckValidity() {
            if (this._mixinShouldSkipSgdsValidation())
                return true;
            return this.inputValidationController.checkValidity();
        }
        _mixinReportValidity() {
            if (this._mixinShouldSkipSgdsValidation())
                return true;
            return this.inputValidationController.reportValidity();
        }
        _mixinGetValidity() {
            return this._internals.validity;
        }
        _mixinGetValidationMessage() {
            return this._internals.validationMessage;
        }
        _mixinSetValidity(flags, message, anchor) {
            if (this._mixinShouldSkipSgdsValidation())
                return;
            return this.inputValidationController.setValidity(flags, message, anchor);
        }
        // Only check for noValidate prop
        _mixinShouldSkipSgdsValidation() {
            const form = this.closest("form");
            return (form === null || form === void 0 ? void 0 : form.noValidate) || this.noValidate;
        }
    }
    ToBeValidatedElement.formAssociated = true;
    __decorate([
        queryAsync("sgds-input")
    ], ToBeValidatedElement.prototype, "sgdsInput", void 0);
    __decorate([
        queryAsync("sgds-datepicker-input")
    ], ToBeValidatedElement.prototype, "sgdsDatepickerInput", void 0);
    return ToBeValidatedElement;
};

export { SgdsFormValidatorMixin };
//# sourceMappingURL=validatorMixin.js.map
