import { IS_BROWSER } from "$fresh/runtime.ts";
import { useEffect, useRef, useState } from "preact/hooks";
import { JSX } from "preact/jsx-runtime";
import { Sockpuppet } from "puppet/client";

export function Terminal(props: { channelId: string }) {
  const puppet = useRef<Sockpuppet>();
  const [lines, setLines] = useState<string[]>([]);
  const divRef = useRef<HTMLDivElement>(null);
  const storeKey = "commandHistory";
  const [commandHistory, setCommandHistory] = useState<string[]>(
    JSON.parse(localStorage.getItem(storeKey) || "[]"),
  );
  const [historyIndex, setHistoryIndex] = useState(commandHistory.length);

  const [command, setCommand] = useState("");

  const changeHistoryIndex = (by: number) => setHistoryIndex((i) => i + by);

  useEffect(() => {
    if (!IS_BROWSER || puppet.current) return;
    puppet.current = new Sockpuppet("ws://sockpuppet.cyborggrizzly.com", () => {
      puppet.current?.joinChannel(props.channelId, (line) => {
        if (line === "clear") {
          setLines([]);
        } else {
          setLines((l) => [...l, line]);
        }
      });
      setTimeout(() => {
        const channel = puppet.current?.getChannel(props.channelId);
        // console.log(channel)
        channel?.send("log");
      }, 200);
    });

    document.addEventListener("keyup", (e) => {
      switch (e.key) {
        case "Up":
        case "ArrowUp":
          changeHistoryIndex(-1);
          break;
        case "Down":
        case "ArrowDown":
          changeHistoryIndex(1);
          break;
      }
    });
  }, []);

  useEffect(() => {
    if (divRef.current) {
      divRef.current.scrollTop = divRef.current.scrollHeight;
    }
  }, [lines]);

  const sendCommand = (e: Event) => {
    e.preventDefault();
    puppet.current?.getChannel(props.channelId)?.send(
      commandHistory.at(historyIndex) || command,
    );
    setCommandHistory((
      c,
    ) => [...c, commandHistory.at(historyIndex) || command]);
    setHistoryIndex(commandHistory.length + 1);
    setCommand("");
  };

  const handleCommandUpdate = (
    e: JSX.TargetedEvent<HTMLInputElement, Event>,
  ) => {
    const value = e.currentTarget.value;

    if (historyIndex !== commandHistory.length) {
      setHistoryIndex(commandHistory.length);
    }

    setCommand(value || "");
  };

  useEffect(() => {
    localStorage.setItem(
      storeKey,
      JSON.stringify(commandHistory.slice(0, 100)),
    );
  }, [commandHistory]);

  return (
    <div>
      <div ref={divRef} class="flex flex-col h-[600px] w-full overflow-auto">
        {lines.map((l) => <pre class="font-mono w-full">{l}</pre>)}
      </div>
      <div class="mt-4">
        <form onSubmit={sendCommand}>
          <input
            type="text"
            class="w-full bg-smoke-600 text-white"
            value={commandHistory[historyIndex] || command}
            onInput={handleCommandUpdate}
          />
        </form>
      </div>
    </div>
  );
}
