/*
 * 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/.
 */
#include <fstream>
#include "LoadScene.h"
#pragma warning(disable : 4996)

Parser::Parser()
{
}

Parser::~Parser()
{
}

void Parser::setJsonInfo(const std::string& sbuffer)
{
    this->json_buffer = sbuffer;
    is_json_in_buffer = true;
}

void Parser::setJsonInfo(std::string direct, std::string fileName)
{
    this->json_directory = direct;
    this->json_file = fileName;
    is_json_in_buffer = false;
}

bool Parser::parseJsonFile()
{
    try
    {
        if(is_json_in_buffer)
        {
            std::stringstream ss(this->json_buffer);
            boost::property_tree::json_parser::read_json(ss, ptParse);
        }
        else
        {
            std::string jsonfile = this->json_directory + this->json_file;
            boost::property_tree::json_parser::read_json(jsonfile.c_str(), ptParse);
        }
    }
    catch(boost::property_tree::ptree_error & e) 
    {
        fprintf(stderr, "%s\n",e.what());
        return false;
    }
    catch (boost::exception const&)
    {
        fprintf(stderr, "%s\n", "unknown boost error");
        return false;
    }

    return true;
}

glTFHandle* Parser::getFileNameInJson(const std::string& jsonFile)
{
    glTFHandle* gHandle = (glTFHandle*)malloc(sizeof(glTFHandle));

    boost::property_tree::ptree pImagesTree = ptParse.get_child("images");
    boost::property_tree::ptree pBuffersTree = ptParse.get_child("buffers");
    boost::property_tree::ptree pShadersTree = ptParse.get_child("shaders");
    gHandle->size = pImagesTree.size()+pBuffersTree.size()+pShadersTree.size()+1;

    unsigned int index = 0;
    gHandle->files = (glTFFile**)malloc(gHandle->size*sizeof(glTFFile*));
    gHandle->files[index] = (glTFFile*)malloc(sizeof(glTFFile));
    gHandle->files[index]->type = GLTF_JSON;
    gHandle->files[index]->filename = (char*)malloc(jsonFile.size()+1);
    sprintf(gHandle->files[index++]->filename, "%s" , jsonFile.c_str());

    for (boost::property_tree::ptree::iterator it = pImagesTree.begin();
        it != pImagesTree.end(); ++it)
    {
        boost::property_tree::ptree pImageTree = it->second;
        std::string path = pImageTree.get<std::string>("path");
        gHandle->files[index] = (glTFFile*)malloc(sizeof(glTFFile));
        gHandle->files[index]->type = GLTF_IMAGE;
        gHandle->files[index]->filename = (char*)malloc(path.size()+1);
        sprintf(gHandle->files[index++]->filename, "%s" , path.c_str());
    }

    for (boost::property_tree::ptree::iterator it = pBuffersTree.begin();
        it != pBuffersTree.end(); ++it)
    {
        boost::property_tree::ptree pBufferTree = it->second;
        std::string path = pBufferTree.get<std::string>("path");
        gHandle->files[index] = (glTFFile*)malloc(sizeof(glTFFile));
        gHandle->files[index]->type = GLTF_BINARY;
        gHandle->files[index]->filename = (char*)malloc(path.size()+1);
        sprintf(gHandle->files[index++]->filename, "%s" , path.c_str());
    }

    for (boost::property_tree::ptree::iterator it = pShadersTree.begin();
        it != pShadersTree.end(); ++it)
    {
        glTFFile* glFile = new glTFFile();
        boost::property_tree::ptree pShaderTree = it->second;
        std::string path = pShaderTree.get<std::string>("path");
        gHandle->files[index] = (glTFFile*)malloc(sizeof(glTFFile));
        gHandle->files[index]->type = GLTF_GLSL;
        gHandle->files[index]->filename = (char*)malloc(path.size()+1);
        sprintf(gHandle->files[index++]->filename, "%s" , path.c_str());
    }

    return gHandle;
}

bool Parser::releaseFileName()
{
    glTFHandle *gHandle= pScene->getGltfHandle();
    /*for(int i = 0; i < (int)gHandle->size; i++)
    {
        if(gHandle->files[i]->filename  != NULL) 
        {
            free(gHandle->files[i]->filename);
            gHandle->files[i]->filename = NULL;
        }
        if(gHandle->files[i] !=NULL)
        {
            free(gHandle->files[i]);
            gHandle->files[i] = NULL;
        }
    }
    
    if(gHandle->files != NULL) 
    {
        free(gHandle->files);
        gHandle->files = NULL;
    }*/
    return true;
}
bool Parser::parseScene(class Scene* pscene)
{

    if (0 == pscene)
        return false;
    this->pScene = pscene;
    // node
    if(!this->parseNodes()) return false;
    // mesh
    if(!this->parseMeshs()) return false;
    // Material
    if(!this->parseMaterials()) return false;
    // Camera
    if (ptParse.find("cameras") != ptParse.not_found())
    {
        if(!this->parseCameras()) 
            return false;
    }
    // Light
    if (ptParse.find("lights") != ptParse.not_found())
    {
        if(!this->parseLights())
            return false;
    }
    // buffer
    if(!this->readBuffers()) return false;
    // Attribute
    if(!this->parseAttributes()) return false;
    // Shader
    if(!this->parseTechniques()) return false;


    return true;
}

bool Parser::parseNodes()
{
    glm::mat4 matrix = glm::mat4(1.0f);
    class Node* pRootNode = new Node();
    std::string sceneId = ptParse.get<std::string>("scene");
    std::string pathNode = "scenes." + sceneId + ".nodes";
    boost::property_tree::ptree pNodeArray = ptParse.get_child(pathNode.c_str());
    for (boost::property_tree::ptree::iterator it = pNodeArray.begin();
        it != pNodeArray.end(); ++it)
    {
        this->parseNode(it->second.data(), pRootNode, &matrix);
    }
    this->pScene->setRootNode(pRootNode);
    return true;
}

bool Parser::parseNode(std::string& id, class Node* pParentNode, glm::mat4* parentMatrix)
{
    class Node* pNode = new Node();
    glm::mat4* pmatrix;

    std::string nodeId = "nodes." + id;
    boost::property_tree::ptree pNodeAtrr = ptParse.get_child(nodeId.c_str());

    if (pNodeAtrr.find("name") != pNodeAtrr.not_found())                    //-- name
    {
        pNode->setNodeName(pNodeAtrr.get<std::string>("name"));
    }

    if (pNodeAtrr.find("matrix") != pNodeAtrr.not_found())                  //-- matrix
    {
        boost::property_tree::ptree pMatrix = pNodeAtrr.get_child("matrix");
        float matrix[16];
        unsigned int i = 0;
        for (boost::property_tree::ptree::iterator it = pMatrix.begin();
            it != pMatrix.end(); ++it)
        {
            matrix[i++] = (it->second).get_value<float>();
        }
        pmatrix = (glm::mat4*) new glm::mat4;
        memcpy(pmatrix, matrix, sizeof(glm::mat4));
        *pmatrix = (*parentMatrix) * (*pmatrix);
        pNode->setMatrix(pmatrix);
    }

    boost::property_tree::ptree pNodeChildren;
    if (pNodeAtrr.find("children") != pNodeAtrr.not_found()                 //-- children
        && 0 != pNodeAtrr.get_child("children").size())
    {
        pNode->setNodeType(NodeType_Node);
        pNodeChildren = pNodeAtrr.get_child("children");
        for (boost::property_tree::ptree::iterator it = pNodeChildren.begin();
            it != pNodeChildren.end(); ++it)
        {
            parseNode(it->second.data(), pNode, pmatrix);
        }
    }

    if (pNodeAtrr.find("meshes") != pNodeAtrr.not_found())             //-- meshes
    {
        pNode->setNodeType(NodeType_Mesh);
        boost::property_tree::ptree pMeshes = pNodeAtrr.get_child("meshes");
        for (boost::property_tree::ptree::iterator it = pMeshes.begin(); it != pMeshes.end(); ++it)
        {
            pNode->pushMeshIndex(it->second.data());
        }
    }
    else if (pNodeAtrr.find("light") != pNodeAtrr.not_found())              //-- light
    {
        pNode->setLightIndex(pNodeAtrr.get<std::string>("light"));
        pNode->setNodeType(NodeType_Light);
        pParentNode->setLightFlag();
    }
    else if (pNodeAtrr.find("camera") != pNodeAtrr.not_found())             //-- camera
    {
        pNode->setCameraIndex(pNodeAtrr.get<std::string>("camera"));
        pNode->setNodeType(NodeType_Camera);
    }	

    pParentNode->pushChildNode(pNode);
    pNode->setParentNode(pParentNode);
    this->pScene->pushNode(pNode);
    return true;
}

bool Parser::parseMeshs()
{
    boost::property_tree::ptree pMeshsTree = ptParse.get_child("meshes");
    for (boost::property_tree::ptree::iterator it = pMeshsTree.begin();
        it != pMeshsTree.end(); ++it)
    {
        class Mesh* pMesh = new Mesh();

        boost::property_tree::ptree pMeshTree = it->second;
        pMesh->setMeshName(pMeshTree.get<std::string>("name"));
        parsePrimitive(pMeshTree.get_child("primitives"), pMesh);

        this->pScene->insertMeshMap(it->first, pMesh);
    }
    return true;
}

bool Parser::parsePrimitive(boost::property_tree::ptree& pTree, class Mesh* pMesh)
{
    for (boost::property_tree::ptree::iterator it = pTree.begin(); it != pTree.end(); ++it)
    {
        class Primitives* pPrim= new Primitives();

        boost::property_tree::ptree pPrimTree = it->second;
        boost::property_tree::ptree pPrimValueTree = pPrimTree.get_child("attributes");
        if (pPrimValueTree.find("NORMAL") != pPrimValueTree.not_found())
        {
            pPrim->insertAttribute("NORMAL", pPrimValueTree.get<std::string>("NORMAL"));
        }
        if (pPrimValueTree.find("POSITION") != pPrimValueTree.not_found())
        {
            pPrim->insertAttribute("POSITION", pPrimValueTree.get<std::string>("POSITION"));
        }
        if (pPrimValueTree.find("TEXCOORD_0") != pPrimValueTree.not_found())
        {
            pPrim->insertAttribute("TEXCOORD_0", pPrimValueTree.get<std::string>("TEXCOORD_0"));
        }
        pPrim->setIndicesIndex(pPrimTree.get<std::string>("indices"));
        pPrim->setMaterialIndex(pPrimTree.get<std::string>("material"));

        pMesh->setPrimitiveVec(pPrim);
    }
    return true;
}

bool Parser::parseMaterials()
{
    std::string techniqueId;
    boost::property_tree::ptree pMaterialsTree = ptParse.get_child("materials");
    for (boost::property_tree::ptree::iterator it = pMaterialsTree.begin();
        it != pMaterialsTree.end(); ++it)
    {
        class Material* pMaterial = new Material();

        boost::property_tree::ptree pMaterialTree = it->second;
        techniqueId = pMaterialTree.get<std::string>("instanceTechnique.technique");
        parseMaterialProper(pMaterialTree.get_child("instanceTechnique.values"),
            pMaterial, techniqueId);

        pMaterial->setTechniqueId(techniqueId);
        this->pScene->insertMaterialMap(it->first, pMaterial);
    }
    return true;
}

bool Parser::parseMaterialProper(boost::property_tree::ptree& pTree, 
class Material* pMaterial, std::string& techniqueId)
{
    float* pBuffer;
    for (boost::property_tree::ptree::iterator it = pTree.begin(); it != pTree.end(); ++it)
    {
        class MaterialProperty* pMaterialProper = new MaterialProperty();

        std::string typePath = "techniques." + techniqueId + ".parameters." + it->first + ".type";
        unsigned int type = ptParse.get<unsigned int>(typePath.c_str());
        pMaterialProper->setPropertyName(it->first);
        switch (type)
        {
        case DataType_SAMPLER_2D:
            {
                std::string textureId = it->second.data();
                std::string textureSource = "textures." + textureId + ".source";
                std::string imageId = ptParse.get<std::string>(textureSource.c_str());
                std::string imagePath = "images." + imageId + ".path";
                pMaterialProper->setImagePath(ptParse.get<std::string>(imagePath.c_str()));
                pMaterialProper->setDataLength(0);
                pMaterialProper->setDataType(DataType_SAMPLER_2D);
                pScene->loadTexture(pMaterialProper->getImagePath());
            }
            break;
        case DataType_FLOAT:
            {
                pMaterialProper->setDataLength(sizeof(float));
                pBuffer = new float;
                *pBuffer = (it->second).get_value<float>();
                pMaterialProper->setPropertyData((char*)pBuffer);
                pMaterialProper->setDataType(DataType_FLOAT);
            }
            break;
        case DataType_FLOAT_VEC4:
            {
                pMaterialProper->setDataLength(sizeof(float)*4);			
                boost::property_tree::ptree pValue = it->second;
                unsigned int i = 0;
                pBuffer = new float[4];
                for (boost::property_tree::ptree::iterator iter = pValue.begin();
                    iter != pValue.end(), i < 4; ++iter, ++i)
                {
                    pBuffer[i] = (iter->second).get_value<float>();
                }
                pMaterialProper->setPropertyData((char*)pBuffer);
                pMaterialProper->setDataType(DataType_FLOAT_VEC4);
            }
            break;
        default:
            break;
        }
        pMaterial->pushMaterialProper(pMaterialProper);
    }

    return true;
}

bool Parser::parseCameras()
{
    boost::property_tree::ptree pCamerasTree = ptParse.get_child("cameras");
    for (boost::property_tree::ptree::iterator it = pCamerasTree.begin();
        it != pCamerasTree.end(); ++it)
    {
        class Camera* pCamera = new Camera();

        boost::property_tree::ptree pCameraTree = it->second;
        std::string type = pCameraTree.get<std::string>("type");
        boost::property_tree::ptree pCameraAttrTree = pCameraTree.get_child(type.c_str());

        if (pCameraAttrTree.find("aspect_ratio") == pCameraAttrTree.not_found())
        {
            pCamera->setXFov(pCameraAttrTree.get<float>("xfov"));
            pCamera->setYFov(pCameraAttrTree.get<float>("yfov"));
        }
        else
        {
            pCamera->setAspectRatio(pCameraAttrTree.get<float>("aspect_ratio"));
            if (pCameraAttrTree.find("xfov") != pCameraAttrTree.not_found())
            {
                pCamera->setXFov(pCameraAttrTree.get<float>("xfov"));
                pCamera->setYFov(pCamera->getXFov() * pCamera->getAspectRatio());
            }
            else
            {
                pCamera->setYFov(pCameraAttrTree.get<float>("yfov"));
                pCamera->setXFov(pCamera->getYFov() / pCamera->getAspectRatio());
            }
        }
        pCamera->setFar(pCameraAttrTree.get<float>("zfar"));
        pCamera->setNear(pCameraAttrTree.get<float>("znear"));

        this->pScene->insertCameraMap(it->first, pCamera);
    }
    return true;
}

Light* GetParseLight( boost::property_tree::ptree pRoot
                     ,LightSourceType_E NodeType
                     ,const char* ChildName)
{
    unsigned int i;
    Vector3D LightPos;
    float *fLight = new float[4];
    memset(fLight, 0, sizeof(float)*4);
    class Light *pLight = new Light();
    pLight->setType(NodeType);
    boost::property_tree::ptree pParseLight = pRoot.get_child(ChildName);
    if (pParseLight.find("color") != pParseLight.not_found())
    {
        i = 0;
        boost::property_tree::ptree color = pParseLight.get_child("color");
        for (boost::property_tree::ptree::iterator it = color.begin();
            it != color.end(); it++, i++)
        {
            fLight[i] = (it->second).get_value<float>();
        }
        pLight->setColorAmbient((GLfloat*)&fLight[0]);
        pLight->setColorDiffuse((GLfloat*)&fLight[1]);
        pLight->setColorSpecular((GLfloat*)&fLight[2]);
    }
    if (pParseLight.find("position") != pParseLight.not_found())
    {
        i = 0;
        boost::property_tree::ptree pos = pParseLight.get_child("position");
        for (boost::property_tree::ptree::iterator it = pos.begin();
            it != pos.end(); it++, i++)
        {
            fLight[i] = (it->second).get_value<float>();
        }
        if (i >= 3)
        {
            pLight->setPositions((GLfloat*)fLight);
        }
        else
        {
            LightPos.x = fLight[0];
            LightPos.y = fLight[1];
            LightPos.z = fLight[2];
            pLight->setPosition(LightPos);
        }
    }
    return pLight;
}

bool Parser::parseLights()
{
    boost::property_tree::ptree pLightsTree = ptParse.get_child("lights");
    for (boost::property_tree::ptree::iterator it = pLightsTree.begin();
        it != pLightsTree.end(); ++it)
    {
        class Light* pLight = new Light();

        boost::property_tree::ptree pLightTree = it->second;

        if (pLightTree.find("point") != pLightTree.not_found())
        {
            pLight = GetParseLight(pLightTree, LightSource_POINT, "point");
        }
        else if (pLightTree.find("directional") != pLightTree.not_found())
        {
            pLight = GetParseLight(pLightTree, LightSource_DIRECTIONAL, "directional");
        }

        this->pScene->insertLightMap(it->first, pLight);
    }
    return true;
}

bool Parser::parseAttributes()
{
    //we suppose that there is only one xxx.bin. todo
    boost::property_tree::ptree pAttrsTree = ptParse.get_child("accessors");
    for (boost::property_tree::ptree::iterator it = pAttrsTree.begin();
        it != pAttrsTree.end(); ++it)
    {
        class Attribute* pAttribute = new Attribute();

        boost::property_tree::ptree pAttrTree = it->second;
        //get offset and length of bufferview.
        std::string bufferView = "bufferViews." + pAttrTree.get<std::string>("bufferView");
        boost::property_tree::ptree pBufferView = ptParse.get_child(bufferView.c_str());
        unsigned int bufferByteLength = pBufferView.get<unsigned int>("byteLength");
        unsigned int bufferByteOffset = pBufferView.get<unsigned int>("byteOffset");

        //get offset, count and type... we need to read the data from xxx.bin.
        unsigned int attrByteOffset = pAttrTree.get<unsigned int>("byteOffset");
        unsigned int count = pAttrTree.get<unsigned int>("count");	
        unsigned int type = pAttrTree.get<unsigned int>("type");
        unsigned int byteStride = 2;
        if (pAttrTree.find("byteStride") != pAttrTree.not_found())
        {
            byteStride = pAttrTree.get<unsigned int>("byteStride");
        }

        char* pbuffer = this->pScene->getBuffer(0) + bufferByteOffset + attrByteOffset;
        switch (type)
        {
        case DataType_FLOAT_VEC3:
            pAttribute->setAttributeData(pbuffer, count*byteStride);
            pAttribute->setDataType(DataType_FLOAT_VEC3);
            break;
        case DataType_FLOAT_VEC2:
            pAttribute->setAttributeData(pbuffer, count*byteStride);
            pAttribute->setDataType(DataType_FLOAT_VEC2);
            break;
        case DataType_UNSIGNED_SHORT:
            pAttribute->setAttributeData(pbuffer, count*byteStride);
            pAttribute->setDataType(DataType_UNSIGNED_SHORT);
        default:
            std::cout << "Attribute Type:" << type << std::endl;
        }
        pAttribute->setDataCount(count);
        pAttribute->setByteStride(byteStride);
  
        //max
        if (DataType_FLOAT_VEC3 == type && pAttrTree.find("max") != pAttrTree.not_found())
        {
            float max[3];
            boost::property_tree::ptree pMaxTree = pAttrTree.get_child("max");
            unsigned int i = 0;
            for (boost::property_tree::ptree::iterator it = pMaxTree.begin();
                it != pMaxTree.end(); ++it)
            {
                max[i++] = (it->second).get_value<float>();
            }
            this->pScene->setVertexMax(max[0], max[1], max[2]);
        }
        //min
        if (DataType_FLOAT_VEC3 == type && pAttrTree.find("min") != pAttrTree.not_found())
        {
            float min[3];
            boost::property_tree::ptree pMinTree = pAttrTree.get_child("min");
            unsigned int i = 0;
            for (boost::property_tree::ptree::iterator it = pMinTree.begin();
                it != pMinTree.end(); ++it)
            {
                min[i++] = (it->second).get_value<float>();
            }
            this->pScene->setVertexMin(min[0], min[1], min[2]);
        }

        this->pScene->insertAttributeMap(it->first, pAttribute);
    }
    return true;
}

bool Parser::parseTechniques()
{
    boost::property_tree::ptree pTechniquesTree = ptParse.get_child("techniques");
    for (boost::property_tree::ptree::iterator it = pTechniquesTree.begin();
        it != pTechniquesTree.end(); ++it)
    {
        class Technique* pTechnique = new Technique();

        boost::property_tree::ptree pTechniqueTree = it->second;
        std::string passId = pTechniqueTree.get<std::string>("pass");
        std::string passPath = "passes." + passId + ".instanceProgram";
        boost::property_tree::ptree pInstanceTree = pTechniqueTree.get_child(passPath.c_str());
        boost::property_tree::ptree pParameterTree = pTechniqueTree.get_child("parameters");
        parseTechniqueProgram(pInstanceTree, pParameterTree, pTechnique);
        std::string statePath = "passes."+passId+".states";
        boost::property_tree::ptree pStateTree = pTechniqueTree.get_child(statePath.c_str());
        parseTechniqueState(pStateTree,pTechnique);

        this->pScene->insertTechniqueMap(it->first, pTechnique);
    }
    return true;
}

bool Parser::parseTechniqueState(boost::property_tree::ptree& pInstanceTree, class Technique* pTechnique)
{
    for (boost::property_tree::ptree::iterator it = pInstanceTree.begin();
        it != pInstanceTree.end(); ++it)
    {
        if ("blendFunc" == it->first)
        {
            boost::property_tree::ptree dfactorNode = pInstanceTree.get_child("blendFunc.dfactor");
            boost::property_tree::ptree sfactorNode = pInstanceTree.get_child("blendFunc.sfactor");
            pTechnique->getTechState()->blendFuncDfactor = dfactorNode.get_value<unsigned int>();
            pTechnique->getTechState()->blendFuncSfactor = sfactorNode.get_value<unsigned int>();
            continue;
        }

        if ("blendEnable" == it->first)
        {
            pTechnique->getTechState()->blendEnable = it->second.get_value<unsigned int>();
            continue;
        }

        if ("blendEquation" == it->first)
        {
            pTechnique->getTechState()->blendEquation= it->second.get_value<unsigned int>();
            continue;
        }

        if ("cullFaceEnable" == it->first)
        {
            pTechnique->getTechState()->cullFaceEnable= it->second.get_value<unsigned int>();
            continue;
        }

        if ("depthMask" == it->first)
        {
            pTechnique->getTechState()->depthMask= it->second.get_value<unsigned int>();
            continue;
        }

        if ("depthTestEnable" == it->first)
        {
            pTechnique->getTechState()->depthTestEnable= it->second.get_value<unsigned int>();
            continue;
        }
    }
    return true;
}

bool Parser::parseTechniqueProgram(boost::property_tree::ptree& pInstanceTree, 
    boost::property_tree::ptree& pParameterTree, 
    class Technique* pTechnique)
{
    // [instanceProgram/attributes]
    boost::property_tree::ptree pAttrsTree = pInstanceTree.get_child("attributes");
    for (boost::property_tree::ptree::iterator it = pAttrsTree.begin();
        it != pAttrsTree.end(); ++it)
    {
        std::string parameterId = it->second.data();
        boost::property_tree::ptree pParaTree = pParameterTree.get_child(parameterId.c_str());
        if (pParaTree.find("semantic") != pParaTree.not_found())
        {
            class TechAttribute* pTechAttribute = new TechAttribute();
            pTechAttribute->setAttributeIndex(pParaTree.get<std::string>("semantic"));
            pTechAttribute->setAttributeName(it->first);
            pTechnique->insertTechAttribute(it->first, pTechAttribute);
        }
    }

    // [instanceProgram/uniforms]
    boost::property_tree::ptree pUniformsTree = pInstanceTree.get_child("uniforms");
    for (boost::property_tree::ptree::iterator it = pUniformsTree.begin();
        it != pUniformsTree.end(); ++it)
    {
        class TechUniform* pTechUniform = new TechUniform();
        pTechUniform->setUniformIndex(it->second.data());
        pTechUniform->setUniformName(it->first);
        pTechnique->setTechUniform(pTechUniform);
    }

    // [instanceProgram/program]
    std::string programId = "programs." + pInstanceTree.get<std::string>("program");
    boost::property_tree::ptree pProgramTree = ptParse.get_child(programId.c_str());
    std::string verId = "shaders." + pProgramTree.get<std::string>("vertexShader") + ".path";
    std::string fraId = "shaders." + pProgramTree.get<std::string>("fragmentShader") + ".path";
    pTechnique->setVertexShader(ptParse.get<std::string>(verId.c_str()));
    pTechnique->setFragmentShader(ptParse.get<std::string>(fraId.c_str())); 

    pTechnique->initTechnique(pScene->getGltfHandle());
    
    return true;
}

bool Parser::readBuffers()
{
    unsigned int length = 0;
    std::string binName;
    boost::property_tree::ptree pBuffers = ptParse.get_child("buffers");
    for (boost::property_tree::ptree::iterator it = pBuffers.begin();
        it != pBuffers.end(); ++it)
    {
        boost::property_tree::ptree pbuffer = it->second;
        binName = pbuffer.get<std::string>("path");
        length = pbuffer.get<unsigned int>("byteLength");
    }
    char* pbuffer = this->pScene->getBuffer(length);
    if(!is_json_in_buffer)
    {
        std::fstream file;
        std::string binfile = this->json_directory + binName;
        file.open(binfile.c_str(), std::ios::binary|std::ios::in);
        file.read(pbuffer, length);
        file.close();
        return true;
    }
    else
        return this->pScene->setBuffer(binName,length);

    return false;
}