import * as React from 'react'
import type { Tab } from './types'
import { tabLabel, isDirty } from './utils'

type Props = {
  tabs: Tab[]
  activeId: string
  onSelect: (id: string) => void
  onClose: (id: string) => void
  onCloseOthers: (id: string) => void
  onCloseAll: () => void
}

export function TabBar({ tabs, activeId, onSelect, onClose, onCloseOthers, onCloseAll }: Props): React.ReactElement {
  const barRef = React.useRef<HTMLDivElement>(null)

  React.useEffect(() => {
    const el = barRef.current
    if (!el) return
    const active = el.querySelector('.tab.active') as HTMLElement | null
    if (active) {
      active.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' })
    }
  }, [activeId])

  return (
    <div className="tab-bar" ref={barRef}>
      {tabs.map((t) => (
        <TabItem
          key={t.id}
          tab={t}
          active={t.id === activeId}
          onSelect={() => onSelect(t.id)}
          onClose={() => onClose(t.id)}
          onCloseOthers={() => onCloseOthers(t.id)}
          onCloseAll={onCloseAll}
        />
      ))}
    </div>
  )
}

type TabItemProps = {
  tab: Tab
  active: boolean
  onSelect: () => void
  onClose: () => void
  onCloseOthers: () => void
  onCloseAll: () => void
}

function TabItem({ tab, active, onSelect, onClose, onCloseOthers, onCloseAll }: TabItemProps): React.ReactElement {
  const [menuOpen, setMenuOpen] = React.useState(false)
  const [menuPos, setMenuPos] = React.useState({ x: 0, y: 0 })
  const menuRef = React.useRef<HTMLDivElement>(null)

  React.useEffect(() => {
    if (!menuOpen) return
    const close = (e: MouseEvent): void => {
      if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
        setMenuOpen(false)
      }
    }
    const closeOnScroll = (): void => setMenuOpen(false)
    document.addEventListener('mousedown', close)
    window.addEventListener('scroll', closeOnScroll, true)
    return () => {
      document.removeEventListener('mousedown', close)
      window.removeEventListener('scroll', closeOnScroll, true)
    }
  }, [menuOpen])

  const handleContextMenu = (e: React.MouseEvent): void => {
    e.preventDefault()
    e.stopPropagation()
    setMenuPos({
      x: Math.min(e.clientX, window.innerWidth - 140),
      y: Math.min(e.clientY, window.innerHeight - 140)
    })
    setMenuOpen(true)
  }

  return (
    <div className={`tab${active ? ' active' : ''}`} onContextMenu={handleContextMenu}>
      <button type="button" className="tab-main" onClick={onSelect} title={tab.filePath ?? undefined}>
        {isDirty(tab) ? <span className="dot">·</span> : null}
        <span className="tab-title">{tabLabel(tab)}</span>
      </button>
      <button
        type="button"
        className="tab-close"
        onClick={(e) => {
          e.stopPropagation()
          onClose()
        }}
        title="关闭"
      >
        ✕
      </button>
      {menuOpen ? (
        <div className="tab-context-menu" ref={menuRef} style={{ left: menuPos.x, top: menuPos.y }}>
          <button type="button" onClick={() => { onClose(); setMenuOpen(false) }}>
            关闭
          </button>
          <button type="button" onClick={() => { onCloseOthers(); setMenuOpen(false) }}>
            关闭其他
          </button>
          <button type="button" onClick={() => { onCloseAll(); setMenuOpen(false) }}>
            关闭全部
          </button>
        </div>
      ) : null}
    </div>
  )
}