package com.zombie.game.systems;

import com.zombie.game.ecs.ECSWorld;
import com.zombie.game.ecs.System;
import com.zombie.game.ecs.components.*;

import java.util.*;

/**
 * Collects and serializes game state for network synchronization.
 * 收集并序列化游戏状态以进行网络同步。
 */
public class StateSyncSystem implements System {

    /**
     * Builds a map representing the current game state including all players and zombies.
     */
    public Map<String, Object> buildGameState(ECSWorld world) {
        Map<String, Object> state = new LinkedHashMap<>();

        // Players
        List<Map<String, Object>> playerStates = new ArrayList<>();
        for (int entityId : world.getPlayers()) {
            Map<String, Object> map = new LinkedHashMap<>();
            Position pos = world.getPositions().get(entityId);
            Health health = world.getHealths().get(entityId);

            String playerId = null;
            for (var entry : world.getPlayerIdToEntity().entrySet()) {
                if (entry.getValue() == entityId) {
                    playerId = entry.getKey();
                    break;
                }
            }

            map.put("id", playerId);
            if (pos != null) {
                map.put("x", pos.getX());
                map.put("y", pos.getY());
                map.put("angle", pos.getAngle());
            }
            if (health != null) {
                map.put("health", health.getHealth());
            }

            PlayerInput input = world.getPlayerInputs().get(entityId);
            if (input != null) {
                map.put("lastProcessedSeq", input.getSeq());
            }

            playerStates.add(map);
        }

        // Zombies (only alive)
        List<Map<String, Object>> zombieStates = new ArrayList<>();
        for (int entityId : world.getZombies()) {
            Health health = world.getHealths().get(entityId);
            if (health == null || !health.isAlive()) continue;

            Map<String, Object> map = new LinkedHashMap<>();
            Position pos = world.getPositions().get(entityId);

            map.put("id", entityId);
            if (pos != null) {
                map.put("x", pos.getX());
                map.put("y", pos.getY());
                map.put("angle", pos.getAngle());
            }
            map.put("health", health.getHealth());
            map.put("maxHealth", health.getMaxHealth());

            zombieStates.add(map);
        }

        // Nut walls
        List<Map<String, Object>> nutWallStates = new ArrayList<>();
        for (Map.Entry<Integer, Health> entry : world.getHealths().entrySet()) {
            int entityId = entry.getKey();
            // Skip non-wall entities (players and zombies have health too)
            if (world.getPlayers().contains(entityId) || world.getZombies().contains(entityId)) continue;
            if (!world.getBlocksMovements().containsKey(entityId)) continue;

            Health health = entry.getValue();
            Position pos = world.getPositions().get(entityId);
            if (pos == null) continue;

            Map<String, Object> wallState = new LinkedHashMap<>();
            wallState.put("id", entityId);
            wallState.put("x", (int) Math.floor(pos.getX()));
            wallState.put("y", (int) Math.floor(pos.getY()));
            wallState.put("health", health.getHealth());
            wallState.put("maxHealth", health.getMaxHealth());
            nutWallStates.add(wallState);
        }

        state.put("players", playerStates);
        state.put("zombies", zombieStates);
        state.put("nutWalls", nutWallStates);
        state.put("gameTime", world.getGameTime());

        return state;
    }

    @Override
    public void update(float dt, ECSWorld world) {
        // No per-frame logic; state is built on demand
    }
}
