/// Inlcudes
#include <iostream>
#include "MicroGlut.h"
#include "GL_utilities.h"


/// Defines
#define ARRAY_COUNT(ARRAY) (sizeof(ARRAY)/sizeof(*(ARRAY)))


/// Globals
GLuint  vertexArray;
GLfloat positions[][3] =
{
    {-0.5f, -0.5f, 0.0f},
    {-0.5f, +0.5f, 0.0f},
    {+0.5f, -0.5f, 0.0f},
};


/// Debug message callback
void APIENTRY debugMessageCallback(
    GLenum          /* source    */,
    GLenum          /* type      */,
    GLuint          /* id        */,
    GLenum          /* severity  */,
    GLsizei         /* length    */,
    GLchar  const *    message,
    void    const * /* userParam */
)
{
    std::cerr << message << std::endl;
}


/// Init
void init(void)
{
    // Debug message callback.
    // Requires OpenGL 4.3 or the GL_KHR_debug extension (which is not hardware
    // dependent and supported almost everywhere *except* MacOS).
    glEnable(GL_DEBUG_OUTPUT);
    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    glDebugMessageCallback(debugMessageCallback, nullptr);

    // GL inits.
    glClearColor(0.2, 0.2, 0.5, 0.0);
    glDisable(GL_DEPTH_TEST);

    // Load and compile shader.
    GLuint program = loadShaders("tsbk07.vert", "tsbk07.frag");

    // Allocate and activate Vertex Array Object (VAO), used for uploading
    // the geometry.
    glGenVertexArrays(1, &vertexArray);
    glBindVertexArray(vertexArray);

    // Allocate and activate Vertex Buffer Objects (VBO), for vertex data.
    GLint  positionLocation = glGetAttribLocation(program, "inPosition");
    GLuint positionBuffer;
    glGenBuffers(1, &positionBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(positionLocation);
}


/// Display
void display(void)
{
    // Clear the screen.
    glClear(GL_COLOR_BUFFER_BIT);

    // Select VAO.
    glBindVertexArray(vertexArray);

    // Draw.
    glDrawArrays(GL_TRIANGLES, 0, ARRAY_COUNT(positions));

    // Show on the screen.
    glutSwapBuffers();
}


/// Main
int main(int argc, char * argv[])
{
    glutInit(&argc, argv);
    glutInitContextVersion(3, 2);
    glutInitWindowSize(600, 600);
    glutCreateWindow("TSBK07");

    glutDisplayFunc(display);

    dumpInfo();
    init();
    glutMainLoop();
}
