package electrosphere.game.server.datacell;

import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.game.collision.CommonWorldData;
import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.main.Globals;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.server.Player;
import java.util.LinkedList;
import java.util.List;
import org.joml.Vector3d;
import org.joml.Vector3f;

/**
 *
 * @author satellite
 */
public class DataCellManager {
    
    List<ServerDataCell> loadedDataCells = new LinkedList();
    ServerDataCell[][] dataCells;
    int discreteWorldSize;
    
    List<Player> playerList = new LinkedList();
    
    public DataCellManager(ServerWorldData data) {
        discreteWorldSize = data.getWorldSizeDiscrete();
        dataCells = new ServerDataCell[discreteWorldSize][discreteWorldSize];
    }
    
    
    public void addPlayer(Player player){
        playerList.add(player);
        int playerSimulationRadius = player.getSimulationRadius();
        int oldX = player.getWorldX();
        int oldY = player.getWorldY();
        for(int x = oldX - playerSimulationRadius; x < oldX + playerSimulationRadius + 1; x++){
            for(int y = oldY - playerSimulationRadius; y < oldY + playerSimulationRadius + 1; y++){
                if(
                        x >= 0 && x < discreteWorldSize &&
                        y >= 0 && y < discreteWorldSize
                        ){
                    LoggerInterface.loggerEngine.DEBUG("DataCellManager: Add player to " + x + " " + y);
                    if(dataCells[x][y] != null){
                        dataCells[x][y].addPlayer(player);
                    } else {
                        //create data cell
                        dataCells[x][y] = ServerDataCell.loadCellAtWorldCoord(x, y);
                        //add player
                        dataCells[x][y].addPlayer(player);
                    }
                }
            }
        }
    }
    
    public void movePlayer(Player player, int newX, int newY){
        int playerSimulationRadius = player.getSimulationRadius();
        int oldX = player.getWorldX();
        int oldY = player.getWorldY();
        player.setWorldX(newX);
        player.setWorldY(newY);
//        System.out.println("=======" + "SET" + newX + " " + newY + " FROM " + oldX + " " + oldY + "========");
        int removals = 0;
        int additions = 0;
        for(int x = oldX - playerSimulationRadius; x < oldX + playerSimulationRadius + 1; x++){
            for(int y = oldY - playerSimulationRadius; y < oldY + playerSimulationRadius + 1; y++){
                if(
                        x >= 0 && x < discreteWorldSize && 
                        y >= 0 && y < discreteWorldSize &&
                        (x < newX - playerSimulationRadius || x > newX + playerSimulationRadius || y < newY - playerSimulationRadius || y > newY + playerSimulationRadius)
                        ){
                    if(dataCells[x][y] != null){
                        if(dataCells[x][y].containsPlayer(player)){
                            removals++;
                            dataCells[x][y].removePlayer(player);
                        }
                    }
                }
            }
        }
        for(int x = newX - playerSimulationRadius; x < newX + playerSimulationRadius + 1; x++){
            for(int y = newY - playerSimulationRadius; y < newY + playerSimulationRadius + 1; y++){
                if(
                        x >= 0 && x < discreteWorldSize &&
                        y >= 0 && y < discreteWorldSize &&
                        (x < oldX - playerSimulationRadius || x > oldX + playerSimulationRadius || y < oldY - playerSimulationRadius || y > oldY + playerSimulationRadius)
                        ){
//                    System.out.println("Add player to " + x + " " + y);
                    if(dataCells[x][y] != null){
                        dataCells[x][y].addPlayer(player);
                    } else {
                        //create data cell
                        dataCells[x][y] = ServerDataCell.loadCellAtWorldCoord(x, y);
                        //add player
                        dataCells[x][y].addPlayer(player);
                    }
                    additions++;
                } else {
//                    System.out.println(x + "\t" + (oldX - playerSimulationRadius) + "\t" + (oldX + playerSimulationRadius));
//                    System.out.println(y + "\t" + (oldY - playerSimulationRadius) + "\t" + (oldY + playerSimulationRadius));
                }
            }
        }
//        System.out.println("removals: " + removals + "\tadditions: " + additions);
    }
    
    public void removePlayer(Player player){
        throw new UnsupportedOperationException("Removing players from the data cell manager isn't supported -- DataCellManager -- removePlayer(Player player)");
    }
    
    public boolean updatePlayerPositions(){
        boolean playerChangedChunk = false;
        for(Player player : playerList){
            Entity playerEntity = player.getPlayerEntity();
            if(playerEntity != null){
                Vector3d position = EntityUtils.getPosition(playerEntity);
                int currentWorldX = Globals.serverWorldData.convertRealToChunkSpace(position.x);
                int currentWorldY = Globals.serverWorldData.convertRealToChunkSpace(position.z);
                if(currentWorldX != player.getWorldX() || currentWorldY != player.getWorldY()){
                    movePlayer(player,currentWorldX,currentWorldY);
                    playerChangedChunk = true;
                }
            }
        }
        return playerChangedChunk;
    }
    
    public void sendNetworkMessageToChunk(NetworkMessage message, int worldX, int worldY){
        if(dataCells[worldX][worldY] != null){
            dataCells[worldX][worldY].broadcastNetworkMessage(message);
        }
    }
    
    public void unloadPlayerlessChunks(){
        
    }
    
}
