import styled from "@emotion/styled"
import { css, cx } from "@emotion/css"
import { useTranslation } from "react-i18next"
import Icon from "@aet/icons/macro"
import { useAutoCallback, useAutoMemo } from "hooks.macro"
import { memo, useState } from "react"
import { useEventListener } from "@aet/hooks"
import type { Rule } from "~/shared/models"
import { RuleType, ruleTypes } from "~/shared/models/utils"
import { token } from "../../theme"
import { useDomainSuggestions } from "~/options/hooks/useDomainSuggestions"
import { useDataList } from "~/shared/hooks/useDatalist"

export const RuleView = memo<{
  rule: Rule
  setRule: (rule: Rule) => void
  onDelete?: () => void
}>(({ rule, setRule, onDelete }) => {
  const { t } = useTranslation()

  const isDomain = rule.type === RuleType.Domain
  const domains = useDomainSuggestions({ skip: !isDomain })
  const datalist = useDataList(domains, "hostname")
  const inputEventListeners = useClickableDomainInputEventListeners(rule)

  const getRuleName = useAutoCallback((type: RuleType) => {
    switch (type) {
      case RuleType.Domain:
        return t("rule.domain")
      case RuleType.Glob:
        return t("rule.glob")
      case RuleType.RegExp:
        return t("rule.regexp")
      case RuleType.URL:
        return t("rule.url")
      case RuleType.URLPrefix:
        return t("rule.urlPrefix")
    }
  })

  const options = useAutoMemo(
    ruleTypes.map(ruleType => (
      <option key={ruleType} value={ruleType}>
        {getRuleName(ruleType)}
      </option>
    )),
  )

  return (
    <Row>
      <ToggleCell
        onClick={() => setRule({ ...rule, exclude: !rule.exclude })}
        style={{ background: rule.exclude ? "#f8514926" : "#2ea04326" }}
      >
        <Checkbox type="checkbox" checked={!rule.exclude} readOnly />
        <Label>{rule.exclude ? t("rule.excludesLabel") : t("rule.includesLabel")}</Label>
      </ToggleCell>
      <RuleTypeCell>
        <select
          className={css`
            border: none;
            background: transparent;
            cursor: pointer;
          `}
          title={t("rule.ruleType")}
          value={rule.type}
          onChange={e => setRule({ ...rule, type: e.target.value as RuleType })}
        >
          {options}
        </select>
      </RuleTypeCell>
      <InputCell>
        <input
          {...inputEventListeners}
          type="text"
          value={rule.value}
          list={isDomain ? datalist.id : undefined}
          onChange={e => setRule({ ...rule, value: e.target.value })}
          className={cx(
            css`
              border: none;
              width: 100%;
            `,
            inputEventListeners.className,
          )}
        />
        {datalist.element}
      </InputCell>
      {onDelete != null && (
        <DeleteButtonCell title={t("rule.deleteRule")}>
          <DeleteButton
            onClick={e => {
              e.stopPropagation()
              onDelete()
            }}
          />
        </DeleteButtonCell>
      )}
    </Row>
  )
})

function useClickableDomainInputEventListeners(rule: Rule) {
  const [metaKeyPressed, setMetaKeyPressed] = useState(false)

  useEventListener(window)("keydown", e => {
    if (e.key === "Meta") {
      setMetaKeyPressed(true)
    }
  })
  useEventListener(window)("keyup", e => {
    if (e.key === "Meta") {
      setMetaKeyPressed(false)
    }
  })

  const onClick = useAutoCallback((e: React.MouseEvent) => {
    if (e.metaKey) {
      e.preventDefault()
      e.stopPropagation()
      window.open(`https://${rule.value}`, "_blank", "noopener,noreferrer")?.focus()
    }
  })

  const className = metaKeyPressed
    ? css`
        &:hover {
          color: ${token.accent.fg};
          text-decoration: underline;
          cursor: pointer;
        }
      `
    : undefined

  if (rule.type !== RuleType.Domain) {
    return {}
  }

  return {
    onClick,
    className,
  }
}

const Row = styled.tr`
  display: flex;
  align-items: center;
  &:not(:last-of-type) {
    border-bottom: 1px solid ${token.border.muted};
  }
  > td {
    min-height: 32px;
  }
`

const ToggleCell = styled.td`
  display: flex;
  align-items: center;
  text-align: center;
  min-width: 85px;
  cursor: pointer;
`

const Checkbox = styled.input`
  height: 1px;
  width: 1px;
  margin-left: -4px;
  z-index: -1;
`

const Label = styled.label`
  width: 100%;
  cursor: inherit;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
`

const RuleTypeCell = styled.td`
  background: ${token.canvas.overlay};
  &:hover {
    background: ${token.canvas.overlay};
  }
`

const InputCell = styled.td`
  flex-grow: 1;
  background: ${token.canvas.overlay};
  &:hover {
    background: ${token.canvas.overlay};
  }
`

const DeleteButtonCell = styled.td`
  background-color: ${token.danger.subtle};
  cursor: pointer;
  &:hover {
    background-color: ${token.danger.muted};
    transition: background-color 0.2s;
  }
`

const DeleteButton = styled(Icon.of("FaTrashAlt"))`
  font-size: 1em;
  margin-bottom: -4px;
`
