#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;
    }

#ifndef WITH_RIVE_EDITOR
    // Runtime-only; editor build registers via editorParentChanged.
    parent()->as<Image>()->setMesh(this);
#endif

    return StatusCode::Ok;
}

StatusCode Mesh::onAddedClean(CoreContext* context)
{
#ifndef WITH_RIVE_EDITOR
    // Runtime .riv loads: indices must be present and in range.
    // Editor mode: UAT coop batches don't transmit triangle indices —
    // editor computes them separately (mirrors Dart's
    // `packages/rive_core/lib/shapes/mesh.dart:252` onAdded →
    // triangulate()). Skip the validation so editor-side Meshes load
    // cleanly; bounds correctness is the editor's responsibility.
    if (m_IndexBuffer == nullptr)
    {
        return StatusCode::InvalidObject;
    }
    for (auto index : *m_IndexBuffer)
    {
        if (index >= m_Vertices.size())
        {
            return StatusCode::InvalidObject;
        }
    }
#endif
    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 clone = static_cast<Mesh*>(MeshBase::clone());
    clone->m_VertexRenderBufferDirty = true;
    // The vertex buffer is created lazily at first draw so it lands on the
    // instance's factory, not the source artboard's. UV and index buffers
    // are immutable and shared across instances.
    clone->m_UVRenderBuffer = m_UVRenderBuffer;
    clone->m_IndexRenderBuffer = m_IndexRenderBuffer;
    return clone;
}

void Mesh::onAssetLoaded(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 != nullptr)
    {
        float* uv = static_cast<float*>(m_UVRenderBuffer->map());
        if (uv != nullptr)
        {
            for (auto vertex : m_Vertices)
            {
                Vec2D xformedUV = uvTransform * Vec2D(vertex->u(), vertex->v());
                *uv++ = xformedUV.x;
                *uv++ = xformedUV.y;
            }
            m_UVRenderBuffer->unmap();
        }
    }

    if (m_IndexBuffer != nullptr)
    {
        m_IndexRenderBuffer = factory->makeRenderBuffer(
            RenderBufferType::index,
            RenderBufferFlags::mappedOnceAtInitialization,
            m_IndexBuffer->size() * sizeof(uint16_t));
        if (m_IndexRenderBuffer)
        {
            void* indexData = m_IndexRenderBuffer->map();
            if (indexData != nullptr)
            {
                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,
                ImageSampler ImageSampler,
                BlendMode blendMode,
                float opacity)
{
    if (m_VertexRenderBufferDirty && m_VertexRenderBuffer == nullptr &&
        !m_Vertices.empty())
    {
        m_VertexRenderBuffer = artboard()->factory()->makeRenderBuffer(
            RenderBufferType::vertex,
            RenderBufferFlags::none,
            m_Vertices.size() * sizeof(Vec2D));
    }
    if (m_VertexRenderBufferDirty && m_VertexRenderBuffer != nullptr)
    {
        Vec2D* mappedVertices =
            reinterpret_cast<Vec2D*>(m_VertexRenderBuffer->map());
        if (mappedVertices != nullptr)
        {
            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,
                            ImageSampler,
                            m_VertexRenderBuffer,
                            m_UVRenderBuffer,
                            m_IndexRenderBuffer,
                            static_cast<uint32_t>(m_Vertices.size()),
                            static_cast<uint32_t>(m_IndexBuffer->size()),
                            blendMode,
                            opacity);
}
