'use client'
import { useState, useEffect, useRef } from 'react'
import { Socket, io } from "socket.io-client"
import { getRandomQuestion, playModes } from "./questions"
import { IconCrown, IconPhotoUp, IconCamera } from "@tabler/icons-react"
import { defaultAvatarImage } from '../avatarImage'
import { resizeBase64Image, getBase64OfImage } from '../utils'
import ModeCard from '@/components/modeCard'
import EditCustomQuestions from '@/components/editCustomQuestions'
import Webcam from 'react-webcam'
import { PlayerChoice } from '@/utils/types'

interface roomProps {
  params: {
    id: string;
  };
}

export default function GameRoom({ params }: roomProps) {
  const [isConnected, setIsConnected] = useState<boolean>(false)
  const [forceUpdate, setForceUpdate] = useState<number>(0)

  const [role, setRole] = useState<string|null>("")
  const [name, setName] = useState<string|null>("")
  const [avatar, setAvatar] = useState<string|null>(defaultAvatarImage)
  const [browserId, setBrowserId] = useState<string|null>("")

  const [gameStarted, setGameStarted] = useState<boolean|null>(false)
  const [gameEnded, setGameEnded] = useState<boolean|null>(false)
  const [questionReply, setQuestionReply] = useState<any>({})
  const [questionDisplayed, setQuestionDisplayed] = useState<any|null>({})
  const [possibleChoice, setPossibleChoice] = useState<PlayerChoice[]>([])
  const [totalVotes, setTotalVotes] = useState<number>(0)
  const [choice, setChoice] = useState<string|null>("")
  const [countdown, setCountdown] = useState<number>(0)
  const [players, setPlayers] = useState<any[]>([])
  const [questionNbr, setQuestionNbr] = useState<number>(0)
  const [questionAlreadyDone, setQuestionAlreadyDone] = useState<any[]>([])
  const [selectedMode, setSelectedMode] = useState<number>(0)
  const [customQuestions, setCustomQuestions] = useState<any[]|null>([])

  const socketRef = useRef<Socket>() // eslint-disable-line
  const inputPhotoRef = useRef<any>()
  const editCustomQuestionsRef = useRef<any>()
  const duration = 15
  const questionLimit = 10

  const { id } = params
  const roomNameDisplay = id.substring(0,3) + " " + id.substring(3,6)

  useEffect(() => {
        const localName = localStorage.getItem('name')
        setName(localName)
        const localAvatar = localStorage.getItem('avatar')
        setAvatar(localAvatar)
        const localBrowserId = localStorage.getItem("browserId")
        setBrowserId(localBrowserId)
        const localCustomQuestionsString = localStorage.getItem("customQuestions")
        const localCustomQuestions = JSON.parse(localCustomQuestionsString != null ? localCustomQuestionsString : "")
        setCustomQuestions(localCustomQuestions == null ? [] : localCustomQuestions)

        // Listen for incoming setMessages
        socketRef.current = io("ws://localhost:3000");

        socketRef.current!.on("connect", () => {
          setIsConnected(true)
          socketRef.current!.emit('room_connect', {id: id, name: localName, avatar: localAvatar, browserId: localBrowserId})
        });

        socketRef.current!.on("new_player", (params) => {
          setPlayers(oldPlayers => [...oldPlayers, params])
        })

        socketRef.current!.on("start_game", (params) => {
          setQuestionNbr(params.questionNbr)
          setGameStarted(true)
          setQuestionDisplayed(params.question)
          setPossibleChoice(params.possibleChoice)
          setCountdown(params.duration)
        })

        socketRef.current!.on("next_question", (params) => {
          setQuestionNbr(oldQ => oldQ + 1)
          setChoice("")
          setQuestionDisplayed(params.question)
          setPossibleChoice(params.possibleChoice)
          setCountdown(params.duration)
          setTotalVotes(0)
        })

        socketRef.current!.on("question_reply", (params) => {
          console.log(params)
          setQuestionReply(params)
        })

        socketRef.current!.on("reset_game", (params) => {
          setGameStarted(false)
          setCountdown(0)
          setPossibleChoice([])
          setQuestionDisplayed("")
          setChoice("")
          setQuestionNbr(0)
          setTotalVotes(0)
        })

        socketRef.current!.on("room_joined", (params) => {
          setPlayers(params.room_users)
          setRole(params.role)
        })

        // Clean up the socket connection on unmount
        return () => {
            socketRef.current!.disconnect();
        };
    }, []);

  function forceUpdateFunc(){
    setForceUpdate(fu => fu + 1)
  }

  useEffect(() => {
        const eventListener = (params: any) => {
          setTotalVotes(oldTotal => oldTotal += 1)
          console.log(params)
          let temp_possibleChoice = possibleChoice
          temp_possibleChoice!.forEach((playerChoice) => {
            if(playerChoice.name == params.choice) {
              playerChoice.nbrVotes += 1
            }
          })
          forceUpdateFunc()
        };
        socketRef.current!.on("player_choice", eventListener)
        return () => {socketRef.current!.off("player_choice", eventListener)}
  }, [possibleChoice])

  useEffect(() => {
    countdown > 0 && setTimeout(() => setCountdown(countdown - 1), 1000);
  }, [countdown]);

  function getPossibleChoice() {
    let choice1 = Math.floor(Math.random() * players.length)
    console.log(players.length)
    let choice2 = Math.floor(Math.random() * players.length)
    console.log(choice2)
    while(choice2 == choice1){
      choice2 = Math.floor(Math.random() * players.length)
    }
    let playerChoice1 = players[choice1]
    playerChoice1.nbrVotes = 0
    let playerChoice2 = players[choice2]
    playerChoice2.nbrVotes = 0
    return [playerChoice1, playerChoice2]
  }

  function startGame() {
    let possibleChoice = getPossibleChoice()
    let questionObj = getRandomQuestion(playModes[selectedMode], [], customQuestions)
    let question = questionObj.question
    setQuestionAlreadyDone(questionObj.alreadyDone)
    socketRef.current!.emit("start_game", {roomId: id, question: question, possibleChoice: possibleChoice, duration: duration})
    setCountdown(duration)
    setPossibleChoice(possibleChoice)
    setQuestionDisplayed(question)
    setGameStarted(true)
    setQuestionNbr(oldQ => oldQ + 1)
  }

  function nextQuestion() {
    let possibleChoice = getPossibleChoice()
    let questionObj = getRandomQuestion(playModes[selectedMode],questionAlreadyDone, customQuestions)
    let question = questionObj.question
    setQuestionAlreadyDone(questionObj.alreadyDone)
    socketRef.current!.emit("next_question", {roomId: id, question: question, possibleChoice: possibleChoice, duration: duration})
    setCountdown(duration)
    setPossibleChoice(possibleChoice)
    setQuestionDisplayed(question)
    setChoice("")
    setQuestionNbr(oldQ => oldQ + 1)
    setTotalVotes(0)
  }

  function resetGame() {
    socketRef.current!.emit("reset_game", {roomId: id})
    setGameStarted(false)
    setCountdown(0)
    setPossibleChoice([])
    setQuestionDisplayed("")
    setChoice("")
    setQuestionNbr(0)
    setTotalVotes(0)
  }

  function setAndSendChoice(playerName: any) {
    setChoice(playerName)
    setTotalVotes(oldTotal => oldTotal += 1)
    let temp_possibleChoice = possibleChoice
    temp_possibleChoice.forEach((playerChoice) => {
      if(playerChoice.name == playerName) {
        playerChoice.nbrVotes += 1
      }
    })
    setPossibleChoice(temp_possibleChoice)
    socketRef.current!.emit("player_choice", {roomId: id, choice: playerName, player: name})
  }

  function setAndSendPhoto(){
    getBase64OfImage(inputPhotoRef.current!.files[0], (data: any) => resizeBase64Image(data).then((data: any) =>{
      setQuestionReply({photo: data})
      socketRef.current!.emit("question_reply", { roomId: id, data:{photo: data}})
    }))
  }

  function setAndSaveCustomQuestions(data: any){
    setCustomQuestions(data)
    localStorage.setItem("customQuestions", JSON.stringify(data))
  }

  return (
    <main  data-theme="cupcake" className="flex min-h-screen flex-col items-center space-y-16 p-4">
      { !gameStarted && 
        <>
          <div className="flex flex-col">
            <h1 className="text-6xl">{roomNameDisplay}</h1>
          </div>
          <div className="flex flex-col space-y-12">
            { !isConnected &&
              <p>Connecting to room...</p>
            }
            { isConnected &&
              <>
              { role == "owner" &&
                <>
                <div className="flex flex-col space-y-4">
                  <h2 className="text-2xl font-bold">Choose game mode</h2>
                  <div className="grid grid-cols-3 place-items-center">
                    { playModes.map((mode, index) => {
                      return(
                        <ModeCard key={index} mode={mode} onChange={() => setSelectedMode(index)} selected={selectedMode === index} />
                      )
                    })}
                  </div>
                </div>
                { playModes[selectedMode].name == "Custom" &&
                  <>
                    <EditCustomQuestions dataRef={editCustomQuestionsRef} questionList={customQuestions} setQuestions={(data: any) => setAndSaveCustomQuestions(data)} />
                    <button className="btn btn-primary" onClick={() => editCustomQuestionsRef.current!.showModal()}>Edit questions...</button>
                  </>
                }
                </>
              }
              <div className="flex flex-col space-y-4">
               <h2 className="text-2xl font-bold">Players</h2> 
              { players.length == 0 &&
                <p>Waiting for players to join...</p>
              }
              { players.length > 0 &&
                <div className="flex flex-col space-y-16">
                  <div className="grid grid-cols-3 gap-4 place-items-center">
                    { players.map((player) => {
                      return (
                        <>
                          <div className="flex flex-col items-center">
                            <div className="avatar indicator">
                              {player.role == "owner" && <IconCrown className="indicator-item" />}
                              <div className="w-16 rounded">
                                <img src={player.avatar} />
                              </div>
                            </div>
                            <p className="flex flex-row">{player.name}</p>
                          </div>
                        </>
                      )
                    })}
                  </div>
                  { role == "owner" && 
                    <button className="btn btn-primary" onClick={startGame}>Start game</button>
                  }
                </div>
              }
              </div>
              </>
            }
          </div>
        </>
      }
      { gameStarted &&
        <>
        <div className="flex flex-col space-y-4 items-center">
          <h1 className="text-3xl">{questionDisplayed!.text}</h1>
          <span className="indicator-item badge indicator-bottom indicator-center opacity-30">{questionNbr}/{questionLimit}</span>
        </div>
        { countdown > 0 &&
          <>
            <span className="countdown">
              <span style={{"--value":countdown.toString()} as React.CSSProperties }></span>
            </span>
            <div className="flex flex-row space-x-4">
              { choice == "" &&
                <>
                  { possibleChoice.map((playerChoice, index) => (
                    <button key={index} className="btn btn-primary" disabled={choice != ""} onClick={() => {setAndSendChoice(playerChoice.name)}}>{playerChoice.name}</button>
                  ))}
                </>
              }
              { choice != "" &&
                  <span>Waiting <span className="loading loading-dots loading-xs"></span></span>
              }
            </div>
          </>
        }
        { countdown == 0 && 
          <>
          <div className="flex flex-row space-x-4">
            { possibleChoice.map((playerChoice, index) => {
              console.log(totalVotes)
              console.log(playerChoice.nbrVotes / totalVotes)
              let percent = Math.floor((playerChoice.nbrVotes / totalVotes) * 100)
              return (
                <div key={index} className="flex items-center space-y-4 flex-col">
                  <div className="radial-progress text-primary" style={{ "--value": percent } as React.CSSProperties} role="progressbar">
                  {percent}%
                  </div> 
                  <h1>{playerChoice.name}</h1>
                </div>
              )})}
          </div>
            { (questionDisplayed.type == "photo" && possibleChoice.sort((a,b) => b.nbrVotes - a.nbrVotes)[0].browserId == browserId) && 
              <>
              { questionReply.photo == undefined &&
                <div className="flex flex-col items-center space-y-4">
                  <span className="text-xl">À toi d&apos;envoyer une photo !</span>
                  <input type="file" ref={inputPhotoRef} onChange={setAndSendPhoto} className="hidden" />
                  <div className="flex flex-row space-x-4">
                    <button className="btn btn-primary" onClick={() => inputPhotoRef.current!.click()}><IconPhotoUp /></button>
                  </div>
                </div>
              }
              { questionReply.photo != undefined &&
                <div>
                  <img src={questionReply.photo} />
                  <span className="text-zinc-500">Photo received from {possibleChoice.sort((a,b) => b.nbrVotes - a.nbrVotes)[0].name}...</span>
                </div>

              }
              </>
            }
            { (questionDisplayed.type == "photo" && possibleChoice.sort((a,b) => b.nbrVotes - a.nbrVotes)[0].browserId != browserId) && 
              <>
              { questionReply.photo == undefined &&
                <div>
                  <span className="text-zinc-500">Waiting for {possibleChoice.sort((a,b) => b.nbrVotes - a.nbrVotes)[0].name}...</span>
                </div>
              }
              { questionReply.photo != undefined &&
                <div>
                  <img src={questionReply.photo} />
                  <span className="text-zinc-500">Photo received from {possibleChoice.sort((a,b) => b.nbrVotes - a.nbrVotes)[0].name}...</span>
                </div>

              }
              </>
            }
            { (role == "owner" && questionNbr < questionLimit) &&
              <button className="btn btn-primary" onClick={nextQuestion}>Next question</button>
            }
            { (role == "owner" && questionNbr == questionLimit) &&
              <button className="btn btn-primary" onClick={resetGame}>Replay</button>
            }
          </>
        }
        </>
      }
    </main>
  );
}
