import plugin from 'tailwindcss/plugin'
declare let module: any

export type ThemeColors =
  | 'ai'
  | 'black'
  | 'white'
  | 'primary'
  | 'teal'
  | 'gray'
  | 'purple'
  | 'rose'
  | 'error'
  | 'warning'
  | 'success'

/**
 * Generates all the CSS color properties from the Tailwind configuration.
 */
module.exports = plugin(function ({ addUtilities, theme }) {
  const colors = theme('colors')
  const lightStyles = new Map()
  const darkStyles = new Map()
  const lightStylesHC = new Map()
  const darkStylesHC = new Map()
  const HCChromaFactor = 0.01
  const HCLightnessFactors = [0.01, 0.01, 0.03, 0.07, 0.07, 0.07, 0.08, 0.08, 0.08, 0.09, 0.09]

  lightStyles.set('--btu-theme-primary-hue', '264') /* 264 = Closest average primary hue to design system */
  lightStyles.set('--btu-theme-error-hue', '27') /* 27 = Closest average red hue to design system */
  lightStyles.set('--btu-theme-success-hue', '157') /* 157 = Closest average green hue to design system */
  lightStyles.set('--btu-theme-white', theme('colors.white.light'))
  lightStyles.set('--btu-theme-black', theme('colors.black.light'))

  darkStyles.set('--btu-theme-white', theme('colors.white.dark'))
  darkStyles.set('--btu-theme-black', theme('colors.black.dark'))

  for (const color in colors) {
    if (colors[color].light && colors[color].dark) {
      const lightValues = colors[color].light
      const darkValues = colors[color].dark

      if (typeof lightValues === 'object') {
        for (const key in lightValues) {
          lightStyles.set(`--btu-theme-${color}-${key}`, `${lightValues[key]}`)

          // Light high contrast palette.
          lightStylesHC.set(
            `--btu-theme-${color}-${key}`,
            `from oklch(${lightValues[key]}) calc(l - ${HCLightnessFactors[Object.keys(lightValues).indexOf(key)]}) calc(c + ${color === 'gray' ? 0 : HCChromaFactor}) h`,
          )
        }
      }

      if (typeof darkValues === 'object') {
        for (const key in darkValues) {
          darkStyles.set(`--btu-theme-${color}-${key}`, `${darkValues[key]}`)

          // Dark high contrast palette.
          darkStylesHC.set(
            `--btu-theme-${color}-${key}`,
            `from oklch(${darkValues[key]}) calc(l - ${HCLightnessFactors.slice().reverse()[Object.keys(darkValues).indexOf(key)]}) calc(c + ${color === 'gray' ? 0 : HCChromaFactor}) h`,
          )
        }
      }
    }
  }

  addUtilities({
    '.lightTheme': Object.fromEntries(lightStyles.entries()),
    '.lightTheme-highcontrast': Object.fromEntries(lightStylesHC.entries()),
    '.darkTheme': Object.fromEntries(darkStyles.entries()),
    '.darkTheme-highcontrast': Object.fromEntries(darkStylesHC.entries()),
  })
})
