import React, { useContext, useEffect, useRef } from 'react';
import tinycolor from 'tinycolor2';
import SilkePopoverProvider from './components/silke-popover/popover-context';

type SilkeColorGroup =
  | 'surface'
  | 'accent'
  | 'error'
  | 'warning'
  | 'success'
  | 'neutral'
  | 'support-primary'
  | 'support-secondary'
  | 'support-tertiary'
  | 'support-quaternary'
  | 'brand-primary'
  | 'brand-secondary'
  | 'brand-tertiary'
  | 'brand-quaternary';

export type SilkeColor =
  | `${SilkeColorGroup}-${'10' | '20' | '30' | '40' | '50' | '60'}`
  | `neutral-${'0' | '5' | '70' | '80' | '90' | '100'}`
  | `brand-${'primary' | 'secondary' | 'tertiary'}-bright`
  | `surface-${'0' | '1' | '2' | '3' | '4'}`;

export type SilkeColorTheme = Partial<Record<`color-${SilkeColor}`, string>>;

type SilkeContextModel = {
  /** WHen a overflow menu is mounted this is set, call function to close */
  mountedOverflowMenu?: () => void;
  colors?: SilkeColorTheme;
  onFileUpload: (file: File) => Promise<string>;
};

type SilkeThemeProviderProps = {
  children: React.ReactElement;
} & Omit<SilkeContextModel, 'mountedOverflowMenu'>;

const SilkeThemeContext = React.createContext<SilkeContextModel>({ onFileUpload: async () => '' });

export function useSilkeContext() {
  return useContext(SilkeThemeContext);
}

export function SilkeThemeProvider({ children, ...rest }: SilkeThemeProviderProps) {
  const ref = useRef<HTMLDivElement>(null);
  const { colors } = rest;
  useEffect(() => {
    // We use a non wrapping element so we don't need to care about layout and fill etc, can result in 2 theme providers using same parent element, but very unlikely
    const el = ref.current?.parentElement;
    if (!el || !colors) return;
    for (const key in colors) {
      const color = colors[key as keyof SilkeColorTheme];
      if (color) {
        el?.style.setProperty('--' + key, color);
        const { r, g, b } = tinycolor(color).toRgb();
        el?.style.setProperty(`--${key}-rgb`, `${r},${g},${b}`);
      }
    }

    return () => {
      for (const key in colors) {
        el?.style.removeProperty('--' + key);
        el?.style.removeProperty(`--${key}-rgb`);
      }
    };
  }, [colors]);
  return (
    <SilkeThemeContext.Provider value={rest}>
      <div ref={ref} />
      <SilkePopoverProvider>{children}</SilkePopoverProvider>
    </SilkeThemeContext.Provider>
  );
}
