// Canvas Renderer for Tetris

class TetrisRenderer {
  constructor(containerId) {
    this.container = document.getElementById(containerId);
    this.boards = new Map();
  }

  createPlayerBoard(playerId, playerName) {
    const boardDiv = document.createElement('div');
    boardDiv.className = 'player-board';
    boardDiv.id = `board-${playerId}`;
    boardDiv.dataset.playerId = playerId;

    // Main game canvas
    const canvas = document.createElement('canvas');
    canvas.id = `canvas-${playerId}`;
    canvas.width = BOARD_WIDTH * CELL_SIZE;
    canvas.height = BOARD_HEIGHT * CELL_SIZE;
    canvas.style.width = `${BOARD_WIDTH * CELL_SIZE}px`;
    canvas.style.height = `${BOARD_HEIGHT * CELL_SIZE}px`;
    boardDiv.appendChild(canvas);

    // Player info
    const infoDiv = document.createElement('div');
    infoDiv.className = 'board-info';
    infoDiv.innerHTML = `
      <span class="name">${playerName}</span>
      <span class="stats">Lines: <span class="lines">0</span></span>
    `;
    boardDiv.appendChild(infoDiv);

    // Next piece preview
    const nextDiv = document.createElement('div');
    nextDiv.className = 'board-info';
    const nextCanvas = document.createElement('canvas');
    nextCanvas.id = `next-${playerId}`;
    nextCanvas.width = 60;
    nextCanvas.height = 60;
    nextCanvas.style.width = '60px';
    nextCanvas.style.height = '60px';
    nextDiv.innerHTML = '<span>NEXT:</span>';
    nextDiv.appendChild(nextCanvas);
    boardDiv.appendChild(nextDiv);

    // Hold piece preview
    const holdDiv = document.createElement('div');
    holdDiv.className = 'board-info';
    const holdCanvas = document.createElement('canvas');
    holdCanvas.id = `hold-${playerId}`;
    holdCanvas.width = 60;
    holdCanvas.height = 60;
    holdCanvas.style.width = '60px';
    holdCanvas.style.height = '60px';
    holdDiv.innerHTML = '<span>HOLD:</span>';
    holdDiv.appendChild(holdCanvas);
    boardDiv.appendChild(holdDiv);

    // Zone meter
    const zoneDiv = document.createElement('div');
    zoneDiv.className = 'board-info zone-info';
    zoneDiv.id = `zone-${playerId}`;
    zoneDiv.innerHTML = '<span>ZONE: <span class="zone-meter-bar"><span class="zone-meter-fill"></span></span> <span class="zone-status"></span></span>';
    boardDiv.appendChild(zoneDiv);

    this.container.appendChild(boardDiv);

    this.boards.set(playerId, {
      element: boardDiv,
      canvas: canvas,
      nextCanvas: nextCanvas,
      holdCanvas: holdCanvas,
      zoneDiv: zoneDiv,
      info: infoDiv,
      ctx: canvas.getContext('2d'),
      nextCtx: nextCanvas.getContext('2d'),
      holdCtx: holdCanvas.getContext('2d')
    });

    return boardDiv;
  }

  removePlayerBoard(playerId) {
    const board = this.boards.get(playerId);
    if (board) {
      board.element.remove();
      this.boards.delete(playerId);
    }
  }

  renderPlayer(playerId, gameState) {
    const boardData = this.boards.get(playerId);
    if (!boardData) return;

    const { ctx, nextCtx, holdCtx, element, info } = boardData;

    // Clear canvas
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    // Draw grid lines
    this.drawGrid(ctx);

    // Draw locked pieces
    if (gameState && gameState.board) {
      this.drawBoard(ctx, gameState.board);
    }

    // Draw ghost piece (landing preview)
    if (gameState && gameState.currentPiece && !gameState.gameOver && gameState.ghostY !== null) {
      this.drawGhostPiece(ctx, gameState.currentPiece, gameState.ghostY);
    }

    // Draw current piece
    if (gameState && gameState.currentPiece && !gameState.gameOver) {
      this.drawPiece(ctx, gameState.currentPiece);
    }

    // Draw next piece
    if (gameState && gameState.nextPiece) {
      this.drawNextPiece(nextCtx, gameState.nextPiece);
    }

    // Draw hold piece
    if (gameState && gameState.holdPiece) {
      this.drawHoldPiece(holdCtx, gameState.holdPiece, gameState.canHold);
    } else if (holdCtx) {
      // Clear hold canvas if no hold piece
      holdCtx.fillStyle = '#000';
      holdCtx.fillRect(0, 0, holdCtx.canvas.width, holdCtx.canvas.height);
    }

    // Update stats
    if (gameState) {
      const linesSpan = info.querySelector('.lines');
      if (linesSpan) {
        linesSpan.textContent = gameState.lines;
      }

      // Update Zone meter
      const zoneDiv = boardData.zoneDiv;
      if (zoneDiv) {
        const meterFill = zoneDiv.querySelector('.zone-meter-fill');
        const statusSpan = zoneDiv.querySelector('.zone-status');
        if (meterFill) {
          meterFill.style.width = gameState.zoneMeter + '%';
        }
        if (statusSpan) {
          if (gameState.zoneActive) {
            statusSpan.textContent = `ACTIVE (${Math.max(0, Math.round(gameState.zoneTimeRemaining / 1000))}s)`;
            statusSpan.style.color = '#00ff00';
          } else if (gameState.zoneMeter >= 100) {
            statusSpan.textContent = 'READY!';
            statusSpan.style.color = '#ffff00';
          } else {
            statusSpan.textContent = '';
            statusSpan.style.color = '#fff';
          }
        }
      }
    }

    // Update board state classes (preserving main/spectator/position classes)
    const wasMain = element.classList.contains('main');
    const wasSpectator = element.classList.contains('spectator');
    const positions = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
    const wasPos = positions.some(p => element.classList.contains(p));
    element.classList.remove('active', 'eliminated');
    if (wasMain) element.classList.add('main');
    if (wasSpectator) element.classList.add('spectator');
    if (wasPos) {
      positions.forEach(p => {
        if (element.classList.contains(p)) element.classList.add(p);
      });
    }
    if (gameState && gameState.eliminated) {
      element.classList.add('eliminated');
    }
  }

  drawGrid(ctx) {
    ctx.strokeStyle = '#222';
    ctx.lineWidth = 1;

    for (let x = 0; x <= BOARD_WIDTH; x++) {
      ctx.beginPath();
      ctx.moveTo(x * CELL_SIZE, 0);
      ctx.lineTo(x * CELL_SIZE, BOARD_HEIGHT * CELL_SIZE);
      ctx.stroke();
    }

    for (let y = 0; y <= BOARD_HEIGHT; y++) {
      ctx.beginPath();
      ctx.moveTo(0, y * CELL_SIZE);
      ctx.lineTo(BOARD_WIDTH * CELL_SIZE, y * CELL_SIZE);
      ctx.stroke();
    }
  }

  drawBoard(ctx, board) {
    for (let row = 0; row < BOARD_HEIGHT; row++) {
      for (let col = 0; col < BOARD_WIDTH; col++) {
        const color = board[row][col];
        if (color) {
          this.drawCell(ctx, col, row, color);
        }
      }
    }
  }

  drawPiece(ctx, piece) {
    for (let row = 0; row < piece.shape.length; row++) {
      for (let col = 0; col < piece.shape[row].length; col++) {
        if (piece.shape[row][col]) {
          const x = piece.x + col;
          const y = piece.y + row;
          if (y >= 0) {
            this.drawCell(ctx, x, y, piece.color);
          }
        }
      }
    }
  }

  drawCell(ctx, x, y, color) {
    const px = x * CELL_SIZE;
    const py = y * CELL_SIZE;

    // Main fill
    ctx.fillStyle = color;
    ctx.fillRect(px, py, CELL_SIZE, CELL_SIZE);

    // Bevel effect
    ctx.fillStyle = 'rgba(255,255,255,0.3)';
    ctx.fillRect(px, py, CELL_SIZE, 3);
    ctx.fillRect(px, py, 3, CELL_SIZE);

    ctx.fillStyle = 'rgba(0,0,0,0.3)';
    ctx.fillRect(px, py + CELL_SIZE - 3, CELL_SIZE, 3);
    ctx.fillRect(px + CELL_SIZE - 3, py, 3, CELL_SIZE);

    // Border
    ctx.strokeStyle = 'rgba(0,0,0,0.5)';
    ctx.lineWidth = 1;
    ctx.strokeRect(px, py, CELL_SIZE, CELL_SIZE);
  }

  drawGhostPiece(ctx, piece, ghostY) {
    for (let row = 0; row < piece.shape.length; row++) {
      for (let col = 0; col < piece.shape[row].length; col++) {
        if (piece.shape[row][col]) {
          const x = piece.x + col;
          const y = ghostY + row;
          if (y >= 0) {
            this.drawGhostCell(ctx, x, y, piece.color);
          }
        }
      }
    }
  }

  drawGhostCell(ctx, x, y, color) {
    const px = x * CELL_SIZE;
    const py = y * CELL_SIZE;

    // Vibrant outlined border effect
    ctx.strokeStyle = color + 'cc'; // 80% opacity border
    ctx.lineWidth = 3;
    ctx.strokeRect(px + 2, py + 2, CELL_SIZE - 4, CELL_SIZE - 4);

    // More visible fill inside
    ctx.fillStyle = color + '40'; // 25% opacity
    ctx.fillRect(px + 3, py + 3, CELL_SIZE - 6, CELL_SIZE - 6);
  }

  drawNextPiece(ctx, piece) {
    // Clear
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    // Center the piece
    const pieceWidth = piece.shape[0].length * 20;
    const pieceHeight = piece.shape.length * 20;
    const offsetX = (ctx.canvas.width - pieceWidth) / 2;
    const offsetY = (ctx.canvas.height - pieceHeight) / 2;

    for (let row = 0; row < piece.shape.length; row++) {
      for (let col = 0; col < piece.shape[row].length; col++) {
        if (piece.shape[row][col]) {
          const x = offsetX + col * 20;
          const y = offsetY + row * 20;

          ctx.fillStyle = piece.color;
          ctx.fillRect(x, y, 20, 20);

          ctx.fillStyle = 'rgba(255,255,255,0.3)';
          ctx.fillRect(x, y, 20, 3);
          ctx.fillRect(x, y, 3, 20);

          ctx.fillStyle = 'rgba(0,0,0,0.3)';
          ctx.fillRect(x, y + 17, 20, 3);
          ctx.fillRect(x + 17, y, 3, 20);

          ctx.strokeStyle = 'rgba(0,0,0,0.5)';
          ctx.lineWidth = 1;
          ctx.strokeRect(x, y, 20, 20);
        }
      }
    }
  }

  drawHoldPiece(ctx, piece, canHold) {
    // Clear
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    if (!piece) return;

    // Gray out if cannot hold again this turn
    const alpha = canHold ? 1.0 : 0.4;

    // Center the piece
    const pieceWidth = piece.shape[0].length * 20;
    const pieceHeight = piece.shape.length * 20;
    const offsetX = (ctx.canvas.width - pieceWidth) / 2;
    const offsetY = (ctx.canvas.height - pieceHeight) / 2;

    for (let row = 0; row < piece.shape.length; row++) {
      for (let col = 0; col < piece.shape[row].length; col++) {
        if (piece.shape[row][col]) {
          const x = offsetX + col * 20;
          const y = offsetY + row * 20;

          ctx.fillStyle = piece.color + Math.floor(alpha * 255).toString(16).padStart(2, '0');
          ctx.fillRect(x, y, 20, 20);

          if (canHold) {
            ctx.fillStyle = 'rgba(255,255,255,0.3)';
            ctx.fillRect(x, y, 20, 3);
            ctx.fillRect(x, y, 3, 20);

            ctx.fillStyle = 'rgba(0,0,0,0.3)';
            ctx.fillRect(x, y + 17, 20, 3);
            ctx.fillRect(x + 17, y, 3, 20);

            ctx.strokeStyle = 'rgba(0,0,0,0.5)';
            ctx.lineWidth = 1;
            ctx.strokeRect(x, y, 20, 20);
          }
        }
      }
    }
  }

  setActivePlayer(playerId) {
    // Remove main/spectator classes from all boards
    this.boards.forEach((boardData, id) => {
      boardData.element.classList.remove('active', 'main');
      boardData.element.classList.remove('spectator', 'top-left', 'top-right', 'bottom-left', 'bottom-right');
    });

    // If playerId is null (spectator mode), show all boards equally without highlighting
    if (playerId === null) {
      return;
    }

    // Add main class to current player
    const mainBoard = this.boards.get(playerId);
    if (mainBoard) {
      mainBoard.element.classList.add('main');
    }

    // Add spectator class to other boards with positions
    const positions = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
    let posIndex = 0;
    this.boards.forEach((boardData, id) => {
      if (id !== playerId) {
        boardData.element.classList.add('spectator');
        if (posIndex < positions.length) {
          boardData.element.classList.add(positions[posIndex]);
          posIndex++;
        }
      }
    });
  }

  triggerShake(playerId) {
    const boardData = this.boards.get(playerId);
    if (boardData) {
      boardData.element.classList.remove('shake');
      void boardData.element.offsetWidth; // Trigger reflow
      boardData.element.classList.add('shake');
    }
  }

  triggerFlash(playerId) {
    const boardData = this.boards.get(playerId);
    if (boardData) {
      boardData.element.classList.remove('flash');
      void boardData.element.offsetWidth; // Trigger reflow
      boardData.element.classList.add('flash');
    }
  }

  updatePlayerInfo(playerId, name, score, lines) {
    const boardData = this.boards.get(playerId);
    if (boardData) {
      const nameSpan = boardData.info.querySelector('.name');
      if (nameSpan) nameSpan.textContent = name;

      const linesSpan = boardData.info.querySelector('.lines');
      if (linesSpan) linesSpan.textContent = lines;
    }
  }

  clearAll() {
    this.boards.forEach((boardData) => {
      boardData.element.remove();
    });
    this.boards.clear();
  }
}

window.TetrisRenderer = TetrisRenderer;
