import * as React from 'react'
import { Global, ThemeContext as EmotionContext } from '@emotion/core'
import { css, merge, jsx, useStore, Theme } from '.'
import { toCustomProperties, createColorStyles } from './custom-properties'
import { applyMode } from './color-mode'
import { ThemeUIStyleObject } from './types'

const GlobalStyles = ({ global }: { global: ThemeUIStyleObject }) =>
  jsx(Global, {
    styles: (emotionTheme: any): any => {
      const theme = emotionTheme as Theme
      const colorStyles = createColorStyles(theme)

      return css({
        ...colorStyles,
        ...global,
      })(theme)
    },
  })

interface ContextValue {
  theme: Theme
}

const Context = React.createContext<ContextValue>({
  theme: {},
})

export const useKodiakUi = () => React.useContext(Context)

export function BaseProvider({
  context,
  children,
}: React.PropsWithChildren<{ context: ContextValue }>) {
  const { theme } = context
  theme.colors = toCustomProperties(theme.colors, 'colors')

  return jsx(
    EmotionContext.Provider,
    { value: context.theme },
    jsx(
      Context.Provider,
      {
        value: context,
      },
      jsx(GlobalStyles, { global: theme.global as any }),
      children,
    ),
  )
}

export function ThemeProvider({
  theme,
  children,
}: {
  theme: Theme
  children: React.ReactNode
}) {
  const mode = useStore(state => state.mode)
  const components = useStore(state => state.components)
  const variants = useStore(state => state.variants)

  const themeWithMode = applyMode(mode)(theme)
  const componentsAndVariants = {
    ...(components ? components : {}),
    ...(variants ? variants : {}),
  }

  const mergedTheme = merge.all(themeWithMode, componentsAndVariants)

  const context = {
    theme: mergedTheme,
  }

  return jsx(BaseProvider, { context }, children)
}