/*
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 "OgreBinarySerializer.h"
#include "OgreXmlSerializer.h"
#include "OgreParsingUtils.h"

#include "TinyFormatter.h"
#include <assimp/DefaultLogger.hpp>


#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER

// Define as 1 to get verbose logging.
#define OGRE_BINARY_SERIALIZER_DEBUG 0

namespace Assimp
{
namespace Ogre
{

const std::string       MESH_VERSION_1_8        = "[MeshSerializer_v1.8]";
const std::string       SKELETON_VERSION_1_8    = "[Serializer_v1.80]";
const std::string       SKELETON_VERSION_1_1    = "[Serializer_v1.10]";

const unsigned short    HEADER_CHUNK_ID         = 0x1000;

const long              MSTREAM_OVERHEAD_SIZE               = sizeof(uint16_t) + sizeof(uint32_t);
const long              MSTREAM_BONE_SIZE_WITHOUT_SCALE     = MSTREAM_OVERHEAD_SIZE + sizeof(unsigned short) + (sizeof(float) * 7);
const long              MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE = MSTREAM_OVERHEAD_SIZE + (sizeof(float) * 8);

template<>
inline bool OgreBinarySerializer::Read<bool>()
{
    return (m_reader->GetU1() > 0);
}

template<>
inline char OgreBinarySerializer::Read<char>()
{
    return static_cast<char>(m_reader->GetU1());
}

template<>
inline uint8_t OgreBinarySerializer::Read<uint8_t>()
{
    return m_reader->GetU1();
}

template<>
inline uint16_t OgreBinarySerializer::Read<uint16_t>()
{
    return m_reader->GetU2();
}

template<>
inline uint32_t OgreBinarySerializer::Read<uint32_t>()
{
    return m_reader->GetU4();
}

template<>
inline float OgreBinarySerializer::Read<float>()
{
    return m_reader->GetF4();
}

void OgreBinarySerializer::ReadBytes(char *dest, size_t numBytes)
{
    ReadBytes(static_cast<void*>(dest), numBytes);
}

void OgreBinarySerializer::ReadBytes(uint8_t *dest, size_t numBytes)
{
    ReadBytes(static_cast<void*>(dest), numBytes);
}

void OgreBinarySerializer::ReadBytes(void *dest, size_t numBytes)
{
    m_reader->CopyAndAdvance(dest, numBytes);
}

uint8_t *OgreBinarySerializer::ReadBytes(size_t numBytes)
{
    uint8_t *bytes = new uint8_t[numBytes];
    ReadBytes(bytes, numBytes);
    return bytes;
}

void OgreBinarySerializer::ReadVector(aiVector3D &vec)
{
    m_reader->CopyAndAdvance(&vec.x, sizeof(float)*3);
}

void OgreBinarySerializer::ReadQuaternion(aiQuaternion &quat)
{
    float temp[4];
    m_reader->CopyAndAdvance(temp, sizeof(float)*4);
    quat.x = temp[0];
    quat.y = temp[1];
    quat.z = temp[2];
    quat.w = temp[3];
}

bool OgreBinarySerializer::AtEnd() const
{
    return (m_reader->GetRemainingSize() == 0);
}

std::string OgreBinarySerializer::ReadString(size_t len)
{
    std::string str;
    str.resize(len);
    ReadBytes(&str[0], len);
    return str;
}

std::string OgreBinarySerializer::ReadLine()
{
    std::string str;
    while(!AtEnd())
    {
        char c = Read<char>();
        if (c == '\n')
            break;
        str += c;
    }
    return str;
}

uint16_t OgreBinarySerializer::ReadHeader(bool readLen)
{
    uint16_t id = Read<uint16_t>();
    if (readLen)
        m_currentLen = Read<uint32_t>();

#if (OGRE_BINARY_SERIALIZER_DEBUG == 1)
    if (id != HEADER_CHUNK_ID)
    {
        DefaultLogger::get()->debug(Formatter::format() << (assetMode == AM_Mesh
            ? MeshHeaderToString(static_cast<MeshChunkId>(id)) : SkeletonHeaderToString(static_cast<SkeletonChunkId>(id))));
    }
#endif

    return id;
}

void OgreBinarySerializer::RollbackHeader()
{
    m_reader->IncPtr(-MSTREAM_OVERHEAD_SIZE);
}

void OgreBinarySerializer::SkipBytes(size_t numBytes)
{
#if (OGRE_BINARY_SERIALIZER_DEBUG == 1)
    DefaultLogger::get()->debug(Formatter::format() << "Skipping " << numBytes << " bytes");
#endif

    m_reader->IncPtr(numBytes);
}

// Mesh

Mesh *OgreBinarySerializer::ImportMesh(MemoryStreamReader *stream)
{
    OgreBinarySerializer serializer(stream, OgreBinarySerializer::AM_Mesh);

    uint16_t id = serializer.ReadHeader(false);
    if (id != HEADER_CHUNK_ID) {
        throw DeadlyExportError("Invalid Ogre Mesh file header.");
    }

    /// @todo Check what we can actually support.
    std::string version = serializer.ReadLine();
    if (version != MESH_VERSION_1_8)
    {
        throw DeadlyExportError(Formatter::format() << "Mesh version " << version << " not supported by this importer. Run OgreMeshUpgrader tool on the file and try again."
            << " Supported versions: " << MESH_VERSION_1_8);
    }

    Mesh *mesh = new Mesh();
    while (!serializer.AtEnd())
    {
        id = serializer.ReadHeader();
        switch(id)
        {
            case M_MESH:
            {
                serializer.ReadMesh(mesh);
                break;
            }
        }
    }
    return mesh;
}

void OgreBinarySerializer::ReadMesh(Mesh *mesh)
{
    mesh->hasSkeletalAnimations = Read<bool>();

    DefaultLogger::get()->debug("Reading Mesh");
    DefaultLogger::get()->debug(Formatter::format() << "  - Skeletal animations: " << (mesh->hasSkeletalAnimations ? "true" : "false"));

    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        while (!AtEnd() &&
            (id == M_GEOMETRY ||
             id == M_SUBMESH ||
             id == M_MESH_SKELETON_LINK ||
             id == M_MESH_BONE_ASSIGNMENT ||
             id == M_MESH_LOD ||
             id == M_MESH_BOUNDS ||
             id == M_SUBMESH_NAME_TABLE ||
             id == M_EDGE_LISTS ||
             id == M_POSES ||
             id == M_ANIMATIONS ||
             id == M_TABLE_EXTREMES))
        {
            switch(id)
            {
                case M_GEOMETRY:
                {
                    mesh->sharedVertexData = new VertexData();
                    ReadGeometry(mesh->sharedVertexData);
                    break;
                }
                case M_SUBMESH:
                {
                    ReadSubMesh(mesh);
                    break;
                }
                case M_MESH_SKELETON_LINK:
                {
                    ReadMeshSkeletonLink(mesh);
                    break;
                }
                case M_MESH_BONE_ASSIGNMENT:
                {
                    ReadBoneAssignment(mesh->sharedVertexData);
                    break;
                }
                case M_MESH_LOD:
                {
                    ReadMeshLodInfo(mesh);
                    break;
                }
                case M_MESH_BOUNDS:
                {
                    ReadMeshBounds(mesh);
                    break;
                }
                case M_SUBMESH_NAME_TABLE:
                {
                    ReadSubMeshNames(mesh);
                    break;
                }
                case M_EDGE_LISTS:
                {
                    ReadEdgeList(mesh);
                    break;
                }
                case M_POSES:
                {
                    ReadPoses(mesh);
                    break;
                }
                case M_ANIMATIONS:
                {
                    ReadAnimations(mesh);
                    break;
                }
                case M_TABLE_EXTREMES:
                {
                    ReadMeshExtremes(mesh);
                    break;
                }
            }

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }

    NormalizeBoneWeights(mesh->sharedVertexData);
}

void OgreBinarySerializer::ReadMeshLodInfo(Mesh *mesh)
{
    // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
    // @todo Put this stuff to scene/mesh custom properties. If manual mesh the app can use the information.
    ReadLine(); // strategy name
    uint16_t numLods = Read<uint16_t>();
    bool manual = Read<bool>();

    /// @note Main mesh is considered as LOD 0, start from index 1.
    for (size_t i=1; i<numLods; ++i)
    {
        uint16_t id = ReadHeader();
        if (id != M_MESH_LOD_USAGE) {
            throw DeadlyImportError("M_MESH_LOD does not contain a M_MESH_LOD_USAGE for each LOD level");
        }

        m_reader->IncPtr(sizeof(float)); // user value

        if (manual)
        {
            id = ReadHeader();
            if (id != M_MESH_LOD_MANUAL) {
                throw DeadlyImportError("Manual M_MESH_LOD_USAGE does not contain M_MESH_LOD_MANUAL");
            }

            ReadLine(); // manual mesh name (ref to another mesh)
        }
        else
        {
            for(size_t si=0, silen=mesh->NumSubMeshes(); si<silen; ++si)
            {
                id = ReadHeader();
                if (id != M_MESH_LOD_GENERATED) {
                    throw DeadlyImportError("Generated M_MESH_LOD_USAGE does not contain M_MESH_LOD_GENERATED");
                }

                uint32_t indexCount = Read<uint32_t>();
                bool is32bit = Read<bool>();

                if (indexCount > 0)
                {
                    uint32_t len = indexCount * (is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
                    m_reader->IncPtr(len);
                }
            }
        }
    }
}

void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
{
    mesh->skeletonRef = ReadLine();
}

void OgreBinarySerializer::ReadMeshBounds(Mesh * /*mesh*/)
{
    // Skip bounds, not compatible with Assimp.
    // 2x float vec3 + 1x float sphere radius
    SkipBytes(sizeof(float) * 7);
}

void OgreBinarySerializer::ReadMeshExtremes(Mesh * /*mesh*/)
{
    // Skip extremes, not compatible with Assimp.
    size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
    SkipBytes(numBytes);
}

void OgreBinarySerializer::ReadBoneAssignment(VertexData *dest)
{
    if (!dest) {
        throw DeadlyImportError("Cannot read bone assignments, vertex data is null.");
    }

    VertexBoneAssignment ba;
    ba.vertexIndex = Read<uint32_t>();
    ba.boneIndex = Read<uint16_t>();
    ba.weight = Read<float>();

    dest->boneAssignments.push_back(ba);
}

void OgreBinarySerializer::ReadSubMesh(Mesh *mesh)
{
    uint16_t id = 0;

    SubMesh *submesh = new SubMesh();
    submesh->materialRef = ReadLine();
    submesh->usesSharedVertexData = Read<bool>();

    submesh->indexData->count = Read<uint32_t>();
    submesh->indexData->faceCount = static_cast<uint32_t>(submesh->indexData->count / 3);
    submesh->indexData->is32bit = Read<bool>();

    DefaultLogger::get()->debug(Formatter::format() << "Reading SubMesh " << mesh->subMeshes.size());
    DefaultLogger::get()->debug(Formatter::format() << "  - Material: '" << submesh->materialRef << "'");
    DefaultLogger::get()->debug(Formatter::format() << "  - Uses shared geometry: " << (submesh->usesSharedVertexData ? "true" : "false"));

    // Index buffer
    if (submesh->indexData->count > 0)
    {
        uint32_t numBytes = submesh->indexData->count * (submesh->indexData->is32bit ? sizeof(uint32_t) : sizeof(uint16_t));
        uint8_t *indexBuffer = ReadBytes(numBytes);
        submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true));

        DefaultLogger::get()->debug(Formatter::format() << "  - " << submesh->indexData->faceCount
            << " faces from " << submesh->indexData->count << (submesh->indexData->is32bit ? " 32bit" : " 16bit")
            << " indexes of " << numBytes << " bytes");
    }

    // Vertex buffer if not referencing the shared geometry
    if (!submesh->usesSharedVertexData)
    {
        id = ReadHeader();
        if (id != M_GEOMETRY) {
            throw DeadlyImportError("M_SUBMESH does not contain M_GEOMETRY, but shader geometry is set to false");
        }

        submesh->vertexData = new VertexData();
        ReadGeometry(submesh->vertexData);
    }

    // Bone assignment, submesh operation and texture aliases
    if (!AtEnd())
    {
        id = ReadHeader();
        while (!AtEnd() &&
            (id == M_SUBMESH_OPERATION ||
             id == M_SUBMESH_BONE_ASSIGNMENT ||
             id == M_SUBMESH_TEXTURE_ALIAS))
        {
            switch(id)
            {
                case M_SUBMESH_OPERATION:
                {
                    ReadSubMeshOperation(submesh);
                    break;
                }
                case M_SUBMESH_BONE_ASSIGNMENT:
                {
                    ReadBoneAssignment(submesh->vertexData);
                    break;
                }
                case M_SUBMESH_TEXTURE_ALIAS:
                {
                    ReadSubMeshTextureAlias(submesh);
                    break;
                }
            }

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }

    NormalizeBoneWeights(submesh->vertexData);

    submesh->index = static_cast<unsigned int>(mesh->subMeshes.size());
    mesh->subMeshes.push_back(submesh);
}

void OgreBinarySerializer::NormalizeBoneWeights(VertexData *vertexData) const
{
    if (!vertexData || vertexData->boneAssignments.empty())
        return;

    std::set<uint32_t> influencedVertices;
    for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter) {
        influencedVertices.insert(baIter->vertexIndex);
    }

    /** Normalize bone weights.
        Some exporters won't care if the sum of all bone weights
        for a single vertex equals 1 or not, so validate here. */
    const float epsilon = 0.05f;
    for (const uint32_t vertexIndex : influencedVertices)
    {
        float sum = 0.0f;
        for (VertexBoneAssignmentList::const_iterator baIter=vertexData->boneAssignments.begin(), baEnd=vertexData->boneAssignments.end(); baIter != baEnd; ++baIter)
        {
            if (baIter->vertexIndex == vertexIndex)
                sum += baIter->weight;
        }
        if ((sum < (1.0f - epsilon)) || (sum > (1.0f + epsilon)))
        {
            for (auto &boneAssign : vertexData->boneAssignments)
            {
                if (boneAssign.vertexIndex == vertexIndex)
                    boneAssign.weight /= sum;
            }
        }
    }
}

void OgreBinarySerializer::ReadSubMeshOperation(SubMesh *submesh)
{
    submesh->operationType = static_cast<SubMesh::OperationType>(Read<uint16_t>());
}

void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh *submesh)
{
    submesh->textureAliasName = ReadLine();
    submesh->textureAliasRef = ReadLine();
}

void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
{
    uint16_t id = 0;

    if (!AtEnd())
    {
        id = ReadHeader();
        while (!AtEnd() && id == M_SUBMESH_NAME_TABLE_ELEMENT)
        {
            uint16_t submeshIndex = Read<uint16_t>();
            SubMesh *submesh = mesh->GetSubMesh(submeshIndex);
            if (!submesh) {
                throw DeadlyImportError(Formatter::format() << "Ogre Mesh does not include submesh " << submeshIndex << " referenced in M_SUBMESH_NAME_TABLE_ELEMENT. Invalid mesh file.");
            }

            submesh->name = ReadLine();
            DefaultLogger::get()->debug(Formatter::format() << "  - SubMesh " << submesh->index << " name '" << submesh->name << "'");

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }
}

void OgreBinarySerializer::ReadGeometry(VertexData *dest)
{
    dest->count = Read<uint32_t>();

    DefaultLogger::get()->debug(Formatter::format() << "  - Reading geometry of " << dest->count << " vertices");

    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        while (!AtEnd() &&
            (id == M_GEOMETRY_VERTEX_DECLARATION ||
             id == M_GEOMETRY_VERTEX_BUFFER))
        {
            switch(id)
            {
                case M_GEOMETRY_VERTEX_DECLARATION:
                {
                    ReadGeometryVertexDeclaration(dest);
                    break;
                }
                case M_GEOMETRY_VERTEX_BUFFER:
                {
                    ReadGeometryVertexBuffer(dest);
                    break;
                }
            }

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }
}

void OgreBinarySerializer::ReadGeometryVertexDeclaration(VertexData *dest)
{
    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        while (!AtEnd() && id == M_GEOMETRY_VERTEX_ELEMENT)
        {
            ReadGeometryVertexElement(dest);

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }
}

void OgreBinarySerializer::ReadGeometryVertexElement(VertexData *dest)
{
    VertexElement element;
    element.source = Read<uint16_t>();
    element.type = static_cast<VertexElement::Type>(Read<uint16_t>());
    element.semantic = static_cast<VertexElement::Semantic>(Read<uint16_t>());
    element.offset = Read<uint16_t>();
    element.index = Read<uint16_t>();

    DefaultLogger::get()->debug(Formatter::format() << "    - Vertex element " << element.SemanticToString() << " of type "
        << element.TypeToString() << " index=" << element.index << " source=" << element.source);

    dest->vertexElements.push_back(element);
}

void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest)
{
    uint16_t bindIndex = Read<uint16_t>();
    uint16_t vertexSize = Read<uint16_t>();

    uint16_t id = ReadHeader();
    if (id != M_GEOMETRY_VERTEX_BUFFER_DATA)
        throw DeadlyImportError("M_GEOMETRY_VERTEX_BUFFER_DATA not found in M_GEOMETRY_VERTEX_BUFFER");

    if (dest->VertexSize(bindIndex) != vertexSize)
        throw DeadlyImportError("Vertex buffer size does not agree with vertex declaration in M_GEOMETRY_VERTEX_BUFFER");

    size_t numBytes = dest->count * vertexSize;
    uint8_t *vertexBuffer = ReadBytes(numBytes);
    dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true));

    DefaultLogger::get()->debug(Formatter::format() << "    - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
}

void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/)
{
    // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.

    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        while (!AtEnd() && id == M_EDGE_LIST_LOD)
        {
            m_reader->IncPtr(sizeof(uint16_t)); // lod index
            bool manual = Read<bool>();

            if (!manual)
            {
                m_reader->IncPtr(sizeof(uint8_t));
                uint32_t numTriangles = Read<uint32_t>();
                uint32_t numEdgeGroups = Read<uint32_t>();

                size_t skipBytes = (sizeof(uint32_t) * 8 + sizeof(float) * 4) * numTriangles;
                m_reader->IncPtr(skipBytes);

                for (size_t i=0; i<numEdgeGroups; ++i)
                {
                    uint16_t id = ReadHeader();
                    if (id != M_EDGE_GROUP)
                        throw DeadlyImportError("M_EDGE_GROUP not found in M_EDGE_LIST_LOD");

                    m_reader->IncPtr(sizeof(uint32_t) * 3);
                    uint32_t numEdges = Read<uint32_t>();
                    for (size_t j=0; j<numEdges; ++j)
                    {
                        m_reader->IncPtr(sizeof(uint32_t) * 6 + sizeof(uint8_t));
                    }
                }
            }

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }
}

void OgreBinarySerializer::ReadPoses(Mesh *mesh)
{
    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        while (!AtEnd() && id == M_POSE)
        {
            Pose *pose = new Pose();
            pose->name = ReadLine();
            pose->target = Read<uint16_t>();
            pose->hasNormals = Read<bool>();

            ReadPoseVertices(pose);

            mesh->poses.push_back(pose);

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }
}

void OgreBinarySerializer::ReadPoseVertices(Pose *pose)
{
    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        while (!AtEnd() && id == M_POSE_VERTEX)
        {
            Pose::Vertex v;
            v.index = Read<uint32_t>();
            ReadVector(v.offset);
            if (pose->hasNormals)
                ReadVector(v.normal);

            pose->vertices[v.index] = v;

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }
}

void OgreBinarySerializer::ReadAnimations(Mesh *mesh)
{
    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        while (!AtEnd() && id == M_ANIMATION)
        {
            Animation *anim = new Animation(mesh);
            anim->name = ReadLine();
            anim->length = Read<float>();

            ReadAnimation(anim);

            mesh->animations.push_back(anim);

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }
}

void OgreBinarySerializer::ReadAnimation(Animation *anim)
{
    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        if (id == M_ANIMATION_BASEINFO)
        {
            anim->baseName = ReadLine();
            anim->baseTime = Read<float>();

            // Advance to first track
            id = ReadHeader();
        }

        while (!AtEnd() && id == M_ANIMATION_TRACK)
        {
            VertexAnimationTrack track;
            track.type = static_cast<VertexAnimationTrack::Type>(Read<uint16_t>());
            track.target = Read<uint16_t>();

            ReadAnimationKeyFrames(anim, &track);

            anim->tracks.push_back(track);

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }
}

void OgreBinarySerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *track)
{
    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        while (!AtEnd() &&
            (id == M_ANIMATION_MORPH_KEYFRAME ||
             id == M_ANIMATION_POSE_KEYFRAME))
        {
            if (id == M_ANIMATION_MORPH_KEYFRAME)
            {
                MorphKeyFrame kf;
                kf.timePos = Read<float>();
                bool hasNormals = Read<bool>();

                size_t vertexCount = anim->AssociatedVertexData(track)->count;
                size_t vertexSize = sizeof(float) * (hasNormals ? 6 : 3);
                size_t numBytes = vertexCount * vertexSize;

                uint8_t *morphBuffer = ReadBytes(numBytes);
                kf.buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(morphBuffer, numBytes, true));

                track->morphKeyFrames.push_back(kf);
            }
            else if (id == M_ANIMATION_POSE_KEYFRAME)
            {
                PoseKeyFrame kf;
                kf.timePos = Read<float>();

                if (!AtEnd())
                {
                    id = ReadHeader();
                    while (!AtEnd() && id == M_ANIMATION_POSE_REF)
                    {
                        PoseRef pr;
                        pr.index = Read<uint16_t>();
                        pr.influence = Read<float>();
                        kf.references.push_back(pr);

                        if (!AtEnd())
                            id = ReadHeader();
                    }
                    if (!AtEnd())
                        RollbackHeader();
                }

                track->poseKeyFrames.push_back(kf);
            }

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }
}

// Skeleton

bool OgreBinarySerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
{
    if (!mesh || mesh->skeletonRef.empty())
        return false;

    // Highly unusual to see in read world cases but support
    // binary mesh referencing a XML skeleton file.
    if (EndsWith(mesh->skeletonRef, ".skeleton.xml", false))
    {
        OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh);
        return false;
    }

    MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);

    Skeleton *skeleton = new Skeleton();
    OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton);
    serializer.ReadSkeleton(skeleton);
    mesh->skeleton = skeleton;
    return true;
}

bool OgreBinarySerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *mesh)
{
    if (!mesh || mesh->skeletonRef.empty())
        return false;

    MemoryStreamReaderPtr reader = OpenReader(pIOHandler, mesh->skeletonRef);
    if (!reader.get())
        return false;

    Skeleton *skeleton = new Skeleton();
    OgreBinarySerializer serializer(reader.get(), OgreBinarySerializer::AM_Skeleton);
    serializer.ReadSkeleton(skeleton);
    mesh->skeleton = skeleton;
    return true;
}

MemoryStreamReaderPtr OgreBinarySerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename)
{
    if (!EndsWith(filename, ".skeleton", false))
    {
        DefaultLogger::get()->error("Imported Mesh is referencing to unsupported '" + filename + "' skeleton file.");
        return MemoryStreamReaderPtr();
    }

    if (!pIOHandler->Exists(filename))
    {
        DefaultLogger::get()->error("Failed to find skeleton file '" + filename + "' that is referenced by imported Mesh.");
        return MemoryStreamReaderPtr();
    }

    IOStream *f = pIOHandler->Open(filename, "rb");
    if (!f) {
        throw DeadlyImportError("Failed to open skeleton file " + filename);
    }

    return MemoryStreamReaderPtr(new MemoryStreamReader(f));
}

void OgreBinarySerializer::ReadSkeleton(Skeleton *skeleton)
{
    uint16_t id = ReadHeader(false);
    if (id != HEADER_CHUNK_ID) {
        throw DeadlyExportError("Invalid Ogre Skeleton file header.");
    }

    // This deserialization supports both versions of the skeleton spec
    std::string version = ReadLine();
    if (version != SKELETON_VERSION_1_8 && version != SKELETON_VERSION_1_1)
    {
        throw DeadlyExportError(Formatter::format() << "Skeleton version " << version << " not supported by this importer."
            << " Supported versions: " << SKELETON_VERSION_1_8 << " and " << SKELETON_VERSION_1_1);
    }

    DefaultLogger::get()->debug("Reading Skeleton");

    bool firstBone = true;
    bool firstAnim = true;

    while (!AtEnd())
    {
        id = ReadHeader();
        switch(id)
        {
            case SKELETON_BLENDMODE:
            {
                skeleton->blendMode = static_cast<Skeleton::BlendMode>(Read<uint16_t>());
                break;
            }
            case SKELETON_BONE:
            {
                if (firstBone)
                {
                    DefaultLogger::get()->debug("  - Bones");
                    firstBone = false;
                }

                ReadBone(skeleton);
                break;
            }
            case SKELETON_BONE_PARENT:
            {
                ReadBoneParent(skeleton);
                break;
            }
            case SKELETON_ANIMATION:
            {
                if (firstAnim)
                {
                    DefaultLogger::get()->debug("  - Animations");
                    firstAnim = false;
                }

                ReadSkeletonAnimation(skeleton);
                break;
            }
            case SKELETON_ANIMATION_LINK:
            {
                ReadSkeletonAnimationLink(skeleton);
                break;
            }
        }
    }

    // Calculate bone matrices for root bones. Recursively calculates their children.
    for (size_t i=0, len=skeleton->bones.size(); i<len; ++i)
    {
        Bone *bone = skeleton->bones[i];
        if (!bone->IsParented())
            bone->CalculateWorldMatrixAndDefaultPose(skeleton);
    }
}

void OgreBinarySerializer::ReadBone(Skeleton *skeleton)
{
    Bone *bone = new Bone();
    bone->name = ReadLine();
    bone->id = Read<uint16_t>();

    // Pos and rot
    ReadVector(bone->position);
    ReadQuaternion(bone->rotation);

    // Scale (optional)
    if (m_currentLen > MSTREAM_BONE_SIZE_WITHOUT_SCALE)
        ReadVector(bone->scale);

    // Bone indexes need to start from 0 and be contiguous
    if (bone->id != skeleton->bones.size()) {
        throw DeadlyImportError(Formatter::format() << "Ogre Skeleton bone indexes not contiguous. Error at bone index " << bone->id);
    }

    DefaultLogger::get()->debug(Formatter::format() << "    " << bone->id << " " << bone->name);

    skeleton->bones.push_back(bone);
}

void OgreBinarySerializer::ReadBoneParent(Skeleton *skeleton)
{
    uint16_t childId = Read<uint16_t>();
    uint16_t parentId = Read<uint16_t>();

    Bone *child = skeleton->BoneById(childId);
    Bone *parent = skeleton->BoneById(parentId);

    if (child && parent)
        parent->AddChild(child);
    else
        throw DeadlyImportError(Formatter::format() << "Failed to find bones for parenting: Child id " << childId << " for parent id " << parentId);
}

void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton)
{
    Animation *anim = new Animation(skeleton);
    anim->name = ReadLine();
    anim->length = Read<float>();

    if (!AtEnd())
    {
        uint16_t id = ReadHeader();
        if (id == SKELETON_ANIMATION_BASEINFO)
        {
            anim->baseName = ReadLine();
            anim->baseTime = Read<float>();

            // Advance to first track
            id = ReadHeader();
        }

        while (!AtEnd() && id == SKELETON_ANIMATION_TRACK)
        {
            ReadSkeletonAnimationTrack(skeleton, anim);

            if (!AtEnd())
                id = ReadHeader();
        }
        if (!AtEnd())
            RollbackHeader();
    }

    skeleton->animations.push_back(anim);

    DefaultLogger::get()->debug(Formatter::format() << "    " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
}

void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest)
{
    uint16_t boneId = Read<uint16_t>();
    Bone *bone = dest->parentSkeleton->BoneById(boneId);
    if (!bone) {
        throw DeadlyImportError(Formatter::format() << "Cannot read animation track, target bone " << boneId << " not in target Skeleton");
    }

    VertexAnimationTrack track;
    track.type = VertexAnimationTrack::VAT_TRANSFORM;
    track.boneName = bone->name;

    uint16_t id = ReadHeader();
    while (!AtEnd() && id == SKELETON_ANIMATION_TRACK_KEYFRAME)
    {
        ReadSkeletonAnimationKeyFrame(&track);

        if (!AtEnd())
            id = ReadHeader();
    }
    if (!AtEnd())
        RollbackHeader();

    dest->tracks.push_back(track);
}

void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *dest)
{
    TransformKeyFrame keyframe;
    keyframe.timePos = Read<float>();

    // Rot and pos
    ReadQuaternion(keyframe.rotation);
    ReadVector(keyframe.position);

    // Scale (optional)
    if (m_currentLen > MSTREAM_KEYFRAME_SIZE_WITHOUT_SCALE)
        ReadVector(keyframe.scale);

    dest->transformKeyFrames.push_back(keyframe);
}

void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton * /*skeleton*/)
{
    // Skip bounds, not compatible with Assimp.
    ReadLine(); // skeleton name
    SkipBytes(sizeof(float) * 3); // scale
}

} // Ogre
} // Assimp

#endif // ASSIMP_BUILD_NO_OGRE_IMPORTER
