#include <GL/glut.h>
#include <GL/gl.h>

#include "Engine.h"
#include "displayers.h"
#include "DataHandling/Texture.h"
#include "DataHandling/Model3D.h"
#include "InputStatus.h"
#include "Camera.h"

volatile unsigned long long int timer_ticks = 0;
static Texture tree_texture;
static Model3D raptor;
static Texture raptor_texture;

void manage_inputs()
{
    if (InputStatus::is_mouse_button_pressed(GLUT_LEFT_BUTTON))
    {
        glClearColor(0,0,0.5,1);
    }
    else if (InputStatus::is_key_pressed(' '))
    {
        glClearColor(0.5,0,0,1);
    }
    else if (InputStatus::is_key_pressed(0x1B))
    {
        glutDestroyWindow(glutGetWindow());
        exit(EXIT_SUCCESS);
    }
    else
    {
        glClearColor(0,0,0,1);
    }

    if (InputStatus::is_special_key_pressed(GLUT_KEY_RIGHT))
    {
        timer_ticks += 5;
        OGLE::camera.local_translate({0, 0, 0.1});
    }
    if (InputStatus::is_special_key_pressed(GLUT_KEY_LEFT))
    {
        timer_ticks -= 5;
        OGLE::camera.local_translate({0, 0, -0.1});
    }
    if (InputStatus::is_key_pressed(' '))
    {
        OGLE::camera.local_translate({0, 0.1, 0});
    }
    if (InputStatus::is_special_key_pressed(GLUT_KEY_PAGE_DOWN))
    {
        OGLE::camera.local_translate({0, -0.1, 0});
    }

    if (InputStatus::is_special_key_pressed(GLUT_KEY_UP))
    {
        OGLE::camera.local_translate({0.1, 0, 0});
    }

    if (InputStatus::is_special_key_pressed(GLUT_KEY_DOWN))
    {
        OGLE::camera.local_translate({-0.1, 0, 0});
    }

    // Get mouse delta since last frame
    static Vec2i mouse_delta;
    mouse_delta = InputStatus::get_mouse_delta(true);
    if (mouse_delta.x != 0 || mouse_delta.y != 0)
    {
        OGLE::camera.rotate({0,
                       -mouse_delta.x / InputStatus::mouse_sensitivity.x,
                       -mouse_delta.y / InputStatus::mouse_sensitivity.y});
    }
}

void display()
{
    manage_inputs();

    float angleY = 1*timer_ticks;

    display_rotating_pyramid(-5,-2,-5,2,4,angleY);
    display_rotating_pyramid(5,-2,0,1,5,angleY);
    display_rotating_pyramid(-2,-2,4,3,2,angleY);

    display_tree(0,-5,0,3,5,tree_texture);

    glPushMatrix();
    glRotatef(angleY,0,-1,0);
    raptor.draw_model();
    glPopMatrix();
}

void update_angle(int value)
{
    timer_ticks++;
    glutTimerFunc(50,update_angle,0);
}

int main(int argc, char** argv)
{
    OGLE::setup(argc,argv,display);

    // Load and generate tree texture
    tree_texture.load_rgba_tga("resources/arbre.tga","resources/arbre_masque.tga");
    glGenTextures(1,tree_texture.opengl_id);
    // TODO : Put in the Texture class
    glBindTexture(GL_TEXTURE_2D,tree_texture.opengl_id[0]);
    gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8,tree_texture.width,tree_texture.height,GL_RGBA,GL_UNSIGNED_BYTE,tree_texture.image_data);

    // Load and generate raptor texture
    raptor_texture.load_rgb_tga("resources/RAPTOR.tga");
    glGenTextures(1, raptor_texture.opengl_id);
    // TODO : Put in the Texture class
    glBindTexture(GL_TEXTURE_2D, raptor_texture.opengl_id[0]);
    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, raptor_texture.width, raptor_texture.height, GL_RGB, GL_UNSIGNED_BYTE, raptor_texture.image_data);

    // Load raptor model
    raptor.load_ascii_off_file("resources/RAPTOR.off");
    raptor.assign_texture(raptor_texture);
    raptor.set_scaling(0.01,0.01,0.01);
    raptor.set_rotation(-90,1,0,0);


    glutTimerFunc(50,update_angle,0);


    // Enters main loop, managed by GLUT
    glutMainLoop();
	return 0;
}
