#include <iostream>

#include <QKeyEvent>
#include <QImage>
#include <QMessageBox>
#include <eigen3/Eigen/Geometry>
#include <fstream>
#include <vector>
#include "OpenGL.h"
#include "glview.h"
#include "fbo.h"

using namespace Eigen;

GLView::GLView(QWidget *parent)
    : QGLWidget(parent),
      _initGL(false)
{
}

GLView::~GLView()
{
}

void GLView::setScene(int scene)
{
    switch (scene) {
    case 1:
        _scene = Scene1();
        break;
    case 2:
        _scene = Scene2();
        break;
    case 3:
        _scene = Scene3();
        break;
    }
    updateGL();
}


void GLView::colorPicking(Vector2i mouse_coord)
{
    makeCurrent();

    // init fbo
    FBO* image = new FBO();
    image->init(_scene._camera.vpWidth(),
                _scene._camera.vpHeight(),
                GL_RGBA32F, GL_RGBA, GL_FLOAT);
    GL_TEST_ERR;

    // use fbo
    image->beginCapture();

    // init render
    glDisable(GL_BLEND);
    glClearColor(0.,0.,0.,1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0, 0,
               _scene._camera.vpWidth(),
               _scene._camera.vpHeight());
    activeShaderObject();
    GL_TEST_ERR;

    // TODO : draw each object with



    // texture reading
    glUseProgram(0); GL_TEST_ERR;
    image->endCapture(); GL_TEST_ERR;
    image->bindTexture();

    // TODO : retrieve color under mouse coords
    QImage img = Texture2D::currentFrame();




    // TODO : compute id associated to the color




    // TODO : retrive the associated object




    //Free memory
    delete image;
}

void GLView::initializeGL()
{
    if(!_initGL)
    {
        makeCurrent();
        std::cout << "Using OpenGL version: \"" << glGetString(GL_VERSION) << "\"" << std::endl;

        glEnable(GL_DEPTH_TEST);
        glClearColor(0.,0.,0.,0);

        // load shader
        _scene.loadShaders();

        // load texture
        QImage img;
        img.load(TEXTURE_WOOD);
        _texture.load(img);

        _initGL = true;
    }
}

void GLView::resizeGL(int width, int height)
{
    _scene._camera.setViewport(width, height);
}

void GLView::paintGL()
{
    if(!_scene._program.valid())
        return;

    makeCurrent();

    /********** DRAW THE SCENE ***********/
    glClearColor(0.,0.,0.,0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glViewport(0, 0, _scene._camera.vpWidth(), _scene._camera.vpHeight());

    activeShaderObject();

    // draw frame
    glDisable(GL_BLEND);
    _scene._frame.draw();

    // draw objects
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    for(uint i=0 ; i<_scene._objs.size() ; ++i)
        _scene._objs[i].draw();

    GL_TEST_ERR;
}

void GLView::activeShaderObject()
{
    _scene._program.activate();

    // camera information
    glUniformMatrix4fv(glGetUniformLocation(_scene._program.id(),"mat_view"), 1, GL_FALSE, _scene._camera.viewMatrix().data());
    glUniformMatrix4fv(glGetUniformLocation(_scene._program.id(),"mat_proj"), 1, GL_FALSE, _scene._camera.projectionMatrix().data());
    GL_TEST_ERR;

    // texture
    glActiveTexture(GL_TEXTURE0);
    _texture.bind();
    glUniform1i(glGetUniformLocation(_scene._program.id(), "texture"), 0);
    GL_TEST_ERR;
}
