// This code example is created for educational purpose
// by Thorsten Thormaehlen (contact: www.thormae.de).
// It is distributed without any warranty.

#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_1>
#include <QKeyEvent>
#include <QTimer>
#include <QMessageBox>

#include <iostream>
using namespace std;
#include <math.h>

class Renderer : protected QOpenGLFunctions_3_1 {

private:
  struct Vertex
  {
    float position[3];
    float color[4];
  };

public:
  float t;
private:
  enum {Triangle, numVAOs};
  enum {TriangleAll, numVBOs};
  GLuint vaoID[numVAOs];
  GLuint bufID[numVBOs];
  int triangleVertNo;

public:
  // constructor
  Renderer() : t(0.0), triangleVertNo(0) {}

public:
  void init() {
    initializeOpenGLFunctions();
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_DEPTH);

    // create a Vertex Array Objects (VAO)
    glGenVertexArrays(numVAOs, vaoID);

    // generate a Vertex Buffer Object (VBO)
    glGenBuffers(numVBOs, bufID);

    // binding the Triangle VAO
    glBindVertexArray(vaoID[Triangle]);

    float triangleVertexData[] = {
       0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
      -0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
       0.5f,-0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
    };
    triangleVertNo = 3;

    glBindBuffer(GL_ARRAY_BUFFER, bufID[TriangleAll]);
    glBufferData(GL_ARRAY_BUFFER, triangleVertNo*sizeof(Vertex),
                 triangleVertexData, GL_STATIC_DRAW);

    int stride = sizeof(Vertex);

    // position
    int vertexLoc = 0;
    glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, stride, NULL);
    glEnableVertexAttribArray(vertexLoc);
  }


  void resize(int w, int h) {
    glViewport(0, 0, w, h);
  }

  void display() {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // bind Triangle VAO
    glBindVertexArray(vaoID[Triangle]);
    // render data
    glDrawArrays(GL_TRIANGLES, 0, triangleVertNo);
  }

  void dispose() {
    glDeleteVertexArrays(numVAOs, vaoID);
    glDeleteBuffers(numVBOs, bufID);
  }
};


class MyWidget : public QOpenGLWidget {

private:
  Renderer *renderer;

public:
  MyWidget(QWidget *parent = NULL) : QOpenGLWidget(parent) {
    this->setWindowTitle("First OpenGL 3 Forward Compatible Example");
    this->resize(320, 320);
    renderer = new Renderer();
  }

  ~MyWidget() {
    makeCurrent();
    renderer->dispose();
    doneCurrent();
    delete renderer;
  }

protected:
  void initializeGL() { renderer->init(); }
  void resizeGL(int w, int h){ renderer->resize(w, h); }
  void paintGL() { renderer->display();}
};

int main (int argc, char* argv[]) {
    // create a QApplication object that handles initialization,
    // finalization, and the main event loop
    QApplication appl(argc, argv);
    MyWidget widget;  // create a widget
    widget.show(); //show the widget and its children
    return appl.exec(); // execute the application
}
