#pragma once
#ifndef SQUARE_H
#define SQUARE_H

#include "shader.hpp"
#include "glm.hpp"
#include "gtx/quaternion.hpp"

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

class Square
{
private:

	Shader* shader;
	uint32_t program;

    //Values needed for Model Matrix
    glm::vec3 position = glm::vec3(0.0f, 1.2f, -1.0f);
    glm::quat rotation = glm::quat(0, 0, 0, 0);
    glm::vec3 scale = glm::vec3(0.8f, 0.8f, 0.8f);

    glm::mat4 model_matrix = glm::mat4(1);

    GLuint vao;
    GLuint vbo;

    GLuint mvp_location;

    GLuint mView_location;
    GLuint mProjection_location;
    GLuint mModel_location;
    GLuint vVertex_location;
    GLuint vColor_location;

    //cube definition
    glm::vec4 vec_points[36];
    glm::vec4 vec_colors[36];
    glm::vec4 vec_positions[8] = {
    glm::vec4(-0.5f, -0.5f,  0.5f, 1.0f),
    glm::vec4(-0.5f,  0.5f,  0.5f, 1.0f),
    glm::vec4(0.5f,  0.5f,  0.5f, 1.0f),
    glm::vec4(0.5f, -0.5f,  0.5f, 1.0f),
    glm::vec4(-0.5f, -0.5f, -0.5f, 1.0f),
    glm::vec4(-0.5f,  0.5f, -0.5f, 1.0f),
    glm::vec4(0.5f,  0.5f, -0.5f, 1.0f),
    glm::vec4(0.5f, -0.5f, -0.5f, 1.0f) };
    glm::vec4 colors[8] = {
            glm::vec4(1.0f, 0.0f, 0.0f, 1.0f),
            glm::vec4(1.0f, 0.0f, 0.0f, 1.0f),
            glm::vec4(0.0f, 1.0f, 0.0f, 1.0f),
            glm::vec4(0.0f, 1.0f, 0.0f, 1.0f),
            glm::vec4(0.0f, 1.0f, 0.0f, 1.0f),
            glm::vec4(0.0f, 0.0f, 1.0f, 1.0f),
            glm::vec4(0.0f, 0.0f, 1.0f, 1.0f),
            glm::vec4(0.0f, 0.0f, 1.0f, 1.0f)
    };

    void quad(int& iIndex, int a, int b, int c, int d)
    {
        vec_colors[iIndex] = colors[a]; vec_points[iIndex] = vec_positions[a]; iIndex++;
        vec_colors[iIndex] = colors[b]; vec_points[iIndex] = vec_positions[b]; iIndex++;
        vec_colors[iIndex] = colors[c]; vec_points[iIndex] = vec_positions[c]; iIndex++;
        vec_colors[iIndex] = colors[a]; vec_points[iIndex] = vec_positions[a]; iIndex++;
        vec_colors[iIndex] = colors[c]; vec_points[iIndex] = vec_positions[c]; iIndex++;
        vec_colors[iIndex] = colors[d]; vec_points[iIndex] = vec_positions[d]; iIndex++;
    }

    void colorcube()
    {
        int iIndex = 0;
        quad(iIndex, 1, 0, 3, 2);
        quad(iIndex, 2, 3, 7, 6);
        quad(iIndex, 3, 0, 4, 7);
        quad(iIndex, 6, 5, 1, 2);
        quad(iIndex, 4, 5, 6, 7);
        quad(iIndex, 5, 4, 0, 1);
    }

public:
    /*
     Constructor: Run when square is created
     inputs:     The shader program for this square
     returns:    None
    */
    Square(Shader* shader);

    Square();

    void initVBO();

    /*
     initVBO:    Initialize the Vertex Array Object
     inputs:     None
     returns:    None
    */
    void initVAO();

    glm::vec3 GetPosition();
    void UpdatePosition(glm::vec3 _position);
    /*
        initVBO:    Draw the Square
        inputs:     View Projection matrix for Camera
        returns:    None
       */
    void draw(glm::mat4 vp_matrix);
    void draw_frame(glm::mat4 v_matrix, glm::mat4 p_matrix);
};

#endif