import { useRouter } from "next/router";
import { useContext, useEffect, useState } from "react";
import {
  AiFillEyeInvisible,
  AiFillUnlock,
  AiOutlineCheck,
  AiOutlineClose,
} from "react-icons/ai";
import ReconnectingWebSocket from "reconnecting-websocket";
import { AlertType, useAlert } from "../../context/alert.context.js";
import { useWebsocketContext } from "../../context/websocket.context.js";
import {
  changeRoomName,
  deleteParcours,
  deleteRoom,
  getRoom,
  togglePublicResult,
  toggleRoomLock,
} from "../../requests/requests.room.js";
import styles from "../../styles/room/roomView.module.scss";
import { isBrowser, isEmpty, parseClassName } from "../../utils/utils.js";
import Layout from "../Layout.js";
import { BsCheckLg } from "react-icons/bs";
import { BiTrash } from "react-icons/bi";
import { MdRefresh, MdExitToApp, MdEdit } from "react-icons/md";
import { IoMdExit, IoMdReturnLeft } from "react-icons/io";
import { BiEdit, BiUndo } from "react-icons/bi";
import { notificationService } from "../../services/notification.service.js";
import { AiFillLock, AiFillEye } from "react-icons/ai";
export default function RoomView({ user, id_code }) {
  const [dataRoom, setDataRoom] = useState();

  useEffect(() => {
    if (user != undefined && (dataRoom == undefined || isEmpty(dataRoom))) {
      getRoom(id_code, user.clientId)
        .then((res) => {
          setDataRoom(res.room);
        })
        .catch((err) => {
          if (err.response.data.code == 111) {
            setJoined(false);
            router.push({ pathname: "/room/join" });
          }
        });
    }
  }, [user, dataRoom]);

  const router = useRouter();
  const {
    ws,
    send,
    connect,
    addMessageHandler,
    removeMessageHandler,
    isConnected,
    disconnect,
  } = useWebsocketContext();

  useEffect(() => {
    let handler = (e) => {
      let data = JSON.parse(e.data);
      let type = data.type;
      switch (type) {
        case "joined": {
          if (dataRoom) {
            let nick = data.nick;
            let owner = data.owner;
            let online = data.online;
            let code = data.code;

            let oldParticipants = dataRoom.participants;
            let oldWaiters = dataRoom.waiters;
            setDataRoom({
              ...dataRoom,
              participants: [
                ...oldParticipants,
                { nick: nick, owner: owner, online: online, code: code },
              ],
              waiters: [...oldWaiters.filter((w) => w.code != code)],
            });
          }
          break;
        }
        case "disconnect_participant": {
          if (dataRoom) {
            let oldParticipants = dataRoom.participants;
            let nick = data.nick;
            setDataRoom({
              ...dataRoom,
              participants: [
                ...oldParticipants.map((p) => {
                  if (p.nick == nick) {
                    return { ...p, online: false };
                  }
                  return p;
                }),
              ],
            });
          }
          break;
        }
        case "reconnect_participant": {
          if (dataRoom) {
            let oldParticipants = dataRoom.participants;
            let nick = data.nick;
            let participant = oldParticipants.filter((p) => p.nick == nick)[0];
            participant.online = true;
            setDataRoom({
              ...dataRoom,
              participants: [
                ...oldParticipants.filter((p) => p.nick != nick),
                participant,
              ],
            });
          }
          break;
        }
        case "add_waiter": {
          if (dataRoom) {
            let nick = data.nick;
            let code = data.code;
            let status = data.status;

            let oldWaiters = dataRoom.waiters;
            setDataRoom({
              ...dataRoom,
              waiters: [
                ...oldWaiters,
                { nick: nick, code: code, status: status },
              ],
            });
          }
          break;
        }
        case "del_waiter": {
          if (dataRoom) {
            let code = data.code;

            let oldWaiters = dataRoom.waiters;
            setDataRoom({
              ...dataRoom,
              waiters: [...oldWaiters.filter((w) => w.code != code)],
            });
          }
          break;
        }
        case "banned": {
          if (dataRoom) {
            let nick = data.nick;
            let code = data.code;

            if (user.user.code != code) {
              let oldParticipants = dataRoom.participants;
              let oldParcours = dataRoom.parcours;
              setDataRoom({
                ...dataRoom,
                participants: [
                  ...oldParticipants.filter((p) => p.nick != nick),
                ],
              });
            } else if (user.user.code == code) {
              router.push({ pathname: "/room/join" });
            }
          }
          break;
        }

        case "add_parcours": {
          if (dataRoom) {
            let new_parcours = data.parcours;
            let id_code = dataRoom.id_code;
            let oldParcours = dataRoom.parcours;
            setDataRoom({
              ...dataRoom,
              parcours: [...oldParcours, new_parcours],
            });
          }
          break;
        }
        case "delete_parcours": {
          if (dataRoom) {
            setDataRoom({
              ...dataRoom,
              parcours: [
                ...dataRoom.parcours.filter((p) => p.id_code != data.id_code),
              ],
            });
          }
          break;
        }
        case "edit_parcours": {
          if (dataRoom) {
            let new_parcours = data.parcours;
            let id_code = dataRoom.id_code;
            let oldParcours = dataRoom.parcours;

            setDataRoom({
              ...dataRoom,
              parcours: [
                ...oldParcours.map((p) => {
                  if (p.id_code == new_parcours.id_code) {
                    return new_parcours;
                  }
                  return p;
                }),
              ],
            });
          }
          break;
        }

        default:
          break;
      }
    };
    addMessageHandler(handler);
    return () => {
      removeMessageHandler(handler);
    };
  }, [dataRoom]);

  const alert = useAlert();
  const [edit, setEdit] = useState(null);
  useEffect(() => {
    window.addEventListener("click", () => {
      if (edit) {
        setEdit(null);
      }
    });
  });

  useEffect(() => {
    return () => {
      disconnect();
    };
  }, []);

  return (
    <Layout page={dataRoom && dataRoom.name ? dataRoom.name : "..."}>
      {isEmpty(dataRoom) && <><span className='loader'></span></>}
      {dataRoom && !isEmpty(dataRoom) && (
        <div className={styles["full-container"]}>
          <div className={styles["head"]}>
            {(edit === null || edit == false) && edit != "" && (
              <h1
                onClick={() => {
                  if (navigator.clipboard) {
                    navigator.clipboard.write(router.asPath).then((res) => {
                      notificationService.success("Lien", "Lien copié !");
                    });
                  }
                }}
              >
                <p
                  className={styles.title}
                  onDoubleClick={(e) => {
                    if (user.user.owner) {
                      setEdit(dataRoom.name);
                    }
                  }}
                  title={"Double click pour modifier"}
                >
                  {dataRoom.name}
                </p>
                <span>#{dataRoom.id_code}</span>
              </h1>
            )}
            {((edit !== null && edit != false) || edit == "") && (
              <div
                className={styles["title-form"]}
                onClick={(e) => {
                  e.stopPropagation();
                }}
              >
                <input
                  type="text"
                  className="exo-input"
                  value={edit}
                  onChange={(e) => {
                    if (e.target.value == "") {
                      setEdit("");
                    } else {
                      setEdit(e.target.value);
                    }
                  }}
                  onKeyDown={(e) => {
                    if (e.code == "Enter") {
                      changeRoomName({
                        id_code: dataRoom.id_code,
                        clientId: sessionStorage.getItem("clientId"),
                        name: edit,
                      })
                        .then((res) => {
                          setDataRoom({ ...dataRoom, name: res.name });
                          setEdit(null);
                        })
                        .catch((err) => {
                          notificationService.error(
                            "Erreur",
                            "Erreur lors de la modification"
                          );
                        });
                    } else if (e.code == "Escape") {
                      setEdit(null);
                    }
                  }}
                  autoFocus={true}
                />
              </div>
            )}

            <div className={styles["icons-container"]}>
              <MdRefresh
                title={"Actualiser"}
                onClick={() => {
                  setDataRoom();
                  if (!isConnected) {
                    connect("/ws/room/" + id_code);
                  }
                }}
                className={styles.refresh}
              />
              <BiUndo
                onClick={() => {
                  disconnect();
                  router.push("/room", undefined, {shallow:true});
                }}
                className={styles.exit}
                title={"Retour à l'acceuil"}
              />
              {!user.user.owner && (
                <IoMdExit
                  className={styles.exit}
                  title={"Quitter"}
                  onClick={() => {
                    alert.alert({
                      title: "Êtes-vous sûr ?",
                      active: true,
                      message: `Voulez vous quitter le salle ? Cela effacera toute vos données sur les parcours`,
                      type: AlertType.Warning,
                      validate: () => {
                        send({
                          data: {
                            type: "leave",
                            code: user.user.code,
                            nick: user.user.nick,
                            clientId: sessionStorage.getItem("clientId"),
                          },
                        });
                      },
                    });
                  }}
                />
              )}
              {user.user.owner && (
                <BiTrash
                  className={styles.exit}
                  onClick={() => {
                    alert.alert({
                      title: "Êtes-vous sûr ?",
                      active: true,
                      message: `Voulez vous supprimer le salle ?`,
                      type: AlertType.Warning,
                      validate: () => {
                        deleteRoom({
                          clientId:
                            isBrowser && sessionStorage.getItem("clientId"),
                          id_code,
                        })
                          .then((res) => {
                            router.push("/room/", undefined, { shallow: true });
                            notificationService.success(
                              "Suppression",
                              `Salle "${dataRoom.name}" supprimée`,
                              { keepAfterRouteChange: true }
                            );
                          })
                          .catch((err) => {
                            notificationService.error(
                              "Suppression",
                              `Erreur lors de la suppression de la salle "${dataRoom.name}"`,
                              { keepAfterRouteChange: true }
                            );
                          });
                      },
                    });
                  }}
                />
              )}
            </div>
          </div>

          <div className={styles["parcours-container"]}>
            <div className={styles["cat-title"]}>
              <p className={styles["parcours-title"]}>
                {" "}
                {user.user.owner &&
                  (dataRoom.public_result ? (
                    <AiFillEye
                      onClick={() => {
                        togglePublicResult({
                          id_code: dataRoom.id_code,
                          clientId: sessionStorage.getItem("clientId"),
                        })
                          .then((res) => {
                            setDataRoom({
                              ...dataRoom,
                              public_result: res.private,
                            });
                          })
                          .catch((err) => {
                            notificationService.error(
                              "Erreur",
                              "Erreur lors de la modification"
                            );
                          });
                      }}
                      title="Appuyer pour rendre les résultats privé (les membres ne pourront voir que leurs propres résultats)"
                    />
                  ) : (
                    <AiFillEyeInvisible
                      onClick={() => {
                        togglePublicResult({
                          id_code: dataRoom.id_code,
                          clientId: sessionStorage.getItem("clientId"),
                        })
                          .then((res) => {
                            setDataRoom({
                              ...dataRoom,
                              public_result: res.private,
                            });
                          })
                          .catch((err) => {
                            notificationService.error(
                              "Erreur",
                              "Erreur lors de la modification"
                            );
                          });
                      }}
                      title="Appuyer pour rendre les résultats public (les membres pourront voir les résultats des autres)"
                    />
                  ))}
                Parcours{" "}
              </p>
              {user.user.owner && (
                <button
                  className="exo-btn"
                  onClick={() => {
                    router.push(
                      {
                        pathname: `/room/${dataRoom.id_code}/new_parcours`,
                      },
                      undefined,
                      { shallow: true }
                    );
                  }}
                >
                  Nouveau
                </button>
              )}
            </div>
            {dataRoom.parcours.map((p) => {
              return (
                <div
                  className={styles["parcours-item"]}
                  onClick={() => {
                    router.push(
                      {
                        pathname: `/room/${dataRoom.id_code}/${p.id_code}`,
                      },
                      undefined,
                      { shallow: true }
                    );
                  }}
                >
                  <div>
                    {p.is_validate && <BsCheckLg />}
                    <p>{p.name}</p>{" "}
                  </div>

                  {user.user.owner == true && (
                    <BiTrash
                      onClick={(e) => {
                        e.stopPropagation();
                        console.log("CLICK SVG");
                        alert.alert({
                          title: "Êtes-vous sûr ?",
                          active: true,
                          message: `Voulez vous supprimer le parcours "${p.name}"`,
                          type: AlertType.Warning,
                          validate: () => {
                            deleteParcours({
                              id_code: p.id_code,
                              code: user.user.code,
                            }).then((r) => {
                              setDataRoom({
                                ...dataRoom,
                                parcours: [
                                  ...dataRoom.parcours.filter(
                                    (pp) => pp.id_code != r.id_code
                                  ),
                                ],
                              });
                            });
                          },
                        });
                      }}
                    />
                  )}
                </div>
              );
            })}
            {dataRoom.parcours.length == 0 && (
              <p className={styles["no-parcours"]}>Aucun parcours</p>
            )}
          </div>
          <div className={styles["participants-container"]}>
            <div className={styles["cat-title"]}>
              Participants{" "}
              {user.user.owner &&
                (dataRoom.private ? (
                  <AiFillLock
                    className={styles.lock}
                    title={"Rendre la salle publique"}
                    onClick={() => {
                      toggleRoomLock({
                        id_code: dataRoom.id_code,
                        clientId: sessionStorage.getItem("clientId"),
                      })
                        .then((res) => {
                          setDataRoom({ ...dataRoom, private: res.private });
                        })
                        .catch((err) => {
                          notificationService.error(
                            "Erreur",
                            "Erreur lors de la modification"
                          );
                        });
                    }}
                  />
                ) : (
                  <AiFillUnlock
                    className={styles.lock}
                    title={"Rendre la salle privée"}
                    onClick={() => {
                      toggleRoomLock({
                        id_code: dataRoom.id_code,
                        clientId: sessionStorage.getItem("clientId"),
                      })
                        .then((res) => {
                          setDataRoom({ ...dataRoom, private: res.private });
                        })
                        .catch((err) => {
                          notificationService.error(
                            "Erreur",
                            "Erreur lors de la modification"
                          );
                        });
                    }}
                  />
                ))}
            </div>
            <p className={parseClassName([styles.owner, styles.partCat])}>
              En ligne :
            </p>
            {dataRoom.participants
              .filter((p) => p.online)
              .map((p) => {
                return (
                  <p
                    className={
                      p.nick == user.user.nick ? styles["owner"] : undefined
                    }
                  >
                    <span
                      onClick={() => {
                        if (user.user.owner && p.nick != user.user.nick) {
                          alert.alert({
                            title: "Êtes-vous sûr ?",
                            active: true,
                            message: `Vous aller bannir ${p.nick}`,
                            type: AlertType.Warning,
                            validate: () => {
                              send({
                                data: {
                                  type: "ban",
                                  code: p.code,
                                  nick: p.nick,
                                  status: p.status,
                                },
                              });
                            },
                          });
                        }
                      }}
                      title="Bannir"
                      className={parseClassName([
                        user.user.owner ? styles["nick"] : undefined,
                        p.owner || user.user.nick == p.nick
                          ? styles["isOwner"]
                          : undefined,
                      ])}
                    >
                      {p.nick}
                    </span>
                    {p.nick == user.user.nick &&
                      isBrowser &&
                      localStorage.getItem("token") == null && (
                        <span className={styles["code"]}>
                          #{user.user.code}
                        </span>
                      )}

                    {p.owner == true && (
                      <span className={styles["admin"]}>Administrateur</span>
                    )}
                    {user.user.owner &&
                      p.nick != user.user.nick &&
                      p.code.length == 6 && (
                        <span className={styles["code"]}>#{p.code}</span>
                      )}
                  </p>
                );
              })}
            <p className={parseClassName([styles.owner, styles.partCat])}>
              Hors-ligne :
            </p>
            {dataRoom.participants
              .filter((p) => !p.online)
              .map((p) => {
                return (
                  <p
                    className={
                      p.nick == user.user.nick ? styles["owner"] : undefined
                    }
                  >
                    <span
                      onClick={() => {
                        if (user.user.owner && p.nick != user.user.nick) {
                          alert.alert({
                            title: "Êtes-vous sûr ?",
                            active: true,
                            message: `Vous aller bannir ${p.nick}`,
                            type: AlertType.Warning,
                            validate: () => {
                              send({
                                data: {
                                  type: "ban",
                                  code: p.code,
                                  nick: p.nick,
                                  status: p.status,
                                },
                              });
                            },
                          });
                        }
                      }}
                      title="Bannir"
                      className={parseClassName([
                        user.user.owner ? styles["nick"] : undefined,
                        p.owner || user.user.nick == p.nick
                          ? styles["isOwner"]
                          : undefined,
                      ])}
                    >
                      {p.nick}
                    </span>
                    {p.nick == user.user.nick &&
                      isBrowser &&
                      localStorage.getItem("token") == null && (
                        <span className={styles["code"]}>
                          #{user.user.code}
                        </span>
                      )}

                    {p.owner == true && (
                      <span className={styles["admin"]}>Administrateur</span>
                    )}
                    {user.user.owner &&
                      p.nick != user.user.nick &&
                      p.code.length == 6 && (
                        <span className={styles["code"]}>#{p.code}</span>
                      )}
                  </p>
                );
              })}
            {dataRoom.waiters.length != 0 && (
              <>
                <p className={parseClassName([styles.owner, styles.partCat])}>
                  En attente :
                </p>
                {dataRoom.waiters.map((p) => {
                  
                  return (
                    <p>
                      {p.nick}
                      <AiOutlineCheck
                        className={styles["accept"]}
                        onClick={() => {
                          send({
                            data: {
                              type: "acceptParticipant",
                              code: p.code,
                              nick: p.nick,
                              status: p.status,
                            },
                          });
                          setDataRoom({
                            ...dataRoom,
                            waiters: dataRoom.waiters.filter(
                              (w) => w.code != p.code
                            ),
                          });
                        }}
                      />

                      <AiOutlineClose
                        className={styles["refuse"]}
                        onClick={() => {
                          send({
                            data: { type: "refusedParticipant", code: p.code },
                          });
                          setDataRoom({
                            ...dataRoom,
                            waiters: dataRoom.waiters.filter(
                              (w) => w.code != p.code
                            ),
                          });
                        }}
                      />
                    </p>
                  );
                })}{" "}
              </>
            )}
          </div>
        </div>
      )}
    </Layout>
  );
}
