package core.engine.renderer;

import core.engine.entity.Entity;
import core.engine.model.RawModel;
import core.engine.model.TexturedModel;
import core.engine.shader.TerrainShader;
import core.engine.terrain.Terrain;
import core.engine.terrain.TerrainTile;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import utils.MatrixGraphicUtils;
import utils.vectors.Matrix4f;
import utils.vectors.Vector3f;

import java.util.List;

public class TerrainRenderer {

    private TerrainShader shader;

    public TerrainRenderer(TerrainShader shader, Matrix4f projectionMatrix) {
        this.shader = shader;
        shader.start();
        shader.loadProjectionMatrix(projectionMatrix);
        shader.stop();
    }

    public void render(List<TerrainTile> terrains) {
        for(TerrainTile terrain : terrains) {
            prepareTerrain(terrain);
            loadModelMatrix(terrain);
            GL11.glDrawElements(GL11.GL_TRIANGLES, terrain.getModel().getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
            unbindTexturedModel();
        }
    }

    private void prepareTerrain(TerrainTile terrainTile) {
        RawModel rawModel = terrainTile.getModel().getRawModel();
        GL30.glBindVertexArray(rawModel.getVaoID());
        GL20.glEnableVertexAttribArray(0);
        GL20.glEnableVertexAttribArray(1);
        GL20.glEnableVertexAttribArray(2);
        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, terrainTile.getModel().getModelTexture().getTextureID());
        shader.loadTerrainColor(terrainTile.getColor());
    }

    private void unbindTexturedModel() {
        GL20.glDisableVertexAttribArray(0);
        GL20.glDisableVertexAttribArray(1);
        GL20.glDisableVertexAttribArray(2);
        GL30.glBindVertexArray(0);
    }

    private void loadModelMatrix(TerrainTile terrain) {
        Matrix4f transformationMatrix = MatrixGraphicUtils.createTransformationMatrix(terrain.getPosition(), terrain.getRotX(),
                terrain.getRotY(), terrain.getRotZ(), terrain.getScale());
        shader.loadTransformationMatrix(transformationMatrix);
    }
}
