#include "rive/shapes/mesh.hpp"
#include "rive/shapes/image.hpp"
#include "rive/shapes/vertex.hpp"
#include "rive/shapes/mesh_vertex.hpp"
#include "rive/bones/skin.hpp"
#include "rive/artboard.hpp"
#include "rive/factory.hpp"
#include "rive/span.hpp"
#include "rive/assets/image_asset.hpp"
#include <limits>

using namespace rive;

/// Called whenever a vertex moves (x/y change).
void Mesh::markDrawableDirty()
{
    if (skin() != nullptr)
    {
        skin()->addDirt(ComponentDirt::Skin);
    }

    addDirt(ComponentDirt::Vertices);
}

void Mesh::addVertex(MeshVertex* vertex) { m_Vertices.push_back(vertex); }

StatusCode Mesh::onAddedDirty(CoreContext* context)
{
    StatusCode result = Super::onAddedDirty(context);
    if (result != StatusCode::Ok)
    {
        return result;
    }

    if (!parent()->is<Image>())
    {
        return StatusCode::MissingObject;
    }

    // All good, tell the image it has a mesh.
    parent()->as<Image>()->setMesh(this);

    return StatusCode::Ok;
}

StatusCode Mesh::onAddedClean(CoreContext* context)
{
    // Make sure Core found indices in the file for this Mesh.
    if (m_IndexBuffer == nullptr)
    {
        return StatusCode::InvalidObject;
    }

    // Check the indices are all in range. We should consider having a better
    // error reporting system to the implementor.
    for (auto index : *m_IndexBuffer)
    {
        if (index >= m_Vertices.size())
        {
            return StatusCode::InvalidObject;
        }
    }
    return Super::onAddedClean(context);
}

void Mesh::decodeTriangleIndexBytes(Span<const uint8_t> value)
{
    // decode the triangle index bytes
    rcp<IndexBuffer> buffer = rcp<IndexBuffer>(new IndexBuffer());

    BinaryReader reader(value);
    while (!reader.reachedEnd())
    {
        buffer->push_back(reader.readVarUintAs<uint16_t>());
    }
    m_IndexBuffer = buffer;
}

void Mesh::copyTriangleIndexBytes(const MeshBase& object)
{
    m_IndexBuffer = object.as<Mesh>()->m_IndexBuffer;
}

/// Called whenever a bone moves that is connected to the skin.
void Mesh::markSkinDirty() { addDirt(ComponentDirt::Vertices); }

Core* Mesh::clone() const
{
    auto factory = artboard()->factory();
    auto clone = static_cast<Mesh*>(MeshBase::clone());
    clone->m_VertexRenderBufferDirty = true;
    clone->m_VertexRenderBuffer = factory->makeRenderBuffer(RenderBufferType::vertex,
                                                            RenderBufferFlags::none,
                                                            m_Vertices.size() * sizeof(Vec2D));
    clone->m_UVRenderBuffer = m_UVRenderBuffer;
    clone->m_IndexRenderBuffer = m_IndexRenderBuffer;
    return clone;
}

void Mesh::initializeSharedBuffers(RenderImage* renderImage)
{
    Mat2D uvTransform = renderImage != nullptr ? renderImage->uvTransform() : Mat2D();

    auto factory = artboard()->factory();
    m_VertexRenderBufferDirty = true;
    m_VertexRenderBuffer = factory->makeRenderBuffer(RenderBufferType::vertex,
                                                     RenderBufferFlags::none,
                                                     m_Vertices.size() * sizeof(Vec2D));

    m_UVRenderBuffer = factory->makeRenderBuffer(RenderBufferType::vertex,
                                                 RenderBufferFlags::mappedOnceAtInitialization,
                                                 m_Vertices.size() * sizeof(Vec2D));
    if (m_UVRenderBuffer)
    {
        float* uv = static_cast<float*>(m_UVRenderBuffer->map());
        for (auto vertex : m_Vertices)
        {
            Vec2D xformedUV = uvTransform * Vec2D(vertex->u(), vertex->v());
            *uv++ = xformedUV.x;
            *uv++ = xformedUV.y;
        }
        m_UVRenderBuffer->unmap();
    }

    m_IndexRenderBuffer = factory->makeRenderBuffer(RenderBufferType::index,
                                                    RenderBufferFlags::mappedOnceAtInitialization,
                                                    m_IndexBuffer->size() * sizeof(uint16_t));
    if (m_IndexRenderBuffer)
    {
        void* indexData = m_IndexRenderBuffer->map();
        memcpy(indexData, m_IndexBuffer->data(), m_IndexRenderBuffer->sizeInBytes());
        m_IndexRenderBuffer->unmap();
    }
}

void Mesh::buildDependencies()
{
    Super::buildDependencies();
    if (skin() != nullptr)
    {
        skin()->addDependent(this);
    }
    parent()->addDependent(this);
}

void Mesh::update(ComponentDirt value)
{
    if (hasDirt(value, ComponentDirt::Vertices))
    {
        if (skin() != nullptr)
        {
            skin()->deform({(Vertex**)m_Vertices.data(), m_Vertices.size()});
        }
        m_VertexRenderBufferDirty = true;
    }
    Super::update(value);
}

void Mesh::draw(Renderer* renderer, const RenderImage* image, BlendMode blendMode, float opacity)
{
    if (m_VertexRenderBufferDirty && m_VertexRenderBuffer != nullptr)
    {
        Vec2D* mappedVertices = reinterpret_cast<Vec2D*>(m_VertexRenderBuffer->map());
        for (auto vertex : m_Vertices)
        {
            *mappedVertices++ = vertex->renderTranslation();
        }
        m_VertexRenderBuffer->unmap();
        m_VertexRenderBufferDirty = false;
    }

    if (skin() == nullptr)
    {
        renderer->transform(parent()->as<WorldTransformComponent>()->worldTransform());
    }
    renderer->drawImageMesh(image,
                            m_VertexRenderBuffer,
                            m_UVRenderBuffer,
                            m_IndexRenderBuffer,
                            static_cast<uint32_t>(m_Vertices.size()),
                            static_cast<uint32_t>(m_IndexBuffer->size()),
                            blendMode,
                            opacity);
}
