import { h } from "preact";
import { useEffect, useState, useMemo } from "preact/hooks";

export enum ThemeModes {
   AUTO,
   LIGHT,
   DARK
}

export interface IThemeProps {
   mode: ThemeModes;
   children: any;

   primary?: string;
   onPrimary?: string;
   secondary?: string;
   onSecondary?: string;
   error?: string;
   onError?: string;
   success?: string;
   onSuccess?: string;
}

const modeMediaQuery = window.matchMedia("prefers-color-scheme: dark");

export default function Theme({ mode, children, ...colors }: IThemeProps) {
   const [isDark, setIsDark] = useState(
      mode === ThemeModes.AUTO
         ? modeMediaQuery.matches
         : mode === ThemeModes.DARK
   );
   useEffect(() => {
      if (mode === ThemeModes.AUTO) {
         const listener = (ev: MediaQueryListEvent) => {
            setIsDark(ev.matches);
         };
         modeMediaQuery.addListener(listener);

         setIsDark(modeMediaQuery.matches);

         return modeMediaQuery.removeListener(listener);
      }
   }, [mode]);

   const style = useMemo(() => {
      let style = "";
      const getRGB = (color: string) => {
         const cv = document.createElement("canvas");
         cv.width = 10;
         cv.height = 10;

         const ctx = cv.getContext("2d");
         ctx.rect(0, 0, 1, 1);
         ctx.fillStyle = color;
         ctx.fill();

         const [r, g, b] = ctx.getImageData(0, 0, 10, 10).data;

         return [r, g, b];
      };

      const add = (name: string, value: string) =>
         (style += `--${name}: ${value};`);

      if (colors.primary) {
         add("primary:", colors.primary);
         add("primary-rgb", getRGB(colors.primary).join(", "));
      }
      if (colors.onPrimary) add("on-primary:", colors.onPrimary);

      if (colors.secondary) {
         add("secondary:", colors.secondary);
         add("secondary-rgb", getRGB(colors.secondary).join(", "));
      }
      if (colors.onSecondary) add("on-secondary:", colors.onSecondary);

      if (colors.error) {
         add("error:", colors.error);
         add("error-rgb", getRGB(colors.error).join(", "));
      }
      if (colors.onError) add("on-error:", colors.onError);

      if (colors.success) {
         add("success:", colors.success);
         add("success-rgb", getRGB(colors.success).join(", "));
      }
      if (colors.onSuccess) add("on-success:", colors.onSuccess);

      return style;
   }, [
      colors.primary,
      colors.secondary,
      colors.error,
      colors.success,
      colors.onPrimary,
      colors.onSecondary,
      colors.onError,
      colors.onSuccess
   ]);

   return (
      <div class={isDark ? "dark-theme" : "light-theme"} style={style}>
         {children}
      </div>
   );
}
