/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#ifndef RENDERSCENE_H
#define RENDERSCENE_H

#include "Shaders.h"
#include "Common.h"
#include "Texture.h"
#include "Camera.h"
#include "LoadScene.h"
#include "FPSCounter.h"

using namespace glTF;

class RenderPrimitive
{
public:
    class Material* getMaterial();
    void setMaterial(class Material* pMaterial);

    unsigned int getVerterCount();
    void setVerterCount(unsigned int count);

    unsigned int getIndicesCount();
    void setIndicesCount(unsigned int count);

    unsigned int getShaderVertexId();
    void setShaderVertexId(unsigned int id);

    unsigned int getShaderNormalId();
    void setShaderNormalId(unsigned int id);

    unsigned int getShaderCoord0Id();
    void setShaderCoord0Id(unsigned int id);

    unsigned int getVertexBuffer();
    void setVertexBuffer(unsigned int bufferId);

    unsigned int getNormalBuffer();
    void setNormalBuffer(unsigned int bufferId);

    unsigned int getTexCoordBuffer();
    void setTexCoordBuffer(unsigned int bufferId);

    unsigned int getIndicesBuffer();
    void setIndicesBuffer(unsigned int bufferId);

    DataType_E getIndicesDataType();
    void setIndicesDataType(DataType_E type);

    void setProject(glm::mat4* pProject);
    glm::mat4* getProject();

    void setColor(glm::vec3* pColor);
    glm::vec3* getColor();

    void setMatrix(glm::mat4* pMatrix);
    glm::mat4* getMatrix();
    
    RenderPrimitive();
    ~RenderPrimitive();
private:
    glm::mat4* pMatrix;
    glm::mat4* pProject;
    glm::vec3* pColor;
    class Material* pMaterial;
    DataType_E mIndicesDataType;
    unsigned int mVerterCount;
    unsigned int mIndicesCount;
    unsigned int mShaderVertexId;
    unsigned int mShaderNormalId;
    unsigned int mShaderCoord0Id;
    unsigned int mVertexBuffer;
    unsigned int mNormalBuffer;
    unsigned int mTexCoordBuffer;
    unsigned int mIndicesBuffer;
};

class RenderScene
{
public:
    void getCameraPos(glm::vec3* Eye,glm::vec3* view,glm::vec3* up);
    glTFHandle* initScene(const glTFFile* jsonfile);
    void initRender(glTFHandle* handle);

    void render(void* lpParam);
    void releaseRender(void* lpParam);
    CPhysicalCamera* getCamera();
    void renderToBuffer(glTFViewport* pViewpoit, unsigned char * buffer);
    void renderRotateCamera(double horizontal, double vertical,
        double planar, double time);
    void renderMoveCamera(double x, double y, double z, double time);
    RenderScene();
    ~RenderScene();
private:
    Parser loadJson;
    CPhysicalCamera* pCamera;
    Light* pLight;

    void initOpengl();
    class Scene* loadScene(const std::string& directory, const std::string& file);
    class Scene* loadScene(glTFHandle* handle);
    void createDefaultLight();
    void createDefaultCamera();
    void constructMesh(const std::string meshName, glm::mat4* pmatrix);
    void constructPrimitive(const Primitives* pPrim, glm::mat4* pmatrix);
    void setPrimitiveVec(class RenderPrimitive* pPrim);
    class RenderPrimitive* getPrimitiveVec(unsigned int index);
    unsigned int getPrimitiveVecSize();
    unsigned int bindAttribute(const class Attribute* pAttr);
    unsigned int bindIndices(const class Attribute* pAttr);
    void getAttributeShaderId(class Material* pMaterial, class RenderPrimitive* pRP);
    void bindAttributeBuffer(const Primitives* pPrimitive, class RenderPrimitive* pRP);
    void upLoadAttribute(unsigned int shaderId, unsigned int bufferId, int size);
    void drawTriangle(class RenderPrimitive* pPrimitive);
    void renderPrimitive(class RenderPrimitive* pPrimitive);
    glm::mat4* calcProjectionMatrix();
    glm::vec3* calcLightColor();
    bool loadFPSShader();
    bool setStates(Technique* pTechnique);
    void timeStampStart();
    void timeStampEnd();
    int getFPS();
    void printFPS( glTFViewport* pViewpoit );
    void createTextureObj(int width, int height);
    void createRenderObj(int width, int height);
    bool createFrameBufferObj(int width, int height);
    std::vector<class RenderPrimitive*> mPrimitiveVec;
    class ShaderProgram mShaderProgram;
    class Scene* pScene;
    GLuint mFBOID;
    GLuint mTextureObj;
    GLuint mRBOID;
    FPSCounter *pFPSCounter;
};

#endif
