import { InternalFormFieldValidationRule } from './internal-form-field-validation-rule.abstract';
/**
 * A rule that checks if a string is empty or not
 *
 * @augments {InternalFormFieldValidationRule<string>}
 */
export class RequiredFieldRule extends InternalFormFieldValidationRule {
  constructor() {
    super(...arguments);
    /**
     * A function that checks if the item is a string, number, or boolean.
     *
     * @param {unknown} item - The item to be checked.
     * @returns {boolean} The return value is a boolean that indicates whether the item is string, number or boolean.
     */
    this.checkArrayItemType = (item) => typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean';
  }
  /**
   * If the input is a number or a boolean, return true. If the input is a string, return true if the string is not empty
   *
   * @param {FormFieldValueType | Array<FormFieldValueType>} input - The input to be evaluated.
   * @returns {EvaluateResult} An object with two properties: isValid and message.
   */
  evaluate(input) {
    if (!this.isAcceptedInputType(input)) {
      throw new Error(`Unexpected type of input: ${typeof input}: ${input}`);
    }
    else if (typeof input === 'number' || typeof input === 'boolean') {
      return {
        isValid: true,
        message: '',
      };
    }
    else if (typeof input === 'string' || Array.isArray(input)) {
      return {
        isValid: input.length > 0,
        message: input.length <= 0 ? 'This field is required' : '',
      };
    }
    else {
      return {
        isValid: false,
        message: 'This field is required',
      };
    }
  }
  /**
   * If the input is accepted and the status is not disabled and visible, then return true
   *
   * @param {unknown} input - The input to be evaluated.
   * @param {FormFieldStatusMeta} [status] - FormFieldStatusMeta
   * @returns {boolean} The return value is a boolean that indicates whether the input can be evaluated.
   */
  canEvaluate(input, status) {
    return status
      ? this.isAcceptedInputType(input) && !status.disabled && status.visible
      : this.isAcceptedInputType(input);
  }
  /**
   * If the field is not disabled, visible, and has been touched or modified, then show the error
   *
   * @param {FormFieldStatusMeta} status - FormFieldStatusMeta
   * @returns {boolean} A boolean value.
   */
  shouldShowError(status) {
    return !status.disabled && status.visible && (status.touched || status.modified);
  }
  /**
   * If the input is a string, number, boolean, or null, return true, otherwise return false.
   *
   * @param {unknown} input - The input value to be validated.
   * @returns {boolean} a boolean value.
   */
  isAcceptedInputType(input) {
    return (typeof input === 'string' ||
      typeof input === 'number' ||
      typeof input === 'boolean' ||
      (Array.isArray(input) && input.every(this.checkArrayItemType)) ||
      input === null ||
      input === undefined);
  }
}
