# client/src/networked_players.py
import pygame
from client.src.player import Player

# A factor for how quickly other players snap to their real position.
# Lower is smoother but laggier, higher is snappier but more jittery.
LERP_FACTOR = 0.25 

class NetworkedPlayers:
    def __init__(self, my_char_id):
        """
        Manages all remote players on the map.
        
        Args:
            my_char_id (int): The character ID of the local player, to avoid managing them here.
        """
        self.other_players = {} # Key: char_id, Value: Player object
        self.my_char_id = my_char_id

    def _add_or_update_player(self, player_data):
        """A helper function to create a new player sprite or update an existing one."""
        if not player_data:
            return
            
        char_id = player_data.get("id")
        print(f"[DEBUG-NET] Received update network player, char_id {char_id}: {player_data}")
        
        # This is the most important check: NEVER manage our own player here.
        if char_id == self.my_char_id:
            return

        # Check if we already have a sprite for this player
        player_sprite = self.other_players.get(char_id)

        if player_sprite:
            # Set their target position for smooth interpolation
            player_sprite.target_x = player_data.get("x")
            player_sprite.target_y = player_data.get("y")
            
            # player_sprite.state = player_data.get("state") 
            # player_sprite.direction = player_data.get("direction")
        else:
            # --- CREATE NEW PLAYER ---
            new_sprite = Player.from_dict(player_data)
            
            # Set both current and target positions to prevent weird initial slide
            new_sprite.target_x = player_data.get("x")
            new_sprite.target_y = player_data.get("y")

            self.other_players[char_id] = new_sprite
            print(f"[Network] Created sprite for new player {player_data.get('name')} (ID: {char_id})")

    def handle_snapshot(self, players_data):
        """Handles the initial batch of players already on the map."""
        print(f"[Network] Handling player snapshot with {len(players_data)} players.")
        # Clear any old data
        self.other_players.clear()
        # Create sprites for everyone in the list
        for player_data in players_data:
            self._add_or_update_player(player_data)

    def handle_spawn(self, player_data):
        """Handles a single new player entering the map."""
        self._add_or_update_player(player_data)
        
    def handle_update(self, player_data):
        """Handles a state update for an existing player."""
        self._add_or_update_player(player_data)

    def handle_despawn(self, char_id):
        """Handles a player leaving the map."""
        if char_id in self.other_players:
            despawned_player = self.other_players.pop(char_id)
            print(f"[Network] Removed sprite for player (ID: {char_id})")

    def update(self, dt):
        """Called every frame to update animations and interpolate positions."""
        for player in self.other_players.values():
            # Smoothly move the player towards their server-authoritative position
            player.x += (player.target_x - player.x) * LERP_FACTOR
            player.y += (player.target_y - player.y) * LERP_FACTOR
        
            player.update_animation()

    def draw(self, surface, cam_x, cam_y):
        """Called every frame to draw all other players."""
        for player in self.other_players.values():
            player.draw(surface, offset_x=-cam_x, offset_y=-cam_y)