import { InternalFormFieldValidationRule } from './internal-form-field-validation-rule.abstract';
/**
 * A rule that checks if number is in min and max range
 */
export class InputRangeMinAndMaxRule extends InternalFormFieldValidationRule {
  /**
   * It creates a new instance of the class with the given config.
   *
   * @param {{ minValue: number; maxValue: number }} config - config including the minDate and the maxDate
   * @param {string} config.minValue - The min number
   * @param {string} config.maxValue - The max number
   */
  constructor(config) {
    super();
    /**
     * Generate an invalid result
     *
     * @param {string} message Error message
     * @returns {EvaluateResultTranslation} invalid validation result
     */
    this.invalidResult = (message) => ({
      isValid: false,
      message,
    });
    /**
     * Generate a valid result
     *
     * @returns {EvaluateResultTranslation} invalid validation result
     */
    this.validResult = () => ({
      isValid: true,
      message: '',
    });
    this.minValue = config.minValue === 0 || config.minValue ? Number(config.minValue) : null;
    this.maxValue = config.maxValue === 0 || config.maxValue ? Number(config.maxValue) : null;
  }
  /**
   * 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} A boolean value.
   */
  canEvaluate(input, status) {
    return status
      ? this.isAcceptedInputType(input) && !status.disabled && status.visible
      : this.isAcceptedInputType(input);
  }
  /**
   * check if the start value is within the min and max range, and if the end value is within the
   * max range
   *
   * @param {string[]} input - The value of the input range.
   * @returns  {EvaluateResultTranslation} - The result of the evaluation.
   */
  evaluate(input) {
    if (!this.isAcceptedInputType(input)) {
      throw new Error(`Unexpected type of input: ${typeof input}: ${input}`);
    }
    const startValue = Number(input[0]), endValue = Number(input[1]);
    if (this.minValue !== null &&
      ((input[0] !== '' && startValue < this.minValue) || (input[1] !== '' && endValue < this.minValue))) {
      return this.invalidResult({ key: 'The minimum input value is {0}', args: [this.minValue] });
    }
    if (this.maxValue !== null &&
      ((input[0] !== '' && startValue > this.maxValue) || (input[1] !== '' && endValue > this.maxValue))) {
      return this.invalidResult({ key: 'The maximum input value is {0}', args: [this.maxValue] });
    }
    if (input[0] !== '' && input[1] !== '' && startValue > endValue) {
      return this.invalidResult(`The end value should be greater than the start value`);
    }
    return this.validResult();
  }
  /**
   * 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);
  }
  /**
   * It returns true if the input is a string or an array of two strings, and each string is a valid string
   *
   * @param {unknown} input - The input value to be validated.
   * @returns {boolean} A boolean value.
   */
  isAcceptedInputType(input) {
    return (Array.isArray(input) &&
      input.length === 2 &&
      input.every((item) => typeof Number(item) === 'number'));
  }
}
