import CBOR from "cbor";
import { useEffect, useState } from "react";
import useWebSocket, { ReadyState } from "react-use-websocket";
import * as Automerge from "@automerge/automerge";
import * as uuid from "uuid";
import { wsUrl } from "./constants";
import { Tab, Tabs } from "react-bootstrap";
import Upload from "./Upload";
import Chat from "./Chat";
import Grub from "./Grub";
import { RoomContext } from "./lib/roomContext";
import { Wifi } from "react-bootstrap-icons";

const connectionStatusMap = {
  [ReadyState.CONNECTING]: "Connecting",
  [ReadyState.OPEN]: "Open",
  [ReadyState.CLOSING]: "Closing",
  [ReadyState.CLOSED]: "Closed",
  [ReadyState.UNINSTANTIATED]: "Uninstantiated",
};

export default function Room({ roomId }) {
  const [readyState, setReadyState] = useState(ReadyState.CLOSED);
  const [connectedClients, setConnectedClients] = useState([]);
  const [clientId, setClientId] = useState<string | null>(null);

  const {
    sendMessage,
    lastJsonMessage,
    readyState: newReadyState,
  } = useWebSocket(wsUrl, {
    share: true,
    onOpen: ({}) => {
      console.log("Shiet, connected.");
    },
    onMessage: async (event) => {
      const data = CBOR.decode(await event.data.arrayBuffer());
      console.log("received", data);

      if (data.type === "ServerHello") {
        setClientId(uuid.stringify(data.client_id));
      }

      if (data.type === "RoomClientList") {
        setConnectedClients(data.clients.map((x) => uuid.stringify(x)));
      }

      if (data.type === "Automerge") {
        const [nextDoc, nextSyncState, patch] = Automerge.receiveSyncMessage(
          doc,
          syncState,
          data.message[1]
        );
        setDoc(nextDoc);
        setSyncState(nextSyncState);
        console.log("patch", patch);
      }
    },
  });

  function sendWtfMessage(data) {
    let cbor = CBOR.encode(data);
    console.log(
      "cbor-encoded",
      [...new Uint8Array(cbor)]
        .map((x) => x.toString(16).padStart(2, "0"))
        .join(" ")
    );
    sendMessage(cbor);
  }

  useEffect(() => {
    if (
      readyState === ReadyState.CONNECTING &&
      newReadyState === ReadyState.OPEN
    ) {
      // On Open
      sendWtfMessage({ type: "JoinRoom", room_id: roomId });
      console.log("Sent connection message");
    }
    setReadyState(newReadyState);
  }, [newReadyState]);

  const connectionStatus = connectionStatusMap[readyState];

  if (newReadyState !== ReadyState.OPEN) return <>Connecting...</>;

  return (
    <RoomContext.Provider value={{ roomId, clientId }}>
      <p>Room Id: {roomId}</p>
      <p>
        Connection status: <ConnectionStatus readyState={readyState} />
      </p>
      Connected:
      <ul>
        {connectedClients.map((x) => (
          <li key={x}>{x}</li>
        ))}
      </ul>
      <Tabs
        defaultActiveKey="file-transfer"
        id="uncontrolled-tab-example"
        className="mb-3"
      >
        <Tab eventKey="file-transfer" title="File Transfer">
          <Upload />
        </Tab>
        <Tab eventKey="grocery-tracking" title="Grocery Tracking">
          <Grub />
        </Tab>
        <Tab eventKey="chat" title="Chat">
          <Chat />
        </Tab>
      </Tabs>
    </RoomContext.Provider>
  );
}

function ConnectionStatus({ readyState }) {
  switch (readyState) {
    case ReadyState.CONNECTING:
      return <Wifi color="yellow" />;
    case ReadyState.OPEN:
      return <Wifi color="green" />;
    default:
      return null;
  }
}
