import React, { useContext, useState, useMemo, useRef, useEffect } from "react";
import equal from "fast-deep-equal";

import { Resource } from "./Resource";
import { Placard } from "./Placard";
import { GlobalContext } from "./GlobalContext";
import { assetsPath } from "./Common";
import "./Hand.css";

/* eslint-disable @typescript-eslint/no-explicit-any */

interface DevelopmentProps {
  type: string;
  card: any;
  onClick: () => void;
}

const Development: React.FC<DevelopmentProps> = ({ type, card, onClick }) => {
  return (
    <div
      className={`Development ${card.played ? "Selected" : ""}`}
      onClick={onClick}
      style={{
        backgroundImage: `url(${assetsPath}/gfx/card-${type}.png)`,
      }}
    />
  );
};

interface HandProps {
  buildActive: boolean;
  setBuildActive: (active: boolean) => void;
  setCardActive: (card: any) => void;
}

const Hand: React.FC<HandProps> = ({ buildActive, setBuildActive, setCardActive }) => {
  const { ws, sendJsonMessage } = useContext(GlobalContext);
  const [priv, setPriv] = useState<any>(undefined);
  const [color, setColor] = useState<string | undefined>(undefined);
  const [turn, setTurn] = useState<any>(undefined);
  const [longestRoad, setLongestRoad] = useState<string | undefined>(undefined);
  const [largestArmy, setLargestArmy] = useState<string | undefined>(undefined);
  const [development, setDevelopment] = useState<React.ReactElement[]>([]);
  const [mostPorts, setMostPorts] = useState<string | undefined>(undefined);
  const [mostDeveloped, setMostDeveloped] = useState<string | undefined>(undefined);
  const [selected, setSelected] = useState<number>(0);

  const fields = useMemo(
    () => ["private", "turn", "color", "longestRoad", "largestArmy", "mostPorts", "mostDeveloped"],
    []
  );
  const onWsMessage = (event: MessageEvent) => {
    const data = JSON.parse(event.data);
    switch (data.type) {
      case "game-update":
        console.log(`hand - game-update: `, data.update);
        if ("private" in data.update && !equal(priv, data.update.private)) {
          setPriv(data.update.private);
        }
        if ("turn" in data.update && !equal(turn, data.update.turn)) {
          setTurn(data.update.turn);
        }
        if ("color" in data.update && color !== data.update.color) {
          setColor(data.update.color);
        }
        if ("longestRoad" in data.update && longestRoad !== data.update.longestRoad) {
          setLongestRoad(data.update.longestRoad);
        }
        if ("largestArmy" in data.update && largestArmy !== data.update.largestArmy) {
          setLargestArmy(data.update.largestArmy);
        }
        if ("mostDeveloped" in data.update && data.update.mostDeveloped !== mostDeveloped) {
          setMostDeveloped(data.update.mostDeveloped);
        }
        if ("mostPorts" in data.update && data.update.mostPorts !== mostPorts) {
          setMostPorts(data.update.mostPorts);
        }
        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,
    });
  }, [sendJsonMessage, fields]);

  useEffect(() => {
    if (!priv) {
      return;
    }

    const cardClicked = (card: any) => {
      setCardActive(card);
    };

    const stacks: { [key: string]: any[] } = {};
    priv.development.forEach((card: any) =>
      card.type in stacks ? stacks[card.type].push(card) : (stacks[card.type] = [card])
    );

    const development: React.ReactElement[] = [];
    for (const type in stacks) {
      const cards = stacks[type]
        .sort((A: any, B: any) => {
          if (A.played) {
            return -1;
          }
          if (B.played) {
            return +1;
          }
          return B.turn - A.turn; /* Put playable cards on top */
        })
        .map((card: any) => (
          <Development
            onClick={() => cardClicked(card)}
            card={card}
            key={`${type}-${card.card}`}
            type={`${type}-${card.card}`}
          />
        ));
      development.push(
        <div key={type} className="Stack">
          {cards}
        </div>
      );
    }
    setDevelopment(development);
  }, [priv, setDevelopment, setCardActive]);

  useEffect(() => {
    const count = document.querySelectorAll(".Hand .CardGroup .Resource.Selected");
    if (count.length !== selected) {
      setSelected(count.length);
    }
  }, [setSelected, selected, turn]);

  if (!priv) {
    return <></>;
  }

  const cardSelected = () => {
    const count = document.querySelectorAll(".Hand .CardGroup .Resource.Selected");
    setSelected(count.length);
  };

  return (
    <div className="Hand">
      {
        <div className="CardsSelected" style={selected === 0 ? { display: "none" } : {}}>
          {selected} cards selected
        </div>
      }
      <div className="CardGroup">
        <Resource type="wood" count={priv.wood} onClick={cardSelected} />
        <Resource type="wheat" count={priv.wheat} onClick={cardSelected} />
        <Resource type="stone" count={priv.stone} onClick={cardSelected} />
        <Resource type="brick" count={priv.brick} onClick={cardSelected} />
        <Resource type="sheep" count={priv.sheep} onClick={cardSelected} />
      </div>
      <div className="CardGroup">{development}</div>
      {mostDeveloped && mostDeveloped === color && <Placard type="most-developed" />}
      {mostPorts && mostPorts === color && <Placard type="port-of-call" />}
      {longestRoad && longestRoad === color && <Placard type="longest-road" />}
      {largestArmy && largestArmy === color && <Placard type="largest-army" />}
      <Placard className="BuildCard" {...{ buildActive, setBuildActive }} disabled={!turn || !turn.roll} type={color} />
    </div>
  );
};

export { Hand };
