import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import useAdb from '@/hooks/useAdb'
import { encodeUtf8, type AdbSubprocessProtocol } from '@yume-chan/adb'
import { Consumable, WritableStream } from '@yume-chan/stream-extra'
import { useEffect, useRef, useState } from 'react'

import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'

import 'xterm/css/xterm.css'

export const ShellTab: React.FC = () => {
  const adb = useAdb(state => state.adb)

  const shellRef = useRef<HTMLDivElement>(null)

  const [process, setProcess] = useState<AdbSubprocessProtocol | undefined>()

  useEffect(() => {
    const startTerminal = async () => {
      if (shellRef.current && adb) {
        if (shellRef.current.children.length > 0) {
          // remove all children from the shellRef
          while (shellRef.current.firstChild) {
            shellRef.current.removeChild(shellRef.current.firstChild)
          }
        }
        const terminal: Terminal = new Terminal()
        const fitAddon = new FitAddon()
        terminal.loadAddon(fitAddon)

        const process: AdbSubprocessProtocol = await adb.subprocess.shell(
          '/data/data/com.termux/files/usr/bin/telnet localhost 45515'
        )
        process.stdout.pipeTo(
          new WritableStream<Uint8Array>({
            write(chunk) {
              terminal.write(chunk)
            }
          })
        )

        const writer = process.stdin.getWriter()
        terminal.onData(data => {
          const buffer = encodeUtf8(data)
          const consumable = new Consumable(buffer)
          writer.write(consumable)
        })

        terminal.options.cursorBlink = true
        terminal.options.theme = {
          background: '#1e1e1e',
          foreground: '#d4d4d4'
        }

        terminal.open(shellRef.current)
        fitAddon.fit()
        setProcess(process)
      }
    }
    startTerminal()

    return () => {
      console.log('cleaning up shell')
      shellRef.current && shellRef.current.firstChild && shellRef.current.removeChild(shellRef.current.firstChild)
      process?.stderr.cancel()
      process?.stdin.close()
      process?.stdout.cancel()
      process?.kill()
    }
  }, [shellRef, adb])

  return (
    <Card>
      <CardHeader>
        <CardTitle>Shell</CardTitle>
        <CardDescription>Access your device's shell using a terminal emulator</CardDescription>
      </CardHeader>
      <CardContent>
        <div className="flex items-center justify-end py-3 w-full">
          <div>
            <Button
              variant={'destructive'}
              onClick={() => {
                process?.stderr.cancel()
                process?.stdin.close()
                process?.stdout.cancel()
                process?.kill()
              }}
            >
              Kill Shell
            </Button>
          </div>
        </div>
        <div className="w-full h-[800px] bg-slate-700" ref={shellRef}></div>
      </CardContent>
    </Card>
  )
}
