import type { HSL } from "../types";
import { HSL_LIMITS, TYPE } from "../constants";

/**
 * Validates HSL values
 * @param hslInput HSL values to validate
 * @getters getResult(), getHSLInput(), hasErrors(), getErrorsList()
 * @result HSL values object or null
 */
export default class ValidateHSLValues {
  private result: HSL | null = null;
  private errors: boolean = false;
  private errmsg: string[] = [];
  private hslInput: HSL = { type: TYPE.HSL, h: -1, s: -1, l: -1 }; // default returns error to validation

  constructor(hslInput: HSL) {
    this.hslInput = hslInput;

    if (this.isHueOutOfRange() || this.isSaturationOutOfRange() || this.isLightnessOutOfRange()) {
      this.setErrorState();
      return;
    }

    const regex = /^[0-9]*$/;

    for (const [key, value] of Object.entries(this.hslInput)) {
      if (!regex.test(value.toString())) {
        this.setErrorState();
        this.addError(`${key.toUpperCase()} value must be a number.`);
      }
    }

    this.result = this.errors ? null : this.hslInput;
  }

  get getResult() {
    return this.result;
  }

  get getHSLInput() {
    return this.hslInput;
  }

  get hasErrors() {
    return this.errors;
  }

  get getErrorsList() {
    return this.errmsg;
  }

  private addError(msg: string) {
    this.errmsg.push(msg);
  }

  private setErrorState() {
    this.errors = true;
  }

  private showErrors() {
    this.errmsg.forEach((msg) => {
      console.log(msg);
    });
  }

  isHueOutOfRange() {
    if (this.hslInput.h > HSL_LIMITS.MAX_H) {
      this.addError(`Hue value is too high. Max is ${HSL_LIMITS.MAX_H}.`);
      return true;
    }
    if (this.hslInput.h < HSL_LIMITS.MIN_H) {
      this.addError(`Hue value is too low. Min is ${HSL_LIMITS.MIN_H}.`);
      return true;
    }
    return false;
  }

  isSaturationOutOfRange() {
    if (this.hslInput.s > HSL_LIMITS.MAX_S) {
      this.addError(`Saturation value is too high. Max is ${HSL_LIMITS.MAX_S}.`);
      return true;
    }
    if (this.hslInput.s < HSL_LIMITS.MIN_S) {
      this.addError(`Saturation value is too low. Min is ${HSL_LIMITS.MIN_S}.`);
      return true;
    }
    return false;
  }

  isLightnessOutOfRange() {
    if (this.hslInput.l > HSL_LIMITS.MAX_L) {
      this.addError(`Lightness value is too high. Max is ${HSL_LIMITS.MAX_L}.`);
      return true;
    }
    if (this.hslInput.l < HSL_LIMITS.MIN_L) {
      this.addError(`Lightness value is too low. Min is ${HSL_LIMITS.MIN_L}.`);
      return true;
    }
    return false;
  }
}
