package electrosphere.net.client.protocol;


import org.joml.Vector3f;

import electrosphere.client.scene.ClientWorldData;
import electrosphere.client.terrain.cache.ChunkData;
import electrosphere.collision.CollisionWorldData;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.net.template.ClientProtocolTemplate;

/**
 * The client protocol for handling terrain messages
 */
public class TerrainProtocol implements ClientProtocolTemplate<TerrainMessage> {

    @Override
    public TerrainMessage handleAsyncMessage(TerrainMessage message) {
        return message;
    }

    @Override
    public void handleSyncMessage(TerrainMessage message) {
        Globals.profiler.beginCpuSample("TerrainProtocol.handleTerrainMessage");
        switch(message.getMessageSubtype()){
            case RESPONSEMETADATA:
                Globals.clientWorldData = new ClientWorldData(
                        //Vector3f worldMinPoint, Vector3f worldMaxPoint, int dynamicInterpolationRatio, float randomDampener, int worldDiscreteSize
                        new Vector3f(message.getworldMinX(),0,message.getworldMinY()),
                        new Vector3f(message.getworldMaxX(),3,message.getworldMaxY()),
                        ChunkData.CHUNK_SIZE,
                        message.getrandomDampener(),
                        message.getworldSizeDiscrete()
                );
                Globals.clientSceneWrapper.getCollisionEngine().setCollisionWorldData(new CollisionWorldData(Globals.clientWorldData));
                Globals.clientConnection.getMessageProtocol().setHasReceivedWorld(true);
                break;
            case SPAWNPOSITION:
                LoggerInterface.loggerNetworking.WARNING("Received spawnPosition packet on client. This is deprecated!");
                break;
            case SENDCHUNKDATA:
                Globals.clientTerrainManager.attachTerrainMessage(message);
                break;
            case UPDATEVOXEL: {
                if(Globals.clientTerrainManager.containsChunkDataAtWorldPoint(message.getworldX(), message.getworldY(), message.getworldZ())){
                    ChunkData data = Globals.clientTerrainManager.getChunkDataAtWorldPoint(message.getworldX(), message.getworldY(), message.getworldZ());
                    if(data != null){
                        data.updatePosition(
                            message.getvoxelX(),
                            message.getvoxelY(),
                            message.getvoxelZ(),
                            message.getterrainWeight(),
                            message.getterrainValue()
                        );
                        Globals.drawCellManager.markUpdateable(message.getworldX(), message.getworldY(), message.getworldZ());
                    }
                }
            } break;
            case SENDFLUIDDATA: {
                Globals.clientFluidManager.attachFluidMessage(message);
            } break;
            case UPDATEFLUIDDATA: {
                Globals.clientFluidManager.attachFluidMessage(message);
            } break;
            default:
                LoggerInterface.loggerNetworking.WARNING("Client networking: Unhandled message of type: " + message.getMessageSubtype());
                break;
        }
        Globals.profiler.endCpuSample();
    }

}
