import type { CustomCell, CustomRenderer } from '@glideapps/glide-data-grid'
import { GridCellKind } from '@glideapps/glide-data-grid'

import { ReactNode } from 'react'

import { APP_CONFIG } from '@lib/config'

export type HoverableRenderer<T extends CustomCell = CustomCell> = {
  hoverOverlay?: (cellData: T['data']) => ReactNode
} & CustomRenderer<T>

export type CountryArrayCell = CustomCell<{
  kind: 'country-array-cell'
  countries: { id: string; label: string; hoverLabel?: string }[]
}>

const countryImageCache: Record<string, HTMLImageElement> = {}

export const countryArrayDataTableRenderer: HoverableRenderer<CountryArrayCell> = {
  kind: GridCellKind.Custom,
  isMatch: (cell): cell is CountryArrayCell => (cell.data as { kind?: string }).kind === 'country-array-cell',
  draw: ({ ctx, rect, theme }, { data: { countries } }) => {
    const flagHeight = rect.height - theme.cellVerticalPadding * 2
    const flagWidth = flagHeight * 1.5 // flags are 3:2 aspect ratio

    let x = rect.x + theme.cellHorizontalPadding
    const y = rect.y + theme.cellVerticalPadding

    for (const { id, label } of countries) {
      const isUnknown = !id || id === ''

      let image: HTMLImageElement | undefined

      if (!isUnknown) {
        if (!countryImageCache[id]) {
          countryImageCache[id] = new Image()
          countryImageCache[id].src = `/flags/${id}.svg`
          countryImageCache[id].onload = () => {
            ctx.canvas.dispatchEvent(new Event('invalidate'))
          }
        }
        image = countryImageCache[id]
      }

      const circlepath = new Path2D()
      circlepath.roundRect(x, y, flagWidth, flagHeight, 2)
      ctx.save()
      ctx.clip(circlepath)

      if (isUnknown || !image || !image.complete || image.naturalHeight === 0 || APP_CONFIG.useTestAssets) {
        // Draw grey rectangle for unknown country
        ctx.fillStyle = '#cccccc'
        ctx.fillRect(x, y, flagWidth, flagHeight)
      } else {
        ctx.drawImage(image, x, y, flagWidth, flagHeight)
      }

      ctx.restore()

      ctx.save()
      ctx.font = `${theme.baseFontFull} ${theme.fontFamily}`
      ctx.fillStyle = theme.textDark
      ctx.fillText(label, x + flagWidth + 5, y + flagHeight / 2)
      ctx.restore()

      const labelWidth = ctx.measureText(label).width
      x += flagWidth + 5 + labelWidth + 10
    }

    return true
  },
  needsHover: true,
  hoverOverlay: (data) => {
    const { countries } = data
    return <>{countries.map((c) => c.hoverLabel || c.label).join(', ')}</>
  },
}
