import { Dispatch, SetStateAction, useMemo, useState } from "react";
import { ReactSortable, ReactSortableProps } from "react-sortablejs";
import api, { baseUrl } from "./api";

interface Player {
  id: number;
  name: string;
  number: string | null;
}

type PlayerListProps = Partial<ReactSortableProps<any>> & {
  orderedList?: boolean;
};

function PlayerList(props: PlayerListProps) {
  return (
    <ReactSortable {...props} animation={200}>
      {props.list?.map((item, index) => (
        <div key={item.id} className="item">
          {props.orderedList ? index + 1 + ". " + item.name : item.name}
        </div>
      ))}
    </ReactSortable>
  );
}

interface SelectUserProps {
  user: Player[];
  setUser: Dispatch<SetStateAction<Player[]>>;
  players: Player[];
  setPlayers: Dispatch<SetStateAction<Player[]>>;
}

export function SelectUser({
  user,
  setUser,
  players,
  setPlayers,
}: SelectUserProps) {
  return (
    <>
      <div className="box user">
        {user.length < 1 ? (
          <>
            <span>your name?</span>
            <br /> <span className="grey hint">drag your name here</span>
          </>
        ) : (
          <>
            <span
              className="renew"
              onClick={() => {
                setUser([]);
              }}
            >
              {" ✕"}
            </span>
          </>
        )}
        <PlayerList
          list={user}
          setList={setUser}
          group={{
            name: "user-shared",
            put: function (to) {
              return to.el.children.length < 1;
            },
          }}
          className="dragbox"
        />
      </div>
      {user.length < 1 && (
        <div className="box one">
          <h2>🥏🏃</h2>
          <ReactSortable
            list={players}
            setList={setPlayers}
            group={{ name: "user-shared", pull: "clone" }}
            className="dragbox reservoir"
            animation={200}
          >
            {players.length < 1 ? (
              <span className="loader"></span>
            ) : (
              players.map((item, _) => (
                <div key={"extra" + item.id} className="extra-margin">
                  <div key={item.id} className="item">
                    {item.name}
                  </div>
                </div>
              ))
            )}
          </ReactSortable>
        </div>
      )}
    </>
  );
}

interface PlayerInfoProps {
  user: Player[];
  players: Player[];
}

export function Chemistry({ user, players }: PlayerInfoProps) {
  const index = players.indexOf(user[0]);
  var otherPlayers = players.slice();
  otherPlayers.splice(index, 1);
  const [playersLeft, setPlayersLeft] = useState<Player[]>([]);
  const [playersMiddle, setPlayersMiddle] = useState<Player[]>(otherPlayers);
  const [playersRight, setPlayersRight] = useState<Player[]>([]);

  const [dialog, setDialog] = useState("dialog");

  async function handleSubmit() {
    const dialog = document.querySelector("dialog[id='ChemistryDialog']");
    (dialog as HTMLDialogElement).showModal();
    if (user.length < 1) {
      setDialog("who are you?");
    } else {
      setDialog("sending...");
      let _user = user.map(({ name }) => name)[0];
      let left = playersLeft.map(({ name }) => name);
      let middle = playersMiddle.map(({ name }) => name);
      let right = playersRight.map(({ name }) => name);
      const data = { user: _user, hate: left, undecided: middle, love: right };
      const response = await api("chemistry", data);
      response.ok ? setDialog("success!") : setDialog("try sending again");
    }
  }

  return (
    <>
      <div className="container">
        <div className="box three">
          <h2>😬</h2>
          {playersLeft.length < 1 && (
            <span className="grey hint">
              drag people here that you'd rather not play with from worst to ...
              ok
            </span>
          )}
          <PlayerList
            list={playersLeft}
            setList={setPlayersLeft}
            group={"shared"}
            className="dragbox"
            orderedList
          />
        </div>
        <div className="box three">
          <h2>🤷</h2>
          <PlayerList
            list={playersMiddle}
            setList={setPlayersMiddle}
            group={"shared"}
            className="middle dragbox"
          />
        </div>
        <div className="box three">
          <h2>😍</h2>
          {playersRight.length < 1 && (
            <span className="grey hint">
              drag people here that you love playing with from best to ... ok
            </span>
          )}
          <PlayerList
            list={playersRight}
            setList={setPlayersRight}
            group={"shared"}
            className="dragbox"
            orderedList
          />
        </div>
      </div>

      <button className="submit" onClick={() => handleSubmit()}>
        💾 <span className="submit_text">submit</span>
      </button>
      <dialog
        id="ChemistryDialog"
        onClick={(event) => {
          event.currentTarget.close();
        }}
      >
        {dialog}
      </dialog>
    </>
  );
}

export function MVP({ user, players }: PlayerInfoProps) {
  const [availablePlayers, setAvailablePlayers] = useState<Player[]>(players);
  const [rankedPlayers, setRankedPlayers] = useState<Player[]>([]);

  const [dialog, setDialog] = useState("dialog");

  async function handleSubmit() {
    const dialog = document.querySelector("dialog[id='MVPDialog']");
    (dialog as HTMLDialogElement).showModal();
    if (user.length < 1) {
      setDialog("who are you?");
    } else {
      setDialog("sending...");
      let _user = user.map(({ name }) => name)[0];
      let mvps = rankedPlayers.map(({ name }) => name);
      const data = { user: _user, mvps: mvps };
      const response = await api("mvps", data);
      response.ok ? setDialog("success!") : setDialog("try sending again");
    }
  }

  return (
    <>
      <div className="container">
        <div className="box two">
          <h2>🥏🏃</h2>
          {availablePlayers.length < 1 && (
            <span className="grey hint">all sorted 👍</span>
          )}
          <PlayerList
            list={availablePlayers}
            setList={setAvailablePlayers}
            group={{
              name: "mvp-shared",
              pull: function (to) {
                return to.el.classList.contains("putclone") ? "clone" : true;
              },
            }}
            className="dragbox"
          />
        </div>
        <div className="box two">
          <h1>🏆</h1>
          {rankedPlayers.length < 1 && (
            <span className="grey hint">
              carefully place as many of the <i>Most Valuable Players</i>{" "}
              (according to your humble opinion) in this box
            </span>
          )}
          <PlayerList
            list={rankedPlayers}
            setList={setRankedPlayers}
            group={{
              name: "mvp-shared",
              pull: function (to) {
                return to.el.classList.contains("putclone") ? "clone" : true;
              },
            }}
            className="dragbox"
            orderedList
          />
        </div>
      </div>

      <button className="submit" onClick={() => handleSubmit()}>
        💾 <span className="submit_text">submit</span>
      </button>
      <dialog
        id="MVPDialog"
        onClick={(event) => {
          event.currentTarget.close();
        }}
      >
        {dialog}
      </dialog>
    </>
  );
}

function openPage(pageName: string, color: string) {
  // Hide all elements with class="tabcontent" by default */
  var i, tabcontent, tablinks;
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    (tabcontent[i] as HTMLElement).style.display = "none";
  }
  // Remove the background color of all tablinks/buttons
  tablinks = document.getElementsByClassName("tablink");
  for (i = 0; i < tablinks.length; i++) {
    let button = tablinks[i] as HTMLElement;
    button.style.opacity = "50%";
  }
  // Show the specific tab content
  (document.getElementById(pageName) as HTMLElement).style.display = "block";
  // Add the specific color to the button used to open the tab content
  let activeButton = document.getElementById(
    pageName + "Button"
  ) as HTMLElement;
  activeButton.style.fontWeight = "bold";
  activeButton.style.opacity = "100%";
  document.body.style.backgroundColor = color;
}

export default function Rankings() {
  const [user, setUser] = useState<Player[]>([]);
  const [players, setPlayers] = useState<Player[]>([]);

  async function loadPlayers() {
    const response = await fetch(`${baseUrl}player/list`, {
      method: "GET",
    });
    const data = await response.json();
    setPlayers(data as Player[]);
  }

  useMemo(() => {
    loadPlayers();
  }, []);

  return (
    <>
      <SelectUser {...{ user, setUser, players, setPlayers }} />
      {user.length === 1 && (
        <>
          <div className="container navbar">
            <button
              className="tablink"
              id="ChemistryButton"
              onClick={() => openPage("Chemistry", "aliceblue")}
            >
              🧪 Chemistry
            </button>
            <button
              className="tablink"
              id="MVPButton"
              onClick={() => openPage("MVP", "aliceblue")}
            >
              🏆 MVP
            </button>
          </div>

          <div id="Chemistry" className="tabcontent">
            <Chemistry {...{ user, players }} />
          </div>
          <div id="MVP" className="tabcontent">
            <MVP {...{ user, players }} />
          </div>
        </>
      )}
    </>
  );
}
