const themeColor = {};

/**
 * 单例模式确保全局只有一个Color实例
 * @param {Object} themeColor 主题颜色
 */
const Color = (function () {
  let instance;
  return function (themeColor) {
    if (instance) return instance;
    return new ColorConstructor(themeColor);
  };
})();

class ColorConstructor {
  // 定义私有属性，用于存储主题颜色和颜色变化程度
  #themeColor; // 主题颜色
  #changeSpan; // 颜色变化程度
  #themeKey; // 主题颜色key
  #subThemeKey; // 辅助颜色key
  #theme; // 主题
  constructor({
    themeColor,
    changeSpan,
    themeKey,
    theme = "light",
    subThemeKey,
  }) {
    // 如果没有传入主题颜色，则抛出错误
    if (!themeColor) throw new Error(`主题颜色是必须的`);
    // 设置主题
    this.setTheme(theme);
    // 设置主题颜色
    this.setThemeColor({
      themeColor,
      changeSpan,
      themeKey,
      theme,
      subThemeKey,
    });
  }

  // 判断颜色是否为16进制颜色
  isHEX(color) {
    // 如果颜色长度不为7或4，则返回false
    if (color.length !== 7 && color.length !== 4) return false;
    // 定义正则表达式，用于匹配16进制颜色
    const hexreg = /^\#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;
    // 返回正则表达式匹配结果
    return hexreg.test(color);
  }
  isRGB(color) {
    const rgbreg = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/;
    return rgbreg.test(color);
  }

  // 格式化十六进制颜色值
  formatHex(hex) {
    // 如果长度不等于4，则返回原值
    if (hex.length !== 4) return hex;
    // 返回格式化后的十六进制颜色值
    return `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;
  }

  // 参数归一化颜色
  normalizeColor(color) {
    let colorMap = {};
    if (typeof color === "string") {
      if (!this.isHEX(color) && !this.isRGB(color)) {
        throw new Error(`颜色值${color}格式不正确`);
      }
      colorMap[this.#themeKey] = color;
    } else if (Object.prototype.toString.call(color) !== "[object Object]") {
      throw new Error(`颜色值${color}格式不正确 必须是字符串或者对象的形式`);
    } else {
      colorMap = color;
    }
    return colorMap;
  }

  // 设置主题颜色
  setThemeColor({
    themeColor,
    changeSpan = 0.2,
    themeKey = "primary",
    subThemeKey = "success",
    onSuccess,
  }) {
    // 将传入的颜色赋值给私有属性#themeColor
    const newTheme = this.normalizeColor(themeColor);
    this.#changeSpan = changeSpan;
    this.#themeColor = this.#setThemeMap(newTheme, this.#changeSpan);
    this.#themeKey = themeKey;
    this.#subThemeKey = subThemeKey;
    onSuccess?.(this.#themeColor);
  }

  // 设置主题
  setTheme(theme) {
    if (theme !== "dark" && theme !== "light")
      throw new Error(`主题必须是dark或者light`);
    // 将传入的主题赋值给私有属性#theme
    this.#theme = theme;
    // 调用私有方法#setThemeMap，传入私有属性#themeColor和#changeSpan，将返回值赋值给私有属性#themeColor
    this.#themeColor = this.#setThemeMap(this.#themeColor, this.#changeSpan);
  }

  // 获取主题颜色
  get themeColor() {
    // 返回主题颜色
    return this.#themeColor[this.#themeKey];
  }

  // 获取子主题颜色
  get subThemeColor() {
    // 返回主题颜色中子主题键对应的颜色值
    return this.#themeColor[this.#subThemeKey];
  }

  // 获取变淡以及加深的颜色
  #setThemeMap(themeColor, changeSpan) {
    const newTheme = { ...themeColor };
    const changeList = new Array(5)
      .fill(0)
      .map((_, index) => index * changeSpan)
      .filter((item) => item > 0 && item < 1);
    for (const key in newTheme) {
      changeList.forEach((item, index) => {
        newTheme[`${key}-light-${index + 1}`] = this.getLightColor(
          newTheme[key],
          item
        );
        newTheme[`${key}-dark-${index + 1}`] = this.getDarkColor(
          newTheme[key],
          item
        );
      });
    }
    return newTheme;
  }

  // 获取主题颜色 1-4 或者 空
  getThemeColor(index, themeKey = this.#themeKey) {
    // 打印深色主题颜色
    const key = `${themeKey}${!!index ? `-${this.#theme}-${index}` : ""}`;
    return this.#themeColor[key];
  }
  //16进制颜色转GRB颜色
  HexToRgb(str) {
    if (!this.isHEX(str)) {
      return;
    }
    str = this.formatHex(str);
    let hexs = null;
    str = str.replace("#", ""); // 去掉#
    hexs = str.match(/../g); // 切割成数组 409EFF => ['40','9E','FF']
    // 将切割的色值转换为16进制
    for (let i = 0; i < hexs.length; i++) hexs[i] = parseInt(hexs[i], 16);
    return hexs;
  }
  //GRB颜色转16进制颜色
  rgbaToHex(rgba) {
    let hex = "#";
    for (const i of rgba) {
      hex += i.toString(16).padStart(2, "0");
    }
    return hex;
  }

  // 计算颜色
  computedColor(color, fn) {
    // 将颜色转换为rgb格式
    let rgb = color;
    if (this.isHEX(color)) {
      rgb = this.HexToRgb(color);
    }
    // 创建一个空数组，用于存储转换后的颜色值
    let sColorChange = [];
    // 遍历rgb数组
    for (var i = 0; i < rgb.length; i++) {
      // 对每个颜色值进行转换
      let val = fn(rgb[i]);
      // 如果转换后的值小于0，则将其设置为0
      if (val < 0) {
        val = 0;
      }
      // 如果转换后的值大于255，则将其设置为255
      if (val > 255) {
        val = 255;
      }
      // 将转换后的值添加到数组中
      sColorChange.push(val);
    }
    // 将转换后的rgb数组转换为hex格式
    return this.rgbaToHex(sColorChange);
  }

  //得到16进制颜色值为color的加深颜色值，level为加深的程度，限0-1之间
  getDarkColor(color, level) {
    return this.computedColor(color, (item) => item - Math.floor(item * level));
  }
  //得到16进制颜色值为color的减淡颜色值，level为加深的程度，限0-1之间
  getLightColor(color, level) {
    return this.computedColor(color, (item) => item + Math.floor(item * level));
  }
}

export default new Color({ themeColor });
