﻿/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------

Copyright (c) 2006-2017, assimp team

All rights reserved.

Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:

* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.

* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.

* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

----------------------------------------------------------------------
*/

#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <rapidjson/prettywriter.h>

namespace glTF2 {

    using rapidjson::StringBuffer;
    using rapidjson::PrettyWriter;
    using rapidjson::Writer;
    using rapidjson::StringRef;
    using rapidjson::StringRef;

    namespace {

        template<size_t N>
        inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
            val.SetArray();
            val.Reserve(N, al);
            for (decltype(N) i = 0; i < N; ++i) {
                val.PushBack(r[i], al);
            }
            return val;
        }

        inline Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
            val.SetArray();
            val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
            for (unsigned int i = 0; i < r.size(); ++i) {
                val.PushBack(r[i], al);
            }
            return val;
        }

        inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& /*al*/) {
            val.SetDouble(r);

            return val;
        }

        template<class T>
        inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) {
            if (v.empty()) return;
            Value lst;
            lst.SetArray();
            lst.Reserve(unsigned(v.size()), al);
            for (size_t i = 0; i < v.size(); ++i) {
                lst.PushBack(v[i]->index, al);
            }
            obj.AddMember(StringRef(fieldId), lst, al);
        }


    }

    inline void Write(Value& obj, Accessor& a, AssetWriter& w)
    {
        obj.AddMember("bufferView", a.bufferView->index, w.mAl);
        obj.AddMember("byteOffset", a.byteOffset, w.mAl);

        obj.AddMember("componentType", int(a.componentType), w.mAl);
        obj.AddMember("count", a.count, w.mAl);
        obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);

        Value vTmpMax, vTmpMin;
        obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
        obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
    }

    inline void Write(Value& obj, Animation& a, AssetWriter& w)
    {
        /****************** Channels *******************/
        Value channels;
        channels.SetArray();
        channels.Reserve(unsigned(a.Channels.size()), w.mAl);

        for (size_t i = 0; i < unsigned(a.Channels.size()); ++i) {
            Animation::AnimChannel& c = a.Channels[i];
            Value valChannel;
            valChannel.SetObject();
            {
                valChannel.AddMember("sampler", c.sampler, w.mAl);

                Value valTarget;
                valTarget.SetObject();
                {
                    valTarget.AddMember("node", c.target.node->index, w.mAl);
                    valTarget.AddMember("path", c.target.path, w.mAl);
                }
                valChannel.AddMember("target", valTarget, w.mAl);
            }
            channels.PushBack(valChannel, w.mAl);
        }
        obj.AddMember("channels", channels, w.mAl);

        /****************** Samplers *******************/
        Value valSamplers;
        valSamplers.SetArray();

        for (size_t i = 0; i < unsigned(a.Samplers.size()); ++i) {
            Animation::AnimSampler& s = a.Samplers[i];
            Value valSampler;
            valSampler.SetObject();
            {
                Ref<Accessor> inputAccessor = a.GetAccessor(s.input);
                Ref<Accessor> outputAccessor = a.GetAccessor(s.output);
                valSampler.AddMember("input", inputAccessor->index, w.mAl);
                valSampler.AddMember("interpolation", s.interpolation, w.mAl);
                valSampler.AddMember("output", outputAccessor->index, w.mAl);
            }
            valSamplers.PushBack(valSampler, w.mAl);
        }
        obj.AddMember("samplers", valSamplers, w.mAl);
    }

    inline void Write(Value& obj, Buffer& b, AssetWriter& w)
    {
        obj.AddMember("byteLength", static_cast<uint64_t>(b.byteLength), w.mAl);
        obj.AddMember("uri", Value(b.GetURI(), w.mAl).Move(), w.mAl);
    }

    inline void Write(Value& obj, BufferView& bv, AssetWriter& w)
    {
        obj.AddMember("buffer", bv.buffer->index, w.mAl);
        obj.AddMember("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl);
        obj.AddMember("byteLength", static_cast<uint64_t>(bv.byteLength), w.mAl);
        if (bv.byteStride != 0) {
            obj.AddMember("byteStride", bv.byteStride, w.mAl);
        }
        obj.AddMember("target", int(bv.target), w.mAl);
    }

    inline void Write(Value& /*obj*/, Camera& /*c*/, AssetWriter& /*w*/)
    {

    }

    inline void Write(Value& obj, Image& img, AssetWriter& w)
    {
        std::string uri;
        if (img.HasData()) {
            uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
            uri += ";base64,";
            Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
        }
        else {
            uri = img.uri;
        }

        obj.AddMember("uri", Value(uri, w.mAl).Move(), w.mAl);
    }

    namespace {
        inline void SetTexBasic(TextureInfo t, Value& tex, MemoryPoolAllocator<>& al)
        {
            tex.SetObject();
            tex.AddMember("index", t.texture->index, al);

            if (t.texCoord != 0) {
                tex.AddMember("texCoord", t.texCoord, al);
            }
        }

        inline void WriteTex(Value& obj, TextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
        {

            if (t.texture) {
                Value tex;

                SetTexBasic(t, tex, al);

                obj.AddMember(StringRef(propName), tex, al);
            }
        }

        inline void WriteTex(Value& obj, NormalTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
        {

            if (t.texture) {
                Value tex;

                SetTexBasic(t, tex, al);

                if (t.scale != 1) {
                    tex.AddMember("scale", t.scale, al);
                }

                obj.AddMember(StringRef(propName), tex, al);
            }
        }

        inline void WriteTex(Value& obj, OcclusionTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
        {

            if (t.texture) {
                Value tex;

                SetTexBasic(t, tex, al);

                if (t.strength != 1) {
                    tex.AddMember("strength", t.strength, al);
                }

                obj.AddMember(StringRef(propName), tex, al);
            }
        }

        template<size_t N>
        inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, MemoryPoolAllocator<>& al)
        {
            Value arr;
            obj.AddMember(StringRef(propName), MakeValue(arr, prop, al), al);
        }

        template<size_t N>
        inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, const float(&defaultVal)[N], MemoryPoolAllocator<>& al)
        {
            if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) {
                WriteVec(obj, prop, propName, al);
            }
        }

        inline void WriteFloat(Value& obj, float prop, const char* propName, MemoryPoolAllocator<>& al)
        {
            Value num;
            obj.AddMember(StringRef(propName), MakeValue(num, prop, al), al);
        }
    }

    inline void Write(Value& obj, Material& m, AssetWriter& w)
    {
        Value pbrMetallicRoughness;
        pbrMetallicRoughness.SetObject();
        {
            WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorTexture, "baseColorTexture", w.mAl);
            WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl);
            WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultBaseColor, w.mAl);

            if (m.pbrMetallicRoughness.metallicFactor != 1) {
                WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicFactor, "metallicFactor", w.mAl);
            }

            if (m.pbrMetallicRoughness.roughnessFactor != 1) {
                WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.roughnessFactor, "roughnessFactor", w.mAl);
            }
        }

        if (!pbrMetallicRoughness.ObjectEmpty()) {
            obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl);
        }

        WriteTex(obj, m.normalTexture, "normalTexture", w.mAl);
        WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl);
        WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl);
        WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl);

        if (m.alphaCutoff != 0.5) {
            WriteFloat(obj, m.alphaCutoff, "alphaCutoff", w.mAl);
        }

        if (m.alphaMode != "OPAQUE") {
            obj.AddMember("alphaMode", Value(m.alphaMode, w.mAl).Move(), w.mAl);
        }

        if (m.doubleSided) {
            obj.AddMember("doubleSided", m.doubleSided, w.mAl);
        }

        Value exts;
        exts.SetObject();

        if (m.pbrSpecularGlossiness.isPresent) {
            Value pbrSpecularGlossiness;
            pbrSpecularGlossiness.SetObject();

            PbrSpecularGlossiness &pbrSG = m.pbrSpecularGlossiness.value;

            //pbrSpecularGlossiness
            WriteVec(pbrSpecularGlossiness, pbrSG.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl);
            WriteVec(pbrSpecularGlossiness, pbrSG.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl);

            if (pbrSG.glossinessFactor != 1) {
                WriteFloat(obj, pbrSG.glossinessFactor, "glossinessFactor", w.mAl);
            }

            WriteTex(pbrSpecularGlossiness, pbrSG.diffuseTexture, "diffuseTexture", w.mAl);
            WriteTex(pbrSpecularGlossiness, pbrSG.specularGlossinessTexture, "specularGlossinessTexture", w.mAl);

            if (!pbrSpecularGlossiness.ObjectEmpty()) {
                exts.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl);
            }
        }

        if (!exts.ObjectEmpty()) {
            obj.AddMember("extensions", exts, w.mAl);
        }
    }

    namespace {
        inline void WriteAttrs(AssetWriter& w, Value& attrs, Mesh::AccessorList& lst,
            const char* semantic, bool forceNumber = false)
        {
            if (lst.empty()) return;
            if (lst.size() == 1 && !forceNumber) {
                attrs.AddMember(StringRef(semantic), lst[0]->index, w.mAl);
            }
            else {
                for (size_t i = 0; i < lst.size(); ++i) {
                    char buffer[32];
                    ai_snprintf(buffer, 32, "%s_%d", semantic, int(i));
                    attrs.AddMember(Value(buffer, w.mAl).Move(), lst[i]->index, w.mAl);
                }
            }
        }
    }

    inline void Write(Value& obj, Mesh& m, AssetWriter& w)
    {
		/****************** Primitives *******************/
        Value primitives;
        primitives.SetArray();
        primitives.Reserve(unsigned(m.primitives.size()), w.mAl);

        for (size_t i = 0; i < m.primitives.size(); ++i) {
            Mesh::Primitive& p = m.primitives[i];
            Value prim;
            prim.SetObject();
            {
                prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl);

                if (p.material)
                    prim.AddMember("material", p.material->index, w.mAl);

                if (p.indices)
                    prim.AddMember("indices", p.indices->index, w.mAl);

                Value attrs;
                attrs.SetObject();
                {
                    WriteAttrs(w, attrs, p.attributes.position, "POSITION");
                    WriteAttrs(w, attrs, p.attributes.normal, "NORMAL");
                    WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true);
                    WriteAttrs(w, attrs, p.attributes.color, "COLOR", true);
                    WriteAttrs(w, attrs, p.attributes.joint, "JOINTS", true);
                    WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS", true);
                }
                prim.AddMember("attributes", attrs, w.mAl);
            }
            primitives.PushBack(prim, w.mAl);
        }

        obj.AddMember("primitives", primitives, w.mAl);
    }

    inline void Write(Value& obj, Node& n, AssetWriter& w)
    {

        if (n.matrix.isPresent) {
            Value val;
            obj.AddMember("matrix", MakeValue(val, n.matrix.value, w.mAl).Move(), w.mAl);
        }

        if (n.translation.isPresent) {
            Value val;
            obj.AddMember("translation", MakeValue(val, n.translation.value, w.mAl).Move(), w.mAl);
        }

        if (n.scale.isPresent) {
            Value val;
            obj.AddMember("scale", MakeValue(val, n.scale.value, w.mAl).Move(), w.mAl);
        }
        if (n.rotation.isPresent) {
            Value val;
            obj.AddMember("rotation", MakeValue(val, n.rotation.value, w.mAl).Move(), w.mAl);
        }

        AddRefsVector(obj, "children", n.children, w.mAl);

        if (!n.meshes.empty()) {
            obj.AddMember("mesh", n.meshes[0]->index, w.mAl);
        }

        AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);

        if (n.skin) {
            obj.AddMember("skin", n.skin->index, w.mAl);
        }

        if (!n.jointName.empty()) {
          obj.AddMember("jointName", n.jointName, w.mAl);
        }
    }

    inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/)
    {

    }

    inline void Write(Value& obj, Sampler& b, AssetWriter& w)
    {
        if (!b.name.empty()) {
            obj.AddMember("name", b.name, w.mAl);
        }

        if (b.wrapS != SamplerWrap::UNSET && b.wrapS != SamplerWrap::Repeat) {
            obj.AddMember("wrapS", static_cast<unsigned int>(b.wrapS), w.mAl);
        }

        if (b.wrapT != SamplerWrap::UNSET && b.wrapT != SamplerWrap::Repeat) {
            obj.AddMember("wrapT", static_cast<unsigned int>(b.wrapT), w.mAl);
        }

        if (b.magFilter != SamplerMagFilter::UNSET) {
            obj.AddMember("magFilter", static_cast<unsigned int>(b.magFilter), w.mAl);
        }

        if (b.minFilter != SamplerMinFilter::UNSET) {
            obj.AddMember("minFilter", static_cast<unsigned int>(b.minFilter), w.mAl);
        }
    }

    inline void Write(Value& scene, Scene& s, AssetWriter& w)
    {
        AddRefsVector(scene, "nodes", s.nodes, w.mAl);
    }

    inline void Write(Value& /*obj*/, Shader& /*b*/, AssetWriter& /*w*/)
    {

    }

    inline void Write(Value& obj, Skin& b, AssetWriter& w)
    {
        /****************** jointNames *******************/
        Value vJointNames;
        vJointNames.SetArray();
        vJointNames.Reserve(unsigned(b.jointNames.size()), w.mAl);

        for (size_t i = 0; i < unsigned(b.jointNames.size()); ++i) {
            vJointNames.PushBack(b.jointNames[i]->index, w.mAl);
        }
        obj.AddMember("joints", vJointNames, w.mAl);

        if (b.bindShapeMatrix.isPresent) {
            Value val;
            obj.AddMember("bindShapeMatrix", MakeValue(val, b.bindShapeMatrix.value, w.mAl).Move(), w.mAl);
        }

        if (b.inverseBindMatrices) {
            obj.AddMember("inverseBindMatrices", b.inverseBindMatrices->index, w.mAl);
        }

    }

    inline void Write(Value& obj, Texture& tex, AssetWriter& w)
    {
        if (tex.source) {
            obj.AddMember("source", tex.source->index, w.mAl);
        }
        if (tex.sampler) {
            obj.AddMember("sampler", tex.sampler->index, w.mAl);
        }
    }


    inline AssetWriter::AssetWriter(Asset& a)
        : mDoc()
        , mAsset(a)
        , mAl(mDoc.GetAllocator())
    {
        mDoc.SetObject();

        WriteMetadata();
        WriteExtensionsUsed();

        // Dump the contents of the dictionaries
        for (size_t i = 0; i < a.mDicts.size(); ++i) {
            a.mDicts[i]->WriteObjects(*this);
        }

        // Add the target scene field
        if (mAsset.scene) {
            mDoc.AddMember("scene", mAsset.scene->index, mAl);
        }
    }

    inline void AssetWriter::WriteFile(const char* path)
    {
        std::unique_ptr<IOStream> jsonOutFile(mAsset.OpenFile(path, "wt", true));

        if (jsonOutFile == 0) {
            throw DeadlyExportError("Could not open output file: " + std::string(path));
        }

        StringBuffer docBuffer;

        PrettyWriter<StringBuffer> writer(docBuffer);
        mDoc.Accept(writer);

        if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
            throw DeadlyExportError("Failed to write scene data!");
        }

        // Write buffer data to separate .bin files
        for (unsigned int i = 0; i < mAsset.buffers.Size(); ++i) {
            Ref<Buffer> b = mAsset.buffers.Get(i);

            std::string binPath = b->GetURI();

            std::unique_ptr<IOStream> binOutFile(mAsset.OpenFile(binPath, "wb", true));

            if (binOutFile == 0) {
                throw DeadlyExportError("Could not open output file: " + binPath);
            }

            if (b->byteLength > 0) {
                if (binOutFile->Write(b->GetPointer(), b->byteLength, 1) != 1) {
                    throw DeadlyExportError("Failed to write binary file: " + binPath);
                }
            }
        }
    }

    inline void AssetWriter::WriteMetadata()
    {
        Value asset;
        asset.SetObject();
        asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
        asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
        mDoc.AddMember("asset", asset, mAl);
    }

    inline void AssetWriter::WriteExtensionsUsed()
    {
        Value exts;
        exts.SetArray();
        {
            // This is used to export pbrSpecularGlossiness materials with GLTF 2.
            if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
                exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl);
            }
        }

        if (!exts.Empty())
            mDoc.AddMember("extensionsUsed", exts, mAl);
    }

    template<class T>
    void AssetWriter::WriteObjects(LazyDict<T>& d)
    {
        if (d.mObjs.empty()) return;

        Value* container = &mDoc;

        if (d.mExtId) {
            Value* exts = FindObject(mDoc, "extensions");
            if (!exts) {
                mDoc.AddMember("extensions", Value().SetObject().Move(), mDoc.GetAllocator());
                exts = FindObject(mDoc, "extensions");
            }

            if (!(container = FindObject(*exts, d.mExtId))) {
                exts->AddMember(StringRef(d.mExtId), Value().SetObject().Move(), mDoc.GetAllocator());
                container = FindObject(*exts, d.mExtId);
            }
        }

        Value* dict;
        if (!(dict = FindArray(*container, d.mDictId))) {
            container->AddMember(StringRef(d.mDictId), Value().SetArray().Move(), mDoc.GetAllocator());
            dict = FindArray(*container, d.mDictId);
        }

        for (size_t i = 0; i < d.mObjs.size(); ++i) {
            if (d.mObjs[i]->IsSpecial()) continue;

            Value obj;
            obj.SetObject();

            if (!d.mObjs[i]->name.empty()) {
                obj.AddMember("name", StringRef(d.mObjs[i]->name.c_str()), mAl);
            }

            Write(obj, *d.mObjs[i], *this);

            dict->PushBack(obj, mAl);
        }
    }

    template<class T>
    void WriteLazyDict(LazyDict<T>& d, AssetWriter& w)
    {
        w.WriteObjects(d);
    }

}


