#include "rive/artboard.hpp"
#include "rive/assets/image_asset.hpp"
#include "rive/factory.hpp"
#include "rive/layout/axis.hpp"
#include "rive/layout/n_slicer.hpp"
#include "rive/layout/n_slicer_tile_mode.hpp"
#include "rive/math/math_types.hpp"
#include "rive/math/n_slicer_helpers.hpp"
#include "rive/shapes/image.hpp"
#include "rive/shapes/slice_mesh.hpp"

using namespace rive;

const Corner SliceMesh::patchCorners[] = {
    {0, 0},
    {1, 0},
    {1, 1},
    {0, 1},
};

const uint16_t SliceMesh::triangulation[] = {0, 1, 3, 1, 2, 3};

SliceMesh::SliceMesh(NSlicer* nslicer) : m_nslicer(nslicer) {}

void SliceMesh::draw(Renderer* renderer,
                     const RenderImage* renderImage,
                     ImageSampler ImageSampler,
                     BlendMode blendMode,
                     float opacity)
{
    if (m_nslicer == nullptr || m_nslicer->image() == nullptr)
    {
        return;
    }
    if (!m_VertexRenderBuffer || !m_UVRenderBuffer || !m_IndexRenderBuffer)
    {
        return;
    }
    Image* image = m_nslicer->image();
    renderer->transform(image->worldTransform());
    renderer->translate(-image->width() * image->originX(),
                        -image->height() * image->originY());
    renderer->drawImageMesh(renderImage,
                            ImageSampler,
                            m_VertexRenderBuffer,
                            m_UVRenderBuffer,
                            m_IndexRenderBuffer,
                            static_cast<uint32_t>(m_vertices.size()),
                            static_cast<uint32_t>(m_indices.size()),
                            blendMode,
                            opacity);
}

void SliceMesh::onAssetLoaded(RenderImage* renderImage) {}

void SliceMesh::updateBuffers()
{
    auto factory = m_nslicer->artboard()->factory();

    // 1. vertex render buffer
    size_t vertexSizeInBytes = m_vertices.size() * sizeof(Vec2D);
    if (m_VertexRenderBuffer != nullptr &&
        m_VertexRenderBuffer->sizeInBytes() != vertexSizeInBytes)
    {
        m_VertexRenderBuffer = nullptr;
    }

    if (m_VertexRenderBuffer == nullptr && vertexSizeInBytes != 0)
    {
        m_VertexRenderBuffer =
            factory->makeRenderBuffer(RenderBufferType::vertex,
                                      RenderBufferFlags::none, // optimization?
                                      vertexSizeInBytes);
    }

    if (m_VertexRenderBuffer != nullptr)
    {
        Vec2D* mappedVertices =
            reinterpret_cast<Vec2D*>(m_VertexRenderBuffer->map());
        if (mappedVertices != nullptr)
        {
            for (auto v : m_vertices)
            {
                *mappedVertices++ = v;
            }
            m_VertexRenderBuffer->unmap();
        }
    }

    // 2. uv render buffer
    size_t uvSizeInBytes = m_uvs.size() * sizeof(Vec2D);
    if (m_UVRenderBuffer != nullptr &&
        m_UVRenderBuffer->sizeInBytes() != uvSizeInBytes)
    {
        m_UVRenderBuffer = nullptr;
    }

    if (m_UVRenderBuffer == nullptr && uvSizeInBytes != 0)
    {
        m_UVRenderBuffer = factory->makeRenderBuffer(RenderBufferType::vertex,
                                                     RenderBufferFlags::none,
                                                     uvSizeInBytes);
    }

    if (m_UVRenderBuffer)
    {
        auto renderImage = m_nslicer->image()->imageAsset()->renderImage();
        Mat2D uvTransform =
            renderImage != nullptr ? renderImage->uvTransform() : Mat2D();

        Vec2D* mappedUVs = reinterpret_cast<Vec2D*>(m_UVRenderBuffer->map());
        if (mappedUVs != nullptr)
        {
            for (auto uv : m_uvs)
            {
                Vec2D xformedUV = uvTransform * uv;
                *mappedUVs++ = xformedUV;
            }
            m_UVRenderBuffer->unmap();
        }
    }

    // 3. index render buffer
    size_t indexSizeInBytes = m_indices.size() * sizeof(uint16_t);
    if (m_IndexRenderBuffer != nullptr &&
        m_IndexRenderBuffer->sizeInBytes() != indexSizeInBytes)
    {
        m_IndexRenderBuffer = nullptr;
    }

    if (m_IndexRenderBuffer == nullptr && indexSizeInBytes != 0)
    {
        m_IndexRenderBuffer = factory->makeRenderBuffer(RenderBufferType::index,
                                                        RenderBufferFlags::none,
                                                        indexSizeInBytes);
    }

    if (m_IndexRenderBuffer)
    {
        void* mappedIndex = m_IndexRenderBuffer->map();
        if (mappedIndex != nullptr)
        {
            memcpy(mappedIndex, m_indices.data(), indexSizeInBytes);
            m_IndexRenderBuffer->unmap();
        }
    }
}

std::vector<float> SliceMesh::uvStops(AxisType forAxis)
{
    float imageSize = forAxis == AxisType::X ? m_nslicer->image()->width()
                                             : m_nslicer->image()->height();
    float imageScale =
        std::abs(forAxis == AxisType::X ? m_nslicer->image()->scaleX()
                                        : m_nslicer->image()->scaleY());
    if (imageSize == 0 || imageScale == 0)
    {
        return {};
    }

    const std::vector<Axis*>& axes =
        (forAxis == AxisType::X) ? m_nslicer->xs() : m_nslicer->ys();

    return NSlicerHelpers::uvStops(axes, imageSize);
}

std::vector<float> SliceMesh::vertexStops(
    const std::vector<float>& normalizedStops,
    AxisType forAxis)
{
    Image* image = m_nslicer->image();
    float imageSize = forAxis == AxisType::X ? image->width() : image->height();

    // When doing calcualtions, we assume scale is always non-negative to keep
    // everything in image space.
    float imageScale =
        std::abs(forAxis == AxisType::X ? image->scaleX() : image->scaleY());
    if (imageSize == 0 || imageScale == 0)
    {
        return {};
    }

    ScaleInfo scaleInfo =
        NSlicerHelpers::analyzeUVStops(normalizedStops, imageSize, imageScale);

    std::vector<float> vertices;
    float vertex = 0.0;
    float vertexInBounds = 0.0;

    for (int i = 0; i < (int)normalizedStops.size() - 1; i++)
    {
        vertices.emplace_back(vertexInBounds);
        float segment = imageSize *
                        (normalizedStops[i + 1] - normalizedStops[i]) /
                        imageScale;
        if (NSlicerHelpers::isFixedSegment(i))
        {
            vertex += segment;
        }
        else
        {
            if (scaleInfo.useScale)
            {
                vertex += segment * scaleInfo.scaleFactor;
            }
            else
            {
                vertex += scaleInfo.fallbackSize;
            }
        }
        vertexInBounds = math::clamp(vertex, 0, imageSize);
    }
    vertices.emplace_back(vertexInBounds);
    return vertices;
}

uint16_t SliceMesh::tileRepeat(std::vector<SliceMeshVertex>& vertices,
                               std::vector<uint16_t>& indices,
                               const std::vector<SliceMeshVertex>& box,
                               uint16_t start)
{
    assert(box.size() == 4);

    const float startX = box[0].vertex.x;
    const float startY = box[0].vertex.y;
    const float endX = box[2].vertex.x;
    const float endY = box[2].vertex.y;

    const float startU = box[0].uv.x;
    const float startV = box[0].uv.y;
    const float endU = box[2].uv.x;
    const float endV = box[2].uv.y;

    // The size of each repeated tile in image space
    Image* image = m_nslicer->image();
    float scaleX = std::abs(image->scaleX());
    float scaleY = std::abs(image->scaleY());

    if (scaleX == 0 || scaleY == 0)
    {
        return 0;
    }

    const float sizeX = image->width() * (endU - startU) / scaleX;
    const float sizeY = image->height() * (endV - startV) / scaleY;

    if (std::abs(sizeX) < 1 || std::abs(sizeY) < 1)
    {
        return 0;
    }

    float curX = startX;
    float curY = startY;
    int curV = start;

    int escape = 10000;
    while (curY < endY && escape > 0)
    {
        escape--;
        float fracY = (curY + sizeY) > endY ? (endY - curY) / sizeY : 1;
        curX = startX;
        while (curX < endX && escape > 0)
        {
            escape--;
            int v0 = curV;
            float fracX = (curX + sizeX) > endX ? (endX - curX) / sizeX : 1;

            std::vector<SliceMeshVertex> curTile;
            float endU1 = startU + (endU - startU) * fracX;
            float endV1 = startV + (endV - startV) * fracY;
            float endX1 = curX + sizeX * fracX;
            float endY1 = curY + sizeY * fracY;

            // top left
            SliceMeshVertex v = SliceMeshVertex();
            v.id = curV++;
            v.uv = Vec2D(startU, startV);
            v.vertex = Vec2D(curX, curY);
            curTile.emplace_back(v);

            // top right
            v = SliceMeshVertex();
            v.id = curV++;
            v.uv = Vec2D(endU1, startV);
            v.vertex = Vec2D(endX1, curY);
            curTile.emplace_back(v);

            // bottom right
            v = SliceMeshVertex();
            v.id = curV++;
            v.uv = Vec2D(endU1, endV1);
            v.vertex = Vec2D(endX1, endY1);
            curTile.emplace_back(v);

            // bottom left
            v = SliceMeshVertex();
            v.id = curV++;
            v.uv = Vec2D(startU, endV1);
            v.vertex = Vec2D(curX, endY1);
            curTile.emplace_back(v);

            // Commit the four vertices, and the triangulation
            vertices.insert(vertices.end(), curTile.begin(), curTile.end());
            for (uint16_t t : triangulation)
            {
                indices.emplace_back(v0 + t);
            }

            curX += sizeX;
        }
        curY += sizeY;
    }
    return curV - start;
}

void SliceMesh::calc()
{
    m_vertices = {};
    m_indices = {};
    m_uvs = {};

    std::vector<float> us = uvStops(AxisType::X);
    std::vector<float> vs = uvStops(AxisType::Y);
    std::vector<float> xs = vertexStops(us, AxisType::X);
    std::vector<float> ys = vertexStops(vs, AxisType::Y);
    const auto& tileModes = m_nslicer->tileModes();

    std::vector<SliceMeshVertex> vertices;
    uint16_t vertexIndex = 0;
    for (int patchY = 0; patchY < (int)vs.size() - 1; patchY++)
    {
        for (int patchX = 0; patchX < (int)us.size() - 1; patchX++)
        {
            auto tileModeIt =
                tileModes.find(m_nslicer->patchIndex(patchX, patchY));
            auto tileMode = tileModeIt == tileModes.end()
                                ? NSlicerTileModeType::STRETCH
                                : tileModeIt->second;

            // Do nothing if hidden
            if (tileMode == NSlicerTileModeType::HIDDEN)
            {
                continue;
            }

            const uint16_t v0 = vertexIndex;
            std::vector<SliceMeshVertex> patchVertices;
            for (const Corner& corner : patchCorners)
            {
                int xIndex = patchX + corner.x;
                int yIndex = patchY + corner.y;

                SliceMeshVertex v;
                if (tileMode != NSlicerTileModeType::REPEAT)
                {
                    v.id = vertexIndex++;
                }
                v.uv = Vec2D(us[xIndex], vs[yIndex]);
                v.vertex = Vec2D(xs[xIndex], ys[yIndex]);

                patchVertices.emplace_back(v);
            }

            if (tileMode == NSlicerTileModeType::REPEAT)
            {
                vertexIndex +=
                    tileRepeat(vertices, m_indices, patchVertices, v0);
            }
            else
            {
                vertices.insert(vertices.end(),
                                patchVertices.begin(),
                                patchVertices.end());
                for (uint16_t t : triangulation)
                {
                    m_indices.emplace_back(v0 + t);
                }
            }
        }
    }

    for (const SliceMeshVertex& v : vertices)
    {
        m_vertices.emplace_back(v.vertex);
        m_uvs.emplace_back(v.uv);
    }
}

void SliceMesh::update()
{
    // Make sure the image is loaded
    if (m_nslicer == nullptr || m_nslicer->image() == nullptr ||
        m_nslicer->image()->imageAsset() == nullptr)
    {
        return;
    }

    calc();
    updateBuffers();
}
