/**
 * CLASS ENGINE
 *
 * Classe principale du moteur de jeu
 *
 * @author François Autin
 *
 */
package engine;

import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;

public class Engine {

    private long window;

    private Scene scene;

    private boolean running;

    public Engine(){
        this.running = false;
    }

    private void init() {
        if(!glfwInit()){
            // TODO Erreur d'initialisation
        }
        this.running = true;
        glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //On utilise la version 3.3 d'openGL
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //Compatible MAC
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //Le core profile est l'interface 'avancé' d'openGL

        int width = 800;
        int height = 600;
        this.window = glfwCreateWindow(width, height, "Boulevard Combattant", NULL, NULL);
        assert this.window != NULL;

        // On récupère les informations du moniteur principal
        GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
        assert vidmode != null;

        glfwSetWindowPos(this.window, (vidmode.width() - width)/2, (vidmode.height() - height)/2);

        glfwSetKeyCallback(window, new Input());
        glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);

        // Contexte = zone cible des rendus
        glfwMakeContextCurrent(this.window);
        glfwShowWindow(this.window);
        GL.createCapabilities();

        glfwSetFramebufferSizeCallback(window, resizeWindow);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        System.out.println("OpenGL: " + glGetString(GL_VERSION));

        this.scene = new Scene("shaders/vert.vert", "shaders/frag.frag", Primitive.triangle, Primitive.triangle_indices);

    }

    private void update(){
        glfwPollEvents();
    }

    private void render(){
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT); //SWAP avec le precedent
        scene.render();
        int error = glGetError();
        if (error != GL_NO_ERROR) System.out.println(error);
        glfwSwapBuffers(window); //Envoie le buffer vers le moniteur
    }

    public void run(){
    init();
    while(running){
        update();
        render();
        if(glfwWindowShouldClose(window)) running = false;
        }
    }

    /*
    Est appelé à chaque modification de la taille de la fenêtre, et modifie la taille de la zone de rendu
    pour quelle corresponde à la taille de la fenêtre
     */
    private static final GLFWFramebufferSizeCallback resizeWindow = new GLFWFramebufferSizeCallback(){
        @Override
        public void invoke(long window, int width, int height){
            glViewport(0,0,width,height);
        }
    };

    public static void main(String[] args) {
        Engine engine = new Engine();
        engine.run();
    }

}