// Main Application - Ties everything together

let localGame = null;
let renderer = null;
let lastTime = 0;

// Keyboard state for continuous movement (DAS - Delayed Auto Shift)
const keyState = {
  ArrowLeft: false,
  ArrowRight: false,
  ArrowDown: false,
};

// Track key press timing for tap vs hold detection
let keyPressStartTime = null;
let wasAutoMoved = {
  ArrowLeft: false,
  ArrowRight: false,
  ArrowDown: false,
};

let dasCounter = 0;
const DAS_DELAY = 75;  // ms before auto-repeat starts (reduced from 100 for faster response)
const ARR_SPEED = 25;  // ms between auto-repeat moves (reduced from 30 for faster movement)

// Initialize when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
  // Connect to server
  network.connect();

  // Initialize renderer
  renderer = new TetrisRenderer('battle-grid');

  // Setup network listeners
  setupNetworkListeners();

  // Setup keyboard controls
  setupKeyboardControls();
});

function setupNetworkListeners() {
  // Player joined lobby
  network.setListener('player-joined', (player) => {
    ui.updatePlayerList(network.getAllPlayers());
    // Show lobby screen if we're on the login screen
    if (ui.screens.room.classList.contains('active')) {
      ui.showScreen('lobby');
      // Play lobby music when first entering lobby
      if (typeof audio !== 'undefined') {
        audio.playLobby();
      }
    }
    // Reset lobby state when returning from game over (player is null indicates game over reset)
    if (!player) {
      ui.resetLobbyState();
      // Resume lobby music after game ends
      if (typeof audio !== 'undefined') {
        audio.playLobby();
      }
    }
  });

  // Player left lobby
  network.setListener('player-left', (playerId) => {
    ui.updatePlayerList(network.getAllPlayers());
  });

  // Game started
  network.setListener('game-started', (players, states) => {
    ui.showScreen('game');
    ui.displays.gameRoomName.textContent = 'GLOBAL LOBBY';

    // Start game music - will play continuously until game ends
    if (typeof audio !== 'undefined') {
      audio.playGame();
    }

    // Clear old boards
    renderer.clearAll();

    // Create boards for all players
    states.forEach((state) => {
      const player = network.getPlayer(state.playerId);
      renderer.createPlayerBoard(state.playerId, player.name);

      // Initialize local game for current player
      if (state.playerId === network.currentPlayerId) {
        localGame = new TetrisGame(state.playerId);
        localGame.loadState(state);
      }
    });

    // Set up battle grid layout
    updateBattleGridLayout(players.length);

    // Start game loop
    lastTime = performance.now();
    requestAnimationFrame(gameLoop);
  });

  // State update during game
  network.setListener('state-update', (states) => {
    // Update local game if it's our state
    const localState = states.find(s => s.playerId === network.currentPlayerId);
    if (localState) {
      localGame.loadState(localState);
    }

    // Game over is handled by the server via 'game-over' event
    // Don't check locally to avoid premature game end
  });

  // Game over
  network.setListener('game-over', (data) => {
    endGame(data.states);
  });

  // Forced spectator - game already in progress
  network.setListener('forced-spectator', ({ states, players }) => {
    ui.showScreen('game');
    ui.showSpectatorMode();

    // Start game music for spectators too
    if (typeof audio !== 'undefined') {
      audio.playGame();
    }

    // Clear old boards
    renderer.clearAll();

    // Create boards for all players (spectator can see everyone)
    states.forEach((state) => {
      const player = network.getPlayer(state.playerId);
      renderer.createPlayerBoard(state.playerId, player.name);
    });

    // Set up battle grid layout
    updateBattleGridLayout(players.length);

    // Start game loop for viewing
    lastTime = performance.now();
    requestAnimationFrame(gameLoop);
  });

  // Spectator joined
  network.setListener('spectator-joined', (spectator) => {
    ui.updateSpectatorList(network.getAllSpectators());
  });

  // Spectator left
  network.setListener('spectator-left', (spectatorId) => {
    ui.updateSpectatorList(network.getAllSpectators());
  });
}

function setupKeyboardControls() {
  document.addEventListener('keydown', (e) => {
    // Spectators cannot control the game
    if (network.isSpectator) return;

    if (ui.screens.game.classList.contains('active') && localGame) {
      // Track held keys for movement
      if (keyState.hasOwnProperty(e.key)) {
        keyState[e.key] = true;
        keyPressStartTime = performance.now(); // Track when key was pressed
        wasAutoMoved[e.key] = false; // Reset auto-move flag for tap detection
        dasCounter = 0; // Reset DAS counter when key pressed
        e.preventDefault();
        return;
      }

      // One-time actions
      switch (e.key) {
        case 'ArrowUp':
          network.sendRotate();
          e.preventDefault();
          break;
        case ' ':
          network.sendHardDrop();
          e.preventDefault();
          break;
        case 'Shift':
          network.sendHold();
          e.preventDefault();
          break;
        case 'a':
        case 'A':
          network.sendZoneActivate();
          e.preventDefault();
          break;
      }
    }
  });

  document.addEventListener('keyup', (e) => {
    if (keyState.hasOwnProperty(e.key)) {
      keyState[e.key] = false;
      dasCounter = 0;

      // Tap detection: if key was held for less than DAS_DELAY and not auto-moved,
      // send a single move for tap-based horizontal movement
      if (keyPressStartTime) {
        const pressDuration = performance.now() - keyPressStartTime;
        if (pressDuration < DAS_DELAY && !wasAutoMoved[e.key]) {
          // It was a tap - send single move
          if (e.key === 'ArrowLeft') {
            network.sendMove('left');
          } else if (e.key === 'ArrowRight') {
            network.sendMove('right');
          }
        }
      }
      keyPressStartTime = null;
    }
  });

  // Touch controls for mobile
  const btnLeft = document.getElementById('btn-left');
  const btnRight = document.getElementById('btn-right');
  const btnDown = document.getElementById('btn-down');
  const btnRotate = document.getElementById('btn-rotate');
  const btnDrop = document.getElementById('btn-drop');
  const btnHold = document.getElementById('btn-hold');
  const btnZone = document.getElementById('btn-zone');

  const handleTouch = (e, action) => {
    e.preventDefault();
    e.stopPropagation();
    // Spectators cannot control the game
    if (network.isSpectator) return;
    if (ui.screens.game.classList.contains('active')) {
      action();
    }
  };

  // Use pointerdown for better touch response
  btnLeft.addEventListener('pointerdown', (e) => handleTouch(e, () => network.sendMove('left')));
  btnRight.addEventListener('pointerdown', (e) => handleTouch(e, () => network.sendMove('right')));
  btnDown.addEventListener('pointerdown', (e) => handleTouch(e, () => network.sendDrop()));
  btnRotate.addEventListener('pointerdown', (e) => handleTouch(e, () => network.sendRotate()));
  btnDrop.addEventListener('pointerdown', (e) => handleTouch(e, () => network.sendHardDrop()));
  btnHold.addEventListener('pointerdown', (e) => handleTouch(e, () => network.sendHold()));
  btnZone.addEventListener('pointerdown', (e) => handleTouch(e, () => network.sendZoneActivate()));

  // Prevent double-tap zoom
  btnLeft.addEventListener('touchstart', (e) => e.preventDefault());
  btnRight.addEventListener('touchstart', (e) => e.preventDefault());
  btnDown.addEventListener('touchstart', (e) => e.preventDefault());
  btnRotate.addEventListener('touchstart', (e) => e.preventDefault());
  btnDrop.addEventListener('touchstart', (e) => e.preventDefault());
  btnHold.addEventListener('touchstart', (e) => e.preventDefault());
  btnZone.addEventListener('touchstart', (e) => e.preventDefault());
}

function updateBattleGridLayout(playerCount) {
  ui.displays.battleGrid.classList.remove('single-player', 'two-players', 'multi-player');

  if (playerCount === 1) {
    ui.displays.battleGrid.classList.add('single-player');
  } else if (playerCount === 2) {
    ui.displays.battleGrid.classList.add('two-players');
  } else {
    ui.displays.battleGrid.classList.add('multi-player');
  }
}

function endGame(states) {
  // Find winner
  const activePlayers = Object.values(states).filter(s => !s.eliminated);
  const eliminatedPlayers = Object.values(states).filter(s => s.eliminated);

  let winner = null;
  let scores = {};

  if (activePlayers.length === 1) {
    const winnerState = activePlayers[0];
    const winnerPlayer = network.getPlayer(winnerState.playerId);
    winner = winnerPlayer.name;
  }

  // Build scores list with garbage info
  Object.values(states).forEach(state => {
    const player = network.getPlayer(state.playerId);
    if (player) {
      scores[player.name] = {
        score: state.score,
        garbageReceived: (state.garbageReceived || []).length,
        eliminated: state.eliminated
      };
    }
  });

  // Game music will continue during game over screen, then transition back to lobby music via resetLobbyState

  // Reset spectator mode for next round
  network.isSpectator = false;
  ui.hideSpectatorMode();

  ui.showGameOver(winner, scores);
}

function gameLoop(currentTime) {
  if (!ui.screens.game.classList.contains('active')) {
    return;
  }

  const deltaTime = currentTime - lastTime;
  lastTime = currentTime;

  // Handle DAS (Delayed Auto Shift) for continuous movement
  if (!network.isSpectator && (keyState.ArrowLeft || keyState.ArrowRight || keyState.ArrowDown)) {
    dasCounter += deltaTime;

    // Send initial move immediately, then auto-repeat after DAS_DELAY
    if (dasCounter >= DAS_DELAY) {
      const autoRepeatCounter = (dasCounter - DAS_DELAY) % ARR_SPEED;
      if (autoRepeatCounter < (deltaTime || 0)) {
        if (keyState.ArrowLeft) {
          network.sendMove('left');
          wasAutoMoved.ArrowLeft = true; // Mark as auto-moved so keyup doesn't send another
        }
        if (keyState.ArrowRight) {
          network.sendMove('right');
          wasAutoMoved.ArrowRight = true;
        }
        if (keyState.ArrowDown) {
          network.sendDrop();
          wasAutoMoved.ArrowDown = true;
        }
      }
    }
  }

  // Update local game
  if (localGame) {
    localGame.update(deltaTime);
  }

  // Render all players
  const allStates = network.getAllGameStates();
  Object.values(allStates).forEach(state => {
    renderer.renderPlayer(state.playerId, state);
  });

  // Update Zone button state for current player
  const btnZone = document.getElementById('btn-zone');
  const localState = allStates[network.currentPlayerId];
  if (btnZone && localState) {
    btnZone.disabled = localState.zoneMeter < 100 || localState.zoneActive;
  }

  // Set active player highlight (or null for spectators to show all boards equally)
  renderer.setActivePlayer(network.isSpectator ? null : network.currentPlayerId);

  requestAnimationFrame(gameLoop);
}
