// Network module - Socket.io client handling

class NetworkManager {
  constructor() {
    this.socket = null;
    this.currentPlayerId = null;
    this.isSpectator = false;
    this.players = {};
    this.spectators = {};
    this.gameState = {};
    this.listeners = {
      onPlayerJoined: null,
      onPlayerLeft: null,
      onGameStarted: null,
      onStateUpdate: null,
      onGameOver: null,
      onSpectatorJoined: null,
      onSpectatorLeft: null,
      onForcedSpectator: null
    };
  }

  connect() {
    this.socket = io();

    this.socket.on('connect', () => {
      console.log('Connected to server');
      this.currentPlayerId = this.socket.id;
    });

    this.socket.on('disconnect', () => {
      console.log('Disconnected from server');
    });

    this.socket.on('player-joined', ({ player, players }) => {
      this.updatePlayers(players);
      if (this.listeners.onPlayerJoined) {
        this.listeners.onPlayerJoined(player);
      }
    });

    this.socket.on('player-left', ({ playerId, players }) => {
      delete this.players[playerId];
      this.updatePlayers(players);
      if (this.listeners.onPlayerLeft) {
        this.listeners.onPlayerLeft(playerId);
      }
    });

    this.socket.on('game-started', ({ players, states }) => {
      this.updatePlayers(players);
      this.updateStates(states);
      if (this.listeners.onGameStarted) {
        this.listeners.onGameStarted(players, states);
      }
    });

    this.socket.on('state-update', (states) => {
      this.updateStates(states);
      if (this.listeners.onStateUpdate) {
        this.listeners.onStateUpdate(states);
      }
    });

    this.socket.on('game-over', (data) => {
      if (this.listeners.onGameOver) {
        this.listeners.onGameOver(data);
      }
    });

    // Forced spectator mode - game already in progress
    this.socket.on('forced-spectator', ({ spectatorId, states, players }) => {
      this.isSpectator = true;
      this.updateStates(states);
      this.updatePlayers(players);
      if (this.listeners.onForcedSpectator) {
        this.listeners.onForcedSpectator({ states, players });
      }
    });

    // Spectator joined
    this.socket.on('spectator-joined', ({ spectator, spectators }) => {
      this.updateSpectators(spectators);
      if (this.listeners.onSpectatorJoined) {
        this.listeners.onSpectatorJoined(spectator);
      }
    });

    // Spectator left
    this.socket.on('spectator-left', ({ spectatorId, spectators }) => {
      delete this.spectators[spectatorId];
      this.updateSpectators(spectators);
      if (this.listeners.onSpectatorLeft) {
        this.listeners.onSpectatorLeft(spectatorId);
      }
    });
  }

  joinLobby(playerName) {
    if (!this.socket) return;
    this.socket.emit('join-lobby', { playerName });
  }

  leaveLobby() {
    if (!this.socket) return;
  }

  ready() {
    if (!this.socket) return;
    this.socket.emit('ready');
  }

  unready() {
    if (!this.socket) return;
    this.socket.emit('unready');
  }

  sendMove(direction) {
    if (!this.socket || !this.currentPlayerId) return;
    this.socket.emit('player-move', { playerId: this.currentPlayerId, direction });
  }

  sendRotate() {
    if (!this.socket || !this.currentPlayerId) return;
    this.socket.emit('player-rotate', { playerId: this.currentPlayerId });
  }

  sendDrop() {
    if (!this.socket || !this.currentPlayerId) return;
    this.socket.emit('player-drop', { playerId: this.currentPlayerId, hard: false });
  }

  sendHardDrop() {
    if (!this.socket || !this.currentPlayerId) return;
    this.socket.emit('player-drop', { playerId: this.currentPlayerId, hard: true });
  }

  sendHold() {
    if (!this.socket || !this.currentPlayerId) return;
    this.socket.emit('player-hold', { playerId: this.currentPlayerId });
  }

  sendZoneActivate() {
    if (!this.socket || !this.currentPlayerId) return;
    this.socket.emit('zone-activate', { playerId: this.currentPlayerId });
  }

  updatePlayers(players) {
    this.players = {};
    players.forEach(p => {
      this.players[p.id] = p;
    });
  }

  updateStates(states) {
    states.forEach(s => {
      this.gameState[s.playerId] = s;
    });
  }

  updateSpectators(spectators) {
    this.spectators = {};
    spectators.forEach(s => {
      this.spectators[s.id] = s;
    });
  }

  getPlayer(playerId) {
    return this.players[playerId];
  }

  getGameState(playerId) {
    return this.gameState[playerId];
  }

  getAllPlayers() {
    return this.players;
  }

  getAllGameStates() {
    return this.gameState;
  }

  getAllSpectators() {
    return this.spectators;
  }

  setListener(event, callback) {
    const listenerMap = {
      'player-joined': 'onPlayerJoined',
      'player-left': 'onPlayerLeft',
      'game-started': 'onGameStarted',
      'state-update': 'onStateUpdate',
      'game-over': 'onGameOver',
      'forced-spectator': 'onForcedSpectator',
      'spectator-joined': 'onSpectatorJoined',
      'spectator-left': 'onSpectatorLeft'
    };
    if (callback) {
      this.listeners[listenerMap[event]] = callback;
    }
  }
}

const network = new NetworkManager();
