package electrosphere.game.client.cells;

import electrosphere.collision.dispatch.CollisionObject;
import electrosphere.dynamics.RigidBody;
import electrosphere.entity.Entity;
import electrosphere.entity.EntityDataStrings;
import electrosphere.entity.EntityUtils;
import electrosphere.game.collision.PhysicsUtils;
import electrosphere.game.collision.collidable.Collidable;
import electrosphere.game.terrain.processing.TerrainInterpolator;
import electrosphere.logger.LoggerInterface;
import electrosphere.main.Globals;
import electrosphere.renderer.Mesh;
import electrosphere.renderer.Model;
import electrosphere.renderer.ModelUtils;
import electrosphere.renderer.ShaderProgram;
import electrosphere.renderer.texture.Texture;
import electrosphere.util.Utilities;
import org.joml.Quaternionf;
import org.joml.Vector3f;

/**
 *
 * @author satellite
 */
public class DrawCell {
    int cellX;
    int cellY;
    
    float[][] heightmap;
    float[][] texturemap;
    
    int dynamicInterpolationRatio;
    
    Entity modelEntity;
    
    ShaderProgram program;
    
    CollisionObject physicsObject;
    
    static Texture groundTextureOne = new Texture("/Textures/Ground/GrassTileable.png");
    static Texture groundTextureTwo = new Texture("/Textures/Ground/Dirt1.png");
    static Texture groundTextureThree = new Texture("/Textures/Ground/Dirt1.png");
    static Texture groundTextureFour = new Texture("/Textures/Ground/Dirt1.png");
    
    static {
//        groundTextureOne = new Texture("/Textures/Ground/GrassTileable.png");
//        groundTextureTwo = new Texture("/Textures/Ground/Dirt1.png");
//        groundTextureThree = new Texture("/Textures/Ground/Dirt1.png");
//        groundTextureFour = new Texture("/Textures/Ground/Dirt1.png");
    }
    
    
    DrawCell(){
        
    }
    
    
    /**
     * Catches for this function: drawArray's dimensions need to be equal to drawWidth and 1 greater than cellWidth
     * because the model creation code for terrain heightmaps sucks :D
     * 06/03/2021
     * 
     * 
     * ITS NOT EVEN UP TO DATE!
     * 06/13/2021
     * 
     * //@param drawArray
     */
    public static DrawCell generateTerrainCell(
            int cellX,
            int cellY,
            float[][] heightmap,
            float[][] texturemap,
            int dynamicInterpolationRatio,
            ShaderProgram program
    ){
        DrawCell rVal = new DrawCell();
        rVal.cellX = cellX;
        rVal.cellY = cellY;
        rVal.program = program;
        rVal.dynamicInterpolationRatio = dynamicInterpolationRatio;
        rVal.heightmap = heightmap;
        rVal.texturemap = texturemap;
        return rVal;
    }
    
    /**
     * Generates a drawable entity based on this chunk
     * @param stride The stride between indices used to generate "sparse" meshes
     */
    public void generateDrawableEntity(int stride){
        if(modelEntity != null){
            Globals.entityManager.deregisterEntity(modelEntity);
        }
        Model terrainModel = ModelUtils.createTerrainModelPrecomputedShader(heightmap, texturemap, program, stride);
        Mesh terrainMesh = terrainModel.meshes.get(0);
        terrainMesh.useTextureList = true;
        terrainMesh.textureList.add(groundTextureOne);
        terrainMesh.textureList.add(groundTextureTwo);
        terrainMesh.textureList.add(groundTextureThree);
        terrainMesh.textureList.add(groundTextureFour);
        String terrainModelPath = Globals.assetManager.registerModel(terrainModel);
        modelEntity = EntityUtils.spawnDrawableEntity(terrainModelPath);
        modelEntity.putData(EntityDataStrings.TERRAIN_IS_TERRAIN, true);
        modelEntity.putData(EntityDataStrings.DRAW_CAST_SHADOW, true);
        LoggerInterface.loggerRenderer.INFO("New cell @ " + cellX * dynamicInterpolationRatio + "," + cellY * dynamicInterpolationRatio);
        EntityUtils.getPosition(modelEntity).set(new Vector3f(cellX * dynamicInterpolationRatio, 0.0f, cellY * dynamicInterpolationRatio));
    }
    
    public void retireCell(){
        EntityUtils.cleanUpDrawableEntity(modelEntity);
    }
    
    public void generatePhysics(){
        physicsObject = PhysicsUtils.attachTerrainRigidBody(modelEntity,heightmap);
        Globals.collisionEngine.registerPhysicsEntity(modelEntity);
//        System.out.println("generate physics");
    }
    
    public void destroyPhysics(){
        Globals.collisionEngine.deregisterCollidableEntity(modelEntity);
        Globals.collisionEngine.deregisterRigidBody((RigidBody)physicsObject);
    }
    
}
