import { computed, inject, provide, ref, unref, watch, watchEffect } from "vue";
import {
  IN_BROWSER,
  colorToOnColorHex,
  colorToRGB,
  deepMerge,
  getCurrentInstance,
  getLuma,
  propsFactory
} from "@veno-ui/utils";
import defaultOptions from "./default-options";
const ThemeKey = Symbol.for("veno-ui:theme");
const makeThemeProps = propsFactory({
  /**
   * @zh 设置主题
   */
  theme: String
}, "theme");
const parseThemeOptions = (options = defaultOptions) => {
  if (!options) {
    return { ...defaultOptions, isDisabled: true };
  }
  return deepMerge(defaultOptions, options);
};
function createCssClass(selector, content) {
  return [
    `${selector} {
`,
    ...content.map((line) => `  ${line};
`),
    "}\n"
  ];
}
function createTheme(app, options) {
  const head = app._context.provides.usehead;
  const parsedOptions = parseThemeOptions(options);
  const styleEl = ref();
  const current = ref(parsedOptions.defaultTheme);
  const themes = ref(parsedOptions.themes);
  const computedThemes = computed(() => {
    return Object.keys(themes.value).reduce((obj, key) => {
      const theme = themes.value[key];
      for (const color of Object.keys(theme.colors)) {
        if (/on-[a-z]/.test(color) || theme.colors[`on-${color}`])
          continue;
        theme.colors[`on-${color}`] = colorToOnColorHex(theme.colors[color]);
      }
      obj[key] = theme;
      return obj;
    }, {});
  });
  const styles = computed(() => {
    const lines = [];
    for (const themeName of Object.keys(computedThemes.value)) {
      const theme = computedThemes.value[themeName];
      lines.push(
        ...createCssClass(`.ve-theme--${themeName}`, [
          ...genCssVariables(themeName),
          ...Object.keys(theme.variables).map((key) => {
            const value = theme.variables[key];
            const color = typeof value === "string" && value.startsWith("#") ? colorToRGB(value) : void 0;
            const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : void 0;
            return `--ve-${key}: ${rgb ?? value}`;
          })
        ])
      );
      if (theme.dark) {
        for (const key of Object.keys(theme.colors)) {
          if (/on-[a-z]/.test(key)) {
            lines.push(
              ...createCssClass(`.${key}`, [
                `color: rgb(var(--ve-theme-${key})) !important`
              ])
            );
          } else {
            lines.push(
              ...createCssClass(`.bg-${key}`, [
                `--ve-theme-overlay-multiplier: var(--ve-theme-${key}-overlay-multiplier)`,
                `background: rgb(var(--ve-theme-${key})) !important`,
                `color: rgb(var(--ve-theme-on-${key})) !important`
              ]),
              ...createCssClass(`.text-${key}`, [
                `color: rgb(var(--ve-theme-${key})) !important`
              ]),
              ...createCssClass(`.border-${key}`, [
                `--ve-border-color: var(--ve-theme-${key})`
              ])
            );
          }
        }
      }
    }
    return lines.map((str, i) => i === 0 ? str : `    ${str}`).join("");
  });
  function genCssVariables(name) {
    const theme = computedThemes.value[name];
    if (!theme)
      throw new Error(`Could not find theme ${name}`);
    const lightOverlay = theme.dark ? 2 : 1;
    const darkOverlay = theme.dark ? 1 : 2;
    const variables = [];
    for (const [key, value] of Object.entries(theme.colors)) {
      const rgb = colorToRGB(value);
      variables.push(`--ve-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
      if (!key.startsWith("on-")) {
        variables.push(`--ve-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
      }
    }
    return variables;
  }
  if (head) {
    head.addHeadObjs(computed(() => ({
      style: [{
        children: styles.value,
        type: "text/css",
        id: "veno-ui-theme-stylesheet"
      }]
    })));
    if (IN_BROWSER) {
      watchEffect(() => head.updateDOM());
    }
  } else {
    let updateStyles2 = function() {
      if (parsedOptions.isDisabled)
        return;
      genStyleElement2();
      if (styleEl.value)
        styleEl.value.innerHTML = styles.value;
    }, genStyleElement2 = function() {
      if (typeof document === "undefined" || styleEl.value)
        return;
      const el = document.createElement("style");
      el.type = "text/css";
      el.id = "veno-ui-theme-stylesheet";
      styleEl.value = el;
      document.head.appendChild(styleEl.value);
    };
    var updateStyles = updateStyles2, genStyleElement = genStyleElement2;
    watch(themes, updateStyles2, { deep: true, immediate: true });
  }
  return {
    isDisabled: parsedOptions.isDisabled,
    themes: computedThemes,
    setTheme: (key, theme) => themes.value[key] = theme,
    getTheme: (key) => computedThemes.value[key],
    current,
    themeClasses: computed(() => {
      return parsedOptions.isDisabled ? void 0 : `ve-theme--${current.value}`;
    })
  };
}
function provideTheme(props) {
  getCurrentInstance("provideTheme");
  const theme = inject(ThemeKey, null);
  if (!theme)
    throw new Error("Could not find theme injection");
  const current = computed(() => {
    const { theme: propTheme } = unref(props);
    if (propTheme && propTheme.includes(":")) {
      const [theme1, theme2] = propTheme.split(":");
      return theme?.current.value === theme1 ? theme2 : theme1;
    }
    return propTheme ?? theme?.current.value;
  });
  const themeClasses = computed(() => {
    return theme.isDisabled ? void 0 : `ve-theme--${current.value}`;
  });
  const newTheme = {
    ...theme,
    current,
    themeClasses
  };
  provide(ThemeKey, newTheme);
  return newTheme;
}
function useTheme() {
  getCurrentInstance("useTheme");
  const provider = inject(ThemeKey, null);
  if (!provider)
    throw new Error("Could not find theme injection");
  return provider;
}
export {
  ThemeKey,
  createTheme,
  makeThemeProps,
  provideTheme,
  useTheme
};
//# sourceMappingURL=index.mjs.map
