import { kebabCase } from "lodash"
import { useCallback, useEffect, useRef, useState } from "react"
import { css, cx } from "@emotion/css"
import { toast } from "react-hot-toast"
import styled from "@emotion/styled"
import { parseColor } from "./utils"

import dark from "../../dist/vendor/primer/github-dark.css?string"
import dark_colorblind from "../../dist/vendor/primer/github-dark_colorblind.css?string"
import dark_dimmed from "../../dist/vendor/primer/github-dark_dimmed.css?string"
import dark_high_contrast from "../../dist/vendor/primer/github-dark_high_contrast.css?string"
import dark_tritanopia from "../../dist/vendor/primer/github-dark_tritanopia.css?string"
import light from "../../dist/vendor/primer/github-light.css?string"
import light_colorblind from "../../dist/vendor/primer/github-light_colorblind.css?string"
import light_high_contrast from "../../dist/vendor/primer/github-light_high_contrast.css?string"
import light_tritanopia from "../../dist/vendor/primer/github-light_tritanopia.css?string"

const themes = getTheme({
  dark,
  dark_colorblind,
  dark_dimmed,
  dark_high_contrast,
  dark_tritanopia,
  light,
  light_colorblind,
  light_high_contrast,
  light_tritanopia,
})

export function CSS() {
  return (
    <div>
      {themes.map(([theme, css]) => (
        <style key={theme} data-theme={theme} dangerouslySetInnerHTML={{ __html: css }} />
      ))}
    </div>
  )
}

function getTheme(object: { [key: string]: string }) {
  return Object.entries(object).map(
    ([key, css]) => [key, css.replace(/^:root/, "div")] as const,
  )
}

const colors = {
  Foreground: ["fg.default", "fg.muted", "fg.subtle", "fg.onEmphasis"],
  Canvas: ["canvas.default", "canvas.overlay", "canvas.inset", "canvas.subtle"],
  Border: ["border.default", "border.muted", "border.subtle"],
  Shadow: ["shadow.small", "shadow.medium", "shadow.large", "shadow.extraLarge"],
  Neutral: [
    "neutral.emphasisPlus",
    "neutral.emphasis",
    "neutral.muted",
    "neutral.subtle",
  ],
  Accent: ["accent.fg", "accent.emphasis", "accent.muted", "accent.subtle"],
  Success: ["success.fg", "success.emphasis", "success.muted", "success.subtle"],
  Attention: [
    "attention.fg",
    "attention.emphasis",
    "attention.muted",
    "attention.subtle",
  ],
  Severe: ["severe.fg", "severe.emphasis", "severe.muted", "severe.subtle"],
  Danger: ["danger.fg", "danger.emphasis", "danger.muted", "danger.subtle"],
  Open: ["open.fg", "open.emphasis", "open.muted", "open.subtle"],
  Closed: ["closed.fg", "closed.emphasis", "closed.muted", "closed.subtle"],
  Done: ["done.fg", "done.emphasis", "done.muted", "done.subtle"],
  Sponsors: ["sponsors.fg", "sponsors.emphasis", "sponsors.muted", "sponsors.subtle"],
}

function Col({ defaultTheme = "light" }: { defaultTheme?: string }) {
  const [theme, setTheme] = useState(defaultTheme)

  return (
    <ColContainer
      data-theme={"github-" + theme}
      className={theme.includes("dark") ? "dark" : "light"}
    >
      <Select value={theme} onChange={e => setTheme(e.target.value)}>
        {themes.map(([theme]) => (
          <option key={theme} value={theme}>
            {theme}
          </option>
        ))}
      </Select>
      <Table>
        <tbody>
          {Object.entries(colors).map(([name, values]) => (
            <tr key={name}>
              <td>{name}</td>
              {values.map(value => (
                <td key={value}>
                  <ColorCell theme={theme} name={name} value={value} />
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </Table>
    </ColContainer>
  )
}

function ColorCell({
  theme,
  name,
  value,
}: {
  theme: string
  name: string
  value: string
}) {
  const css = `var(--color-${kebabCase(value)})`

  const onClick = useCallback(async () => {
    await navigator.clipboard.writeText(css)
    toast.success("Copied to clipboard")
  }, [css])

  switch (name) {
    case "Foreground":
      return (
        <CellDiv
          onClick={onClick}
          style={{
            color: css,
            ...(theme.includes("light") &&
              value === "fg.onEmphasis" && {
                backgroundColor: "#333",
              }),
          }}
        >
          {value}
          <ColorHex property="color" />
        </CellDiv>
      )

    case "Border":
      return (
        <CellDiv
          onClick={onClick}
          style={{
            border: `2px solid`,
            borderColor: css,
          }}
        >
          {value}
          <ColorHex property="borderColor" />
        </CellDiv>
      )

    case "Shadow":
      return (
        <CellDiv onClick={onClick} style={{ boxShadow: css }}>
          {value}
          <ColorHex property="boxShadow" />
        </CellDiv>
      )

    default:
      return (
        <CellDiv onClick={onClick} style={{ backgroundColor: css }}>
          {value}
          <ColorHex property="backgroundColor" />
        </CellDiv>
      )
  }
}

function ColorHex({
  property,
}: {
  property: "backgroundColor" | "color" | "borderColor" | "boxShadow"
}) {
  const ref = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const parent = ref.current?.parentElement
    if (!parent) return

    const color = getComputedStyle(parent)[property]
    const { hex, flip } = parseColor(color.slice(color.indexOf("r")))
    if (property === "backgroundColor") {
      parent.classList.toggle("flip", flip)
    }
    ref.current!.textContent = hex
  })

  return <HexContainer ref={ref} />
}

const HexContainer = styled.div`
  font-family: D2Coding, monospace;
  font-size: 0.95em;
  margin-top: 3px;
`

export function App() {
  return (
    <div>
      <div
        className={css`
          display: grid;
          grid-template-columns: repeat(2, 1fr);
          grid-gap: 17px;
        `}
      >
        <Col defaultTheme="light" />
        <Col defaultTheme="dark" />
      </div>
    </div>
  )
}

const ColContainer = styled.div`
  border-radius: 5px;
  padding: 10px;
  select {
    border-radius: 4px;
    font-size: inherit;
    padding: 2px 3px;
  }
  &.light {
    background-color: #fff;
    select {
      border-color: #ccc;
    }
  }
  &.dark {
    background-color: #13171d;
    color: #fff;
    select {
      background-color: #222;
      color: #fff;
    }
  }
`

const CellDiv = styled.div`
  border-radius: 3px;
  cursor: pointer;
  padding: 3px 7px;
  margin: 2px;
  &:hover {
    text-decoration: underline;
  }
  &.flip {
    color: #fcfcfc;
  }
`

const Select = styled.select`
  display: block;
  max-width: 400px;
  width: 100%;
  margin: 0 auto;
  text-align: center;
`

const Table = styled.table`
  margin-top: 10px;
`
