import React, { useState, useEffect, useContext, useRef } from "react";
import Paper from "@mui/material/Paper";
import List from "@mui/material/List";

import "./PlayerList.css";
import { PlayerColor } from "./PlayerColor";
import { MediaAgent, MediaControl } from "./MediaControl";

import { GlobalContext } from "./GlobalContext";

/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */

const PlayerList: React.FC = () => {
  const { ws, name, sendJsonMessage } = useContext(GlobalContext);
  const [players, setPlayers] = useState<{ [key: string]: any }>({});
  const [unselected, setUneslected] = useState<string[]>([]);
  const [state, setState] = useState<string>("lobby");
  const [color, setColor] = useState<string | undefined>(undefined);
  const [peers, setPeers] = useState<{ [key: string]: any }>({});

  const onWsMessage = (event: MessageEvent) => {
    const data = JSON.parse(event.data);
    switch (data.type) {
      case "game-update":
        console.log(`player-list - game update`, data.update);

        if ("unselected" in data.update) {
          setUneslected(data.update.unselected);
        }

        if ("players" in data.update) {
          let found = false;
          for (const key in data.update.players) {
            if (data.update.players[key].name === name) {
              found = true;
              setColor(key);
              break;
            }
          }
          if (!found) {
            setColor(undefined);
          }
          setPlayers(data.update.players);
        }

        if ("state" in data.update && data.update.state !== state) {
          setState(data.update.state);
        }
        break;
      default:
        break;
    }
  };
  const refWsMessage = useRef(onWsMessage);

  useEffect(() => {
    refWsMessage.current = onWsMessage;
  });

  useEffect(() => {
    if (!ws) {
      return;
    }
    const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
    ws.addEventListener("message", cbMessage);
    return () => {
      ws.removeEventListener("message", cbMessage);
    };
  }, [ws, refWsMessage]);

  useEffect(() => {
    if (!sendJsonMessage) {
      return;
    }
    sendJsonMessage({
      type: "get",
      fields: ["state", "players", "unselected"],
    });
  }, [ws]);

  const toggleSelected = (key: string) => {
    ws!.send(
      JSON.stringify({
        type: "set",
        field: "color",
        value: color === key ? "" : key,
      })
    );
  };

  const playerElements: React.ReactElement[] = [];

  const inLobby = state === "lobby";
  const sortedPlayers: any[] = [];

  for (const key in players) {
    sortedPlayers.push(players[key]);
  }

  const sortPlayers = (A: any, B: any) => {
    /* active player first */
    if (A.name === name) {
      return -1;
    }
    if (B.name === name) {
      return +1;
    }

    /* Sort active players first */
    if (A.name && !B.name) {
      return -1;
    }
    if (B.name && !A.name) {
      return +1;
    }

    /* Ohterwise, sort by color */
    return A.color.localeCompare(B.color);
  };

  sortedPlayers.sort(sortPlayers);

  /* Array of just names... */
  unselected.sort((A, B) => {
    /* active player first */
    if (A === name) {
      return -1;
    }
    if (B === name) {
      return +1;
    }
    /* Then sort alphabetically */
    return A.localeCompare(B);
  });

  const videoClass = sortedPlayers.length <= 2 ? "Medium" : "Small";

  sortedPlayers.forEach((player) => {
    const playerName = player.name;
    const selectable = inLobby && (player.status === "Not active" || color === player.color);
    playerElements.push(
      <div
        data-selectable={selectable}
        data-selected={player.color === color}
        className="PlayerEntry"
        onClick={() => {
          inLobby && selectable && toggleSelected(player.color);
        }}
        key={`player-${player.color}`}
      >
        <div>
          <PlayerColor color={player.color} />
          <div className="Name">{playerName ? playerName : "Available"}</div>
          {playerName && !player.live && <div className="NoNetwork"></div>}
        </div>
        {playerName && player.live && (
          <MediaControl className={videoClass} peer={peers[playerName]} isSelf={player.color === color} />
        )}
        {!playerName && <div></div>}
      </div>
    );
  });

  const waiting = unselected.map((player) => {
    return (
      <div className={player === name ? "Self" : ""} key={player}>
        <div>{player}</div>
        <MediaControl className={"Small"} peer={peers[player]} isSelf={name === player} />
      </div>
    );
  });

  return (
    <Paper className={`PlayerList ${videoClass}`}>
      <MediaAgent setPeers={setPeers} />
      <List className="PlayerSelector">{playerElements}</List>
      {unselected && unselected.length !== 0 && (
        <div className="Unselected">
          <div>In lobby</div>
          <div>{waiting}</div>
        </div>
      )}
    </Paper>
  );
};

export { PlayerList };
