#ifndef MESH_H
#define MESH_H

#include <QtOpenGL>
#include <QOpenGLFunctions_4_3_Core>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <postprocess.h>
#include "texture.h"

#define positionIndex 0
#define normalIndex 1
#define uvIndex 2
#define boneIndex 3
#define boneweightIndex 4


struct Vertex
{
    QVector3D pos;
    QVector3D normal;
    QVector2D tex;
    uint IDs[4];
    float weights[4];

    Vertex() {
        for(int i = 0; i < 4; i++){
            IDs[i] = 0;
            weights[i] = 0;
        }
    }

    Vertex(const QVector3D& pos, const QVector3D& normal, const QVector2D& tex)
    {
        this->pos    = pos;
        this->tex    = tex;
        this->normal = normal;
    }

     void AddBoneData(uint BoneID, float Weight);
};

class Mesh
{
public:
    Mesh(QOpenGLFunctions_4_3_Core *f,QString filename);
    ~Mesh();



    void render(QOpenGLShaderProgram *shader, QMatrix4x4 V,QMatrix4x4 P);

private:


    struct MeshEntry{
        MeshEntry();
        ~MeshEntry();

        void init(QOpenGLFunctions_4_3_Core *f,QVector<Vertex>& Vertices,
                  QVector<unsigned int>& Indices);

        QString name;
        GLuint VB;
        GLuint IB;

        int numIndex;
        int materialIndex;
        QOpenGLFunctions_4_3_Core *f;
    };

    struct MaterialInfo
    {
        MaterialInfo();
        QString Name;
        QVector3D Diffuse;
        QVector3D Specular;
        bool hasTexture;
        Texture texture;
        float Shininess;
    };

    struct LightInfo
    {
        QVector4D Position;
        QVector3D Intensity;
    };

    struct Node
    {
        Node();
        QString name;
        QMatrix4x4 transformation;
        QVector<int> meshes;
        QVector<Node> children;
    };

    const aiScene *scene;
    QMatrix4x4 globalInverseTransform;


    QVector<MeshEntry> entries;
    QVector<MaterialInfo> materials;
    Node rootNode;
    QOpenGLFunctions_4_3_Core *f;
    bool loaded;

    void initMeshEntry(int i,aiMesh * entry);
    void initMaterial(QString dir, unsigned int i, const aiMaterial* material);
    void initNode(const aiScene *scene, aiNode *node, Node &newNode);

    void renderNode(QOpenGLShaderProgram *shader, Node &node, QMatrix4x4 V,QMatrix4x4 P,QMatrix4x4 M);
    void renderMesh(QOpenGLShaderProgram *shader, int index);

};

#endif // MESH_H
