var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { MapToComponentField, MapToComponentMethod, InjectVegaSlimmer, VegaSlimmer, methodPlaceholder, } from 'vega-slimmer/core';
import { camelToDashCase } from '../../utils/string';
import { FormFieldController, } from '../validator/form-field-controller';
import { FieldErrorControllerSlimmer } from './field-error-controller-silmmer';
import changeManager from '../change-manager/change-manager';
import { FORM_ELEMENT_VALIDATE } from '../change-manager/subject/static-subject/static-subject-title';
import { FormFieldValidInvokeSlimmer } from './form-field-valid-invoke-slimmer';
import { MutationObserverSlimmer } from './mutation-observer/mutation-observer-slimmer';
import { AttributeOldValueMutationFilter } from './mutation-observer/mutation-observer-filters';
import { isArrayEqual } from '../../utils/array';
import { FormFieldStateControllerSlimmer } from './form-field-state-controller-slimmer';
/**
 * The `FormFieldControllerSlimmer` class is a TypeScript class that extends `VegaSlimmer` and provides functionality for managing form field components.
 * TODO:
 * 1.Apply formFieldController to slimmer
 * 2.There should be a decorator or other type to access the component interface for the `attributeGetter`
 */
export class FormFieldControllerSlimmer extends VegaSlimmer {
  /**
   * The constructor function initializes a FormFieldOptionForSlimmer object with the provided options.
   *
   * @param {FormFieldOptionForSlimmer<unknown>} options - The `options` parameter is an object of type `FormFieldOptionForSlimmer<T>`. It is used to
   * provide additional configuration options for the form field. The specific properties and their
   * types within the `FormFieldOptionForSlimmer` object would depend on the implementation of the `FormField` class.
   */
  constructor(options) {
    super();
    this.fieldErrorSlimmer = new FieldErrorControllerSlimmer();
    this.formFieldValidInvokeSlimmer = new FormFieldValidInvokeSlimmer();
    this.formFormStateController = new FormFieldStateControllerSlimmer();
    this.mutationObserverCallBack = () => {
      if (this.validator) {
        this.setDefaultRules();
        this.internalValidate();
      }
    };
    this.options = options;
    this.setMutationObserverSlimmer();
  }
  /**
   * listen the attributes change when connectedCallback method call
   */
  connectedCallback() {
    if (this.validator === null) {
      this.setInjectFormFieldHelper();
    }
  }
  /**
   * It destroys the validator and disconnects the observer
   */
  disconnectedCallback() {
    if (this.validator) {
      this.validator.destroy();
      this.validator = null;
    }
  }
  /**
   * listen the attributes change when componentDidLoad method call
   */
  componentDidLoad() {
    methodPlaceholder();
  }
  /**
   * "If the element exists and has a data-vega-form attribute, return true, otherwise return false."
   * The function isValidFormField() is used to determine if an element is a form field
   *
   * @param {HTMLElement} element - The element to check.
   * @returns {boolean} A function that takes an element and returns a boolean.
   */
  static isValidFormField(element) {
    return element && Boolean(element.getAttribute('data-vega-form'));
  }
  /**
   * watch the prop validationRules and call the valid method
   * some components has not a prop validationRules
   *
   * @param {FormFieldValidationRule<unknown>[]} newRules the component property validationRules new value
   * @param {FormFieldValidationRule<unknown>[]} oldRules the component property validationRules old value
   */
  watchValidationRulesByFormControllerSlimmer(newRules, oldRules) {
    if (!isArrayEqual(newRules, oldRules, false, (a, b) => {
      return a === b ? 0 : -1;
    })) {
      this.setAdditionalRules();
      this.internalValidate();
    }
  }
  /**
   * inject form file help when componentWillLoad method call
   */
  setInjectFormFieldHelper() {
    if (FormFieldControllerSlimmer.isValidFormField(this.host)) {
      const { defaultValue } = this.options;
      const validator = new FormFieldController(this.getPropertyRules(), this.host, defaultValue, this.options);
      validator.addListener({
        /* eslint-disable jsdoc/require-jsdoc */
        callback: (isValid) => {
          if (this.isValid != isValid) {
            this.isValid = isValid;
            changeManager.notify(FORM_ELEMENT_VALIDATE, { host: this.host, detail: isValid });
          }
        },
      });
      this.validator = validator;
      this.setAdditionalRules();
    }
  }
  /**
   * It sets the additional rules on the validator
   */
  setAdditionalRules() {
    if (this.options.validationRulesName &&
      this.options.validationRulesName === 'validationRules' &&
      this.validator) {
      this.validator.setAdditionalRules(this.validationRules || []);
    }
  }
  /**
   * It creates a new rule for each property rule map option, and then sets the default rules on the
   * target's validator
   */
  setDefaultRules() {
    if (this.validator) {
      this.validator.setDefaultRules(this.getPropertyRules());
    }
  }
  /**
   * It takes the property rules from the option, maps them to a function that returns a validation rule,
   * and then filters out any falsy values
   *
   * @typedef T generic type
   * @returns {FormFieldValidationRule<T>[]} An array of validation rules.
   */
  getPropertyRules() {
    const { propertyRules, attributeGetter } = this.options;
    return propertyRules
      .map((rule) => {
      const dependenceValue = rule.dependence && typeof rule.dependence === 'string'
        ? [attributeGetter(rule.dependence)]
        : Array.isArray(rule.dependence)
          ? rule.dependence.map((item) => attributeGetter(item))
          : [null];
      return rule.ruleFactory(attributeGetter(rule.propertyName), ...dependenceValue);
    })
      .filter(Boolean);
  }
  /**
   * "If the target is not disabled, then call the validate function on the target's validator
   * property."
   *
   * The validator property is a property that we'll add to the target element. It's a property that
   * will hold a reference to the validator object that we'll create
   */
  internalValidate() {
    if (!this.disabled && this.validator) {
      void this.validator.validate();
    }
  }
  setMutationObserverSlimmer() {
    this.mutationObserverSlimmer = new MutationObserverSlimmer({
      options: {
        attributeFilter: this.options.propertyRules.map((rule) => camelToDashCase(rule.propertyName)),
        attributeOldValue: true,
      },
      mutationFilter: AttributeOldValueMutationFilter(),
      callback: this.mutationObserverCallBack,
    });
  }
}
__decorate([
  MapToComponentField()
], FormFieldControllerSlimmer.prototype, "host", void 0);
__decorate([
  MapToComponentField({ writable: true })
], FormFieldControllerSlimmer.prototype, "validationRules", void 0);
__decorate([
  MapToComponentField()
], FormFieldControllerSlimmer.prototype, "disabled", void 0);
__decorate([
  MapToComponentField()
], FormFieldControllerSlimmer.prototype, "autoValidation", void 0);
__decorate([
  MapToComponentField({ writable: true })
], FormFieldControllerSlimmer.prototype, "isValid", void 0);
__decorate([
  InjectVegaSlimmer()
], FormFieldControllerSlimmer.prototype, "fieldErrorSlimmer", void 0);
__decorate([
  InjectVegaSlimmer()
], FormFieldControllerSlimmer.prototype, "formFieldValidInvokeSlimmer", void 0);
__decorate([
  InjectVegaSlimmer()
], FormFieldControllerSlimmer.prototype, "mutationObserverSlimmer", void 0);
__decorate([
  InjectVegaSlimmer()
], FormFieldControllerSlimmer.prototype, "formFormStateController", void 0);
__decorate([
  MapToComponentMethod('connectedCallback')
], FormFieldControllerSlimmer.prototype, "connectedCallback", null);
__decorate([
  MapToComponentMethod('disconnectedCallback')
], FormFieldControllerSlimmer.prototype, "disconnectedCallback", null);
__decorate([
  MapToComponentMethod('componentDidLoad')
], FormFieldControllerSlimmer.prototype, "componentDidLoad", null);
__decorate([
  MapToComponentMethod('watchValidationRules')
], FormFieldControllerSlimmer.prototype, "watchValidationRulesByFormControllerSlimmer", null);
__decorate([
  MapToComponentMethod('componentWillLoad')
], FormFieldControllerSlimmer.prototype, "setInjectFormFieldHelper", null);
