import { isAsyncFunction } from '../../../utils/misc';
/** The `FormFieldValidationRuleHandler` class is responsible for handling the validation rules for a form field. */
export class FormFieldValidationRuleHandler {
  /**
   * The constructor function takes a FormFieldValidationRule as a parameter.
   *
   * @param {FormFieldValidationRule<unknown>} rule - It is used to define the validation rule for a form field.
   */
  constructor(rule) {
    this.rule = rule;
  }
  /**
   * The function `getStatus` returns an object with properties `canEvaluate` and `isAsync` based on the input, status, and statusChanged parameters.
   *
   * @param {unknown} input - The input parameter represents the value that needs to be evaluated.
   * @param {FormFieldStatusMeta} status - It represents the current status of a form field.
   * @param {(keyof FormFieldStatusMeta)[]} statusChanged - It represents the fields whose status has changed.
   * @returns {HandlerStatusType} an object of type HandlerStatusType.
   */
  getStatus(input, status, statusChanged) {
    return {
      canEvaluate: this.rule.canEvaluate(input, status, statusChanged),
      isAsync: isAsyncFunction(this.rule.evaluate),
    };
  }
  /**
   * The function shouldShowError determines whether an error should be shown based on the status and statusChanged parameters.
   *
   * @param {FormFieldStatusMeta} status - It contains information such as whether the field is valid, invalid, or untouched.
   * @param {(keyof FormFieldStatusMeta)[]} statusChanged - It represents the fields that have changed their status.
   * @returns {boolean} show error message or not
   */
  shouldShowError(status, statusChanged) {
    try {
      return this.rule.shouldShowError
        ? this.rule.shouldShowError(status, statusChanged)
        : this.defaultShouldShowError(status);
    }
    catch (e) {
      return false;
    }
  }
  /**
   * The function takes an input of type T and evaluates it using a rule, returning an EvaluateResult or a Promise of EvaluateResult.
   *
   * @param {unknown} input - input field value
   * @returns {EvaluateResult | Promise<EvaluateResult>} The method is returning either an `EvaluateResult` object or a `Promise` that resolves to an `EvaluateResult` object.
   */
  handle(input) {
    try {
      return this.rule.evaluate(input);
    }
    catch (e) {
      return { isValid: true, message: '' };
    }
  }
  /**
   * If the field is not disabled, visible, and the field is touched or modified, then return true
   *
   * @param {FormFieldStatusMeta} status - FormFieldStatusMeta - The status of the field.
   * @returns {boolean} A function that takes in 3 parameters and returns a boolean.
   */
  defaultShouldShowError(status) {
    return !status.disabled && status.visible && (status.touched || status.modified);
  }
}
