//  Copyright (c) 2024 Huawei Technologies Co., Ltd.
//  openUBMC is licensed under Mulan PSL v2.
//  You can use this software according to the terms and conditions of the Mulan PSL v2.
//  You may obtain a copy of Mulan PSL v2 at:
//        #  http://license.coscl.org.cn/MulanPSL2
//  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
//  EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
//  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
//  See the Mulan PSL v2 for more details.
export default class Color {
  public red: number;
  public green: number;
  public blue: number;
  public alpha: number;
  public origin: string;
  private isInvalid: boolean;

  // 支持16进制和rgb合适的字符串进行初始化，例如 #07F #FFFFFF rgb(255,255,255) rgb(255,255,255,1)
  constructor(value: string) {
    const val = (value || '').trim();
    this.origin = val;
    if (this.isHex(val)) {
      this.isInvalid = false;
      const full = this.fullfillHex(val);
      this.red = Math.round(parseInt(full.substring(1, 3), 16));
      this.green = Math.round(parseInt(full.substring(3, 5), 16));
      this.blue = Math.round(parseInt(full.substring(5, 7), 16));
      this.alpha = 1;
    } else if (this.isRgb(val)) {
      this.isInvalid = false;
      const [r, g, b, a] = val.replace(/rgb\(|\)/g, '').split(',');
      this.red = this.toLimit(r);
      this.green = this.toLimit(g);
      this.blue = this.toLimit(b);
      this.alpha = this.toLimit(a) || 1;
    } else {
      this.isInvalid = true;
      this.red = 0;
      this.green = 0;
      this.blue = 0;
      this.alpha = 1;
    }
  }

  private mixinFormula(x: number, y: number, r: number): number {
    return Math.round((r * x) + ((1 - r) * y));
  }

  // 不考虑带alpha色值的混合
  public mixin(color: Color | string, radio: number): Color {
    let c;
    if (typeof color === 'string') {
      c = new Color(color);
    } else {
      c = color;
    }
    const r = this.toLimitMinMax(radio, 0, 1);
    const red = this.mixinFormula(this.red, c.red, r);
    const green = this.mixinFormula(this.green, c.green, r);
    const blue = this.mixinFormula(this.blue, c.blue, r);
    return new Color(`rgb(${red},${green},${blue})`);
  }

  public getHex(): string {
    return `#${this.to2DigitHex(this.red)}${this.to2DigitHex(this.green)}${this.to2DigitHex(this.blue)}`;
  }

  public getRgb(): string {
    const apl = `,${this.alpha}`;
    return `rgb(${this.red},${this.green},${this.blue}${this.alpha === 1 ? '' : apl})`;
  }

  public toString(): string {
    return this.value;
  }

  private isHex(color: string): boolean {
    return /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(color);
  }

  private isRgb(color: string): boolean {
    return (
      /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/.test(color) ||
      /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(([0-1])(\.\d+)?)\s*\)$/.test(color)
    );
  }

  // 将三位色值填补满6位 (e.g. #FFF => #FFFFFF)
  private fullfillHex(val: string): string {
    if (val.length === 4) {
      const [p, r, g, b] = [...val];
      return `${p}${r}${r}${g}${g}${b}${b}`;
    }
    return val;
  }

  private to2DigitHex(num: number): string {
    return num.toString(16).padStart(2, '0');
  }

  private toLimit(number: number | string): number {
    const num = Number(number);
    return this.toLimitMinMax(num, 0, 255);
  }

  private toLimitMinMax(num: number, min: number, max: number): number {
    if (num > max) {
      return max;
    } else {
      return num < min ? min : num;
    }
  }

  get value() {
    if (this.isInvalid) {
      return '';
    } else if (this.alpha === 1) {
      return this.getHex();
    } else {
      return this.getRgb();
    }
  }
}
