const MAX_HEX_LEN = 7;
const MAX_HEX_LEN_WITHOUT_HASH = 6;
const MIN_HEX_LEN = 4;
const MIN_HEX_LEN_WITHOUT_HASH = 3;

/**
 * Validate user's hex code input to make sure it's a valid hex code.
 *
 * Logic flow:
 * - len > 6, too long, error
 * - len < 3, too short, error
 * - len = 3 or 5, is # the one missing? yes: add it at front, no: error
 * - len = 6, is # at the front? yes: success, no: error
 * - success status: len = 6 wit # at front or len = 5 with no #, then add at front
 *
 * @param hexInput Hex code string to validate.
 * @getters getResult(), getHexInput(), hasErrors(), getErrorsList()
 * @result string or null
 */
export default class ValidateHex {
  private result: string | null = null;
  private errors: boolean = false;
  private errmsg: string[] = [];
  private hexInput: string = "";

  constructor(hexInput: string) {
    this.hexInput = hexInput;

    if (this.isLenTooLong() || this.isLenTooShort() || this.isLen4Or7() || this.isLenNot6()) {
      this.setErrorState();
      return;
    } else {
      this.addHashIfNeeded();
    }

    const regex = /^#([0-9A-F]{3}){1,2}$/i;

    if (!regex.test(this.result!)) {
      this.setErrorState();
      this.addError("Hex input is not a valid hex.");
      return;
    }
  }

  get getResult() {
    return this.result;
  }

  get getHexInput() {
    return this.hexInput;
  }

  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);
    });
  }

  isLenTooLong() {
    if (this.hexInput.length > MAX_HEX_LEN) {
      this.addError("Hex input is too long. It's not a valid hex.");
      return true;
    }
    return false;
  }

  private isLenTooShort() {
    if (this.hexInput.length < MIN_HEX_LEN) {
      this.addError("Hex input is too short. It's not a valid hex.");
      return true;
    }
    return false;
  }

  private isLen4Or7() {
    if (this.hexInput.length === MIN_HEX_LEN || this.hexInput.length === MAX_HEX_LEN) {
      if (this.hexInput[0] !== "#") {
        this.addError("Hex input is missing # at the front. It's not a valid hex.");
        return true;
      }
    }
    return false;
  }

  private isLenNot6() {
    return this.hexInput.length !== MAX_HEX_LEN_WITHOUT_HASH ? true : false;
  }

  private addHashIfNeeded() {
    if (this.hexInput[0] !== "#") {
      this.result = `#${this.hexInput}`;
    }
  }
}
