<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Multiplayer Game</title>
  <link rel="stylesheet" type="text/css" href="mflx.min.css">
  <style type="text/css">
    .text-with-shadow {
       text-shadow: -1px -1px 1px #000, 1px -1px 1px #000,
          -1px 1px 1px #000, 1px 1px 1px #000; color: white;
    }
    .div-shadow {
      box-shadow: rgba(0, 0, 0, 0.15) 1.95px 1.95px 2.6px;
    }
    .puzzleboard {
      display: grid;
      grid-template-columns: repeat(12, 1fr); /* 12 columns, equal width */
      grid-template-rows: repeat(4, auto);   /* 4 rows, height adjusts to content */
      gap: 1px; /* Optional: spacing between grid items */
      height: 205px;
      width: 500px;
      max-width: 100%; /* Optional: ensures grid fits within the container */
      max-height: 100%; /* Optional: ensures the grid respects height limits */
    }
    .grid-item {
      background-image: radial-gradient(circle,#21D375 ,green); /* For visualization */
      border: 1px solid black;    /* Optional: visual boundary for items */
      text-align: center;
      padding: 1px;
      border-radius: 5px;
    }
    .grid-item-2 {
      background-color: white; /* For visualization */
      border: 1px solid black;    /* Optional: visual boundary for items */
      text-align: center;
      padding: 1px;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size:1.2rem;
      font-family:'sans';
      font-weight:bold;
      border-radius: 5px;
    }
    .category {
      background-image: radial-gradient(circle,#1f57dd ,#0000ae);
      color: white;
      max-width: 500px;
      font-size:1.2rem;
      font-family:'sans';
      font-weight:bold;
      border-radius: 5px;
      text-align: center;
    }
    .hidden {
      display: none;
      visibility: hidden;
    }
    /* Dialog styling */
    dialog {
      border: none;
      border-radius: 8px;
      padding: 20px;
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
      font-family: Arial, sans-serif;
      max-width: 300px;
      text-align: center;
    }

    dialog::backdrop {
      background-color: rgba(0, 0, 0, 0.5);
    }

    dialog h2 {
      margin-top: 0;
      font-size: 18px;
    }
    .nameInput {
      text-align: center;
    }
  </style>
</head>
<body>
  <!-- Dialog -->
  <dialog class="nameDialog">
    <div class="flx(column) space-evenly">
      <h2>Change Your Name?</h2>
      <label for="nameInput">Name:</label>
      <input type="text" class="nameInput is-round" style="padding: .25rem; ">
      <div class="mt-4 flx(wrap) space-evenly">
        <button class="saveButton btn is-success is-round mr-1 div-shadow">save</button>
        <button class="closeDialogButton btn is-error is-round ml-1 div-shadow">close</button>
      </div>
    <div>
  </dialog>

  <button id="create-room">Create Room</button>
  <input id="join-code" placeholder="Enter room code">
  <button id="join-room">Join Room</button>
  <div class="room-code"></div>
  <div class="flx(wrap) mb-2 players"></div>

  <div id="status"></div>
  <button id="start-game" style="display: none;">Start Game</button>
  <button id="spin-wheel" style="display: none;">Spin Wheel</button>
  <input id="guess-letter" placeholder="Guess a letter" style="display: none;">
  <button id="guess-button" style="display: none;">Guess</button>


  <div class="puzzleboard mb-2"></div>
  <div class="category mb-5"></div>

  <div style="display:relative;">
    <span style="position: absolute; top: 0; left:50%">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>arrow-down-bold</title><path d="M9,4H15V12H19.84L12,19.84L4.16,12H9V4Z" /></svg>
    </span>
    <canvas id="wheelCanvas" width="500" height="500"></canvas>
  </div>
  <script>
//================general Purpose functions=========================================//
    function cryptoSecureShuffle(array) {
      const shuffledArray = [...array]; // Create a copy to avoid mutating the original array
      const n = shuffledArray.length;

      // Fisher-Yates shuffle
      for (let i = n - 1; i > 0; i--) {
          // Generate a cryptographically secure random index
          let randIndex;
          do {
              // Generate a random value in the range [0, 2^32)
              const randomBuffer = new Uint32Array(1);
              window.crypto.getRandomValues(randomBuffer);
              randIndex = randomBuffer[0] >>> 0; // Convert to a non-negative integer
          } while (randIndex >= Math.floor(2 ** 32 / (i + 1)) * (i + 1)); // Avoid bias

          // Compute the unbiased index
          randIndex %= (i + 1);

          // Swap the elements
          [shuffledArray[i], shuffledArray[randIndex]] = [shuffledArray[randIndex], shuffledArray[i]];
      }

      return shuffledArray;
    }
//====================making Name Tags/ assigning colors to names================//
    let nameColors = [
      '#ff0000','#ff8700','#ffd300','#deff0a','#a1ff0a',
      '#0aff99','#0aefff','#147df5','#580aff','#be0aff'
    ]
    nameColors = cryptoSecureShuffle(nameColors);
    function assignColors(names, colors) {
      let result = [];
      let n = 0; // Keep track of name index
      let c = 0; // Keep track of color index

      if (names.length > colors.length) {
          // Assign colors cyclically
          while (n < names.length) {
              result.push({ name: names[n], color: colors[c] });
              n++;
              c = (c + 1) % colors.length; // Cycle through the colors
          }
      } else {
          // Assign colors directly, keeping track of indices
          while (n < names.length) {
              result.push({ name: names[n], color: colors[c] });
              n++;
              c++;
          }
      }

      return result;
    }
//=========================================wheel==========================================//
    const wheel = [
      'lose a turn', 800, 350, 450, 700, 300, 600, 5000,
      300, 600, 300, 500, 800, 550, 400, 300, 900, 500, 'spin again',
      900, 'Bankrupt', 600, 400, 300
    ];
    const wheelSpinSpeedData = {
      '0':0.2523,//lose a turn
      '1':.2497,//800
      '2':.2471,//350
      '3':.2445,//450
      '4':.2418,//450
      '5':.2392,//300
      '6':.2366,//600
      '7':.2339,//5000
      '8':.2313,//300
      '9':.2287,//600
      '10':.2261,//300
      '11':.2235,//500

      '12':.2208,//800
      '13':.2182,//550
      '14':.2156,//400
      '15':.213,//300
      '16':.2104,//900
      '17':.2078,//500
      '18':.2052,//spin again
      '19':.2026,//900
      '20':.1999,//Bankrupt
      '21':.1973,//600
      '22':.1947,//400
      '23':.1921//300
    };
    const canvas = document.getElementById('wheelCanvas');
    const ctx = canvas.getContext('2d');
    const radius = canvas.width / 2;

    let rotation = 0 - (.283*6); //sets the zero index on top
    let spinning = false;
    let spinSpeed = 0;
    let img = new Image();
    img.src = "arrow-down-bold.png";
    img.onload = function() {
      ctx.drawImage(img, 200, -50, 100,100);
    }
    // Draw the wheel
    function drawWheel(drawResult = false) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      
      ctx.save();
      

      ctx.translate(radius, radius);
      ctx.rotate(rotation);
      
      const anglePerSegment = (2 * Math.PI) / wheel.length;

      wheel.forEach((value, i) => {
        const startAngle = i * anglePerSegment;
        const endAngle = startAngle + anglePerSegment;

        ctx.beginPath();
        ctx.moveTo(0, 0);
        ctx.arc(0, 0, radius, startAngle, endAngle);
        ctx.closePath();

        ctx.fillStyle = i % 2 === 0 ? '#ffdd99' : '#ffeecc';
        ctx.fill();
        ctx.stroke();

        // Add text
        ctx.save();
        ctx.translate(
          Math.cos(startAngle + anglePerSegment / 2) * radius * 0.7,
          Math.sin(startAngle + anglePerSegment / 2) * radius * 0.7
        );
        ctx.rotate(startAngle + anglePerSegment / 2 + Math.PI / 2 - 1.5);
        ctx.textAlign = 'center';
        ctx.fillStyle = '#000';
        ctx.font = '12px Arial';
        ctx.fillText(String(i+","+value), 0, 0);

        ctx.restore();
      });

      ctx.restore();
      ctx.drawImage(img, 200, -50, 100,100);
    }

    // Start spinning
    function startSpin(targetIndex) {
      console.log('targetIndex: ',targetIndex);
      let resultingSpeed = wheelSpinSpeedData[targetIndex];
      console.log('resultingSpeed: ', resultingSpeed);
      if (spinning) return;
      rotation = 0 - (.283*6)
      spinning = true;

      const totalSpins = Math.floor(Math.random() * 3) + 3; // 3-6 full spins
      const anglePerSegment = (2 * Math.PI) / wheel.length;
      const targetAngle = targetIndex * anglePerSegment;
      console.log(anglePerSegment);

      let currentRotation = rotation; // Start from the current rotation
      spinSpeed = wheelSpinSpeedData[targetIndex]; // Initial speed

      function animate() {
        if ( spinSpeed < 0.001) {
          spinning = false;
          console.log(`Landed on: ${wheel[targetIndex]}`);
          return;
        }
        // console.log('currentRotation: ',currentRotation);
        // console.log('spinSpeed: ', spinSpeed);
        currentRotation += spinSpeed;
        spinSpeed *= 0.99; // Gradual slowdown


        rotation = currentRotation ;
        drawWheel();
        requestAnimationFrame(animate);
      }

      animate();
    }
    // Simulate WebSocket server response
    // function simulateServerResponse() {
    //   const targetIndex = Math.floor(Math.random() * wheel.length); // Random result
    //   startSpin(targetIndex);
    // }

    // Initial draw
    drawWheel();

    // Trigger spin after 2 seconds
    //setTimeout(simulateServerResponse, 2000);

//==================================end of Wheel=====================================//
    function drawPlayers(message) {
      console.log(message);
      let players = document.querySelector('.players');
      //assignColors(names, colors) {
      let processedNametags = assignColors(message.clients,nameColors);
      const playersHtml = processedNametags.map(client => {
          if(client.name != window.you) {
            if (client.name === message.leaderName) {
              return `<span class='mr-2 btn is-round text-with-shadow div-shadow' style='background-color:${client.color};'>⭐ ${client.name} ⭐</span>`; // Highlight the leader with stars
            } else {
                return `<span class='mr-2 btn is-round text-with-shadow div-shadow' style='background-color:${client.color};'>${client.name}</span>`;
            }
          }
          else if (client.name === message.leaderName) {
              return `<span class='mr-2 btn is-round text-with-shadow div-shadow' style='background-color:${client.color};' onclick="changeName()">⭐ ${client.name} ⭐ (you)</span>`; // Highlight the leader with stars
            } 
          else {
            return `<span class='mr-2 btn is-round text-with-shadow div-shadow' style='background-color:${client.color};' onclick="changeName()">${client.name} (you)</span>`;
          }
          
          
        }).join(""); // Combine all elements into a single string

        players.innerHTML = playersHtml;
    }

    function drawPuzzle(message, gridRows = 4, gridCols = 12) {
      //legend null = space, "" = white space to guess, "a" is a letter already solved for you.
      console.log(message);
      //wheel of fortune puzzles must fit within a 12x4 grid of letter spaces
      //first we draw the spaces
      let puzzle = message.puzzle.puzzle;
      let puzzleBoard = document.querySelector('.puzzleboard');
      let resultingPuzzleBoard = [];
      //if the first entry of the puzzle is an array and not a string display the puzzle differently
      if (Array.isArray(message.puzzle.puzzle[0])) {
        console.log('first entry is an array in this puzzle...');
      }
      else if (typeof message.puzzle.puzzle[0] == 'string') {
        console.log('first entry is a string in this puzzle...');
        //if we have a single string we need to return it on the second line from the bottom
        
        resultingPuzzleBoard.push(Array(12).fill(null));
        resultingPuzzleBoard.push(Array(12).fill(null));

        const nextLine = Array(12).fill(null);
        const startIndex = Math.floor((12 - message.puzzle.puzzle.length) / 2);
        console.log(startIndex);
        for (let i = 0; i < message.puzzle.puzzle.length; i++) {
          nextLine[startIndex + i] = message.puzzle.puzzle[i];
        }
        console.log(nextLine);
        resultingPuzzleBoard.push(nextLine);
        resultingPuzzleBoard.push(Array(12).fill(null));
        console.log(resultingPuzzleBoard);
        //after we've drawn our data for our board,now its time to visualize it to the user
        for(let i of resultingPuzzleBoard) {
          for (let j in i) {
            const letter = i[j];
            if (letter == null || letter == ' ') {
              let el = document.createElement('div');
              el.classList.add('grid-item');
              el.innerHTML = '&nbsp;';
              // el.style.height = '50px';
              // el.style.width = '50px';
              // el.style.border = 'solid'
              puzzleBoard.appendChild(el);
            }
            else if (letter != null && letter != ' ') {
              let el = document.createElement('div');
              el.classList.add('grid-item-2');
              el.innerText = letter;
              puzzleBoard.appendChild(el);
            }
          }
        }
      }
      else {
        console.error('error: ','message does not have correct datatype of string or array');
      }
      //finally draw the category!
      document.querySelector('.category').classList.add('pt-2','pb-2');
      document.querySelector('.category').innerHTML = `${message.puzzle.category}`
     
    }

    function changeName() {
      console.log('change name hit.');
      const nameDialog = document.querySelector('.nameDialog');
      const nameInput = document.querySelector('.nameInput');
      const saveButton = document.querySelector('.saveButton');
      const closeDialogButton = document.querySelector('.closeDialogButton');
      nameDialog.showModal();
      nameInput.value = window.you;
      closeDialogButton.addEventListener('click',() => {nameDialog.close()});
      saveButton.addEventListener('click',() => {
        socket.send(JSON.stringify({ type: "change_name", deadName:window.you, newName:nameInput.value }));
        console.log('you changed your name.');

        nameDialog.close();
      });
    }
    const socket = new WebSocket("ws://localhost:8080");

    document.getElementById("create-room").onclick = function () {
      socket.send(JSON.stringify({ type: "create_room" }));
      this.style.display = 'none';
      document.getElementById("join-room").style.display = 'none';
      document.getElementById('join-code').style.display = 'none';
    };

    document.getElementById("join-room").onclick = () => {
      const roomCode = document.getElementById("join-code").value;
      socket.send(JSON.stringify({ type: "join_room", roomCode }));
      this.style.display = 'none';
      document.getElementById("create-room").style.display = 'none';
      document.getElementById('join-code').style.display = 'none';
    };

    document.getElementById("start-game").onclick = () => {
      socket.send(JSON.stringify({ type: "start_game" }));
    };

    document.getElementById("spin-wheel").onclick = () => {
      socket.send(JSON.stringify({ type: "spin_wheel" }));
    };

    document.getElementById("guess-button").onclick = () => {
      const letter = document.getElementById("guess-letter").value;
      socket.send(JSON.stringify({ type: "guess_letter", letter }));
      document.getElementById("guess-letter").value = ""; // Clear input
    };

    

    socket.onmessage = (event) => {
      const message = JSON.parse(event.data);

      if (message.type === "room_created") {
        window.you = message.you;
        document.querySelector(".room-code").innerText =`Room Code: ${message.roomCode}`;
        document.getElementById("status").innerText = `Room created!`;
        drawPlayers(message);
        if (message.isLeader) {
          document.getElementById("start-game").style.display = "inline";
        }
      }
      if (message.type === "changed_name_you") {
        window.you = message.you;
        console.log('server has changed your name!');
      }
      if (message.type === "changed_name") {
        drawPlayers(message);
        console.log('server has changed your name!');
      }
      if (message.type === "joined_room_you") {
        window.you = message.you;
      }
      if (message.type === "joined_room") {
      
        drawPlayers(message);
        const status = message.isLeader ? "You are the party leader!" : "You joined the room!";
        // document.querySelector('.players').innerHtml += `<span>${}<span>`

        document.getElementById("status").innerText = `${status}`;
        document.querySelector(".room-code").innerText =`Room Code: ${message.roomCode}`;
        if (message.isLeader) {
          document.getElementById("start-game").style.display = "inline";
          document.getElementById("spin-wheel").style.display = "inline";
          document.getElementById("guess-letter").style.display = "inline";
          document.getElementById("guess-button").style.display = "inline";
        }
      }

      if (message.type === "game_started") {
          let result = drawPuzzle(message);
          console.log(result);
          document.getElementById("status").innerText = "The game has started!";
          document.getElementById("start-game").style.display = "none";
          document.getElementById("start-game").style.display = "inline";
          document.getElementById("spin-wheel").style.display = "inline";
          document.getElementById("guess-letter").style.display = "inline";
          document.getElementById("guess-button").style.display = "inline";
      }

      if (message.type === "spin_result") {
        console.log('spin result recieved');
        document.getElementById("status").innerText = `Spin result: ${message.spinResult} points (${message.player})`;
          //find target index
          let targetIndexArr = wheel.entries();
          let filterResultsArr = [];
          for(let x of targetIndexArr){
            if (x[1] == message.spinResult) {
              filterResultsArr.push(x);
            }
          }
          console.log(filterResultsArr[0][0]);
          //if there is multiple entries where the spin exists pick a random index.
          if(filterResultsArr.length > 1) {
            startSpin(filterResultsArr[Math.floor(Math.random() * filterResultsArr.length)][0]);
          }
          else{
            startSpin(filterResultsArr[0]);
          }
          
      }

      if (message.type === "guess_result") {
        const outcome = message.correct ? "correct" : "incorrect";
        document.getElementById("status").innerText = `Guess '${message.letter}' was ${outcome} (${message.player})`;
      }

      if (message.type === "new_leader") {
        drawPlayers(message);
        document.getElementById("status").innerText = "You are now the party leader!";
      }

      if (message.type === "error") {
        alert(message.message);
      }
    };
  </script>
  

</body>
</html>