/*
 * Copyright 2022 Rive
 */

#include "rive/renderer/rive_renderer.hpp"

#include "rive_render_paint.hpp"
#include "rive_render_path.hpp"
#include "rive/math/math_types.hpp"
#include "rive/math/simd.hpp"
#include "rive/renderer/rive_render_image.hpp"
#include "rive/profiler/profiler_macros.h"

namespace rive
{
bool RiveRenderer::IsAABB(const RawPath& path, AABB* result)
{
    RIVE_PROF_SCOPE()
    // Any quadrilateral begins with a move plus 3 lines.
    constexpr static size_t kAABBVerbCount = 4;
    constexpr static PathVerb aabbVerbs[kAABBVerbCount] = {PathVerb::move,
                                                           PathVerb::line,
                                                           PathVerb::line,
                                                           PathVerb::line};
    Span<const PathVerb> verbs = path.verbs();
    if (verbs.count() < kAABBVerbCount ||
        memcmp(verbs.data(), aabbVerbs, sizeof(aabbVerbs)) != 0)
    {
        return false;
    }

    // Only accept extra verbs and points if every point after the quadrilateral
    // is equal to p0.
    Span<const Vec2D> pts = path.points();
    for (size_t i = 4; i < pts.count(); ++i)
    {
        if (pts[i] != pts[0])
        {
            return false;
        }
    }

    // We have a quadrilateral! Now check if it is an axis-aligned rectangle.
    float4 corners = {pts[0].x, pts[0].y, pts[2].x, pts[2].y};
    float4 oppositeCorners = {pts[1].x, pts[1].y, pts[3].x, pts[3].y};
    if (simd::all(corners == oppositeCorners.zyxw) ||
        simd::all(corners == oppositeCorners.xwzy))
    {
        float4 r = simd::join(simd::min(corners.xy, corners.zw),
                              simd::max(corners.xy, corners.zw));
        simd::store(result, r);
        return true;
    }
    return false;
}

RiveRenderer::ClipElement::ClipElement(const Mat2D& matrix_,
                                       const RiveRenderPath* path_,
                                       FillRule fillRule_)
{
    reset(matrix_, path_, fillRule_);
}

RiveRenderer::ClipElement::~ClipElement() {}

void RiveRenderer::ClipElement::reset(const Mat2D& matrix_,
                                      const RiveRenderPath* path_,
                                      FillRule fillRule_)
{
    matrix = matrix_;
    rawPathMutationID = path_->getRawPathMutationID();
    pathBounds = path_->getBounds();
    path = ref_rcp(path_);
    fillRule = fillRule_;
    clipID = 0; // This gets initialized lazily.
}

bool RiveRenderer::ClipElement::isEquivalent(const Mat2D& matrix_,
                                             const RiveRenderPath* path_) const
{
    return matrix_ == matrix &&
           path_->getRawPathMutationID() == rawPathMutationID &&
           path_->getFillRule() == fillRule;
}

RiveRenderer::RiveRenderer(gpu::RenderContext* context) : m_context(context) {}

RiveRenderer::~RiveRenderer() {}

void RiveRenderer::save()
{
    // Copy the back of the stack before pushing, in case the vector grows and
    // invalidates the reference.
    RenderState copy = m_stack.back();
    m_stack.push_back(copy);
}

void RiveRenderer::restore()
{
    assert(m_stack.size() > 1);
    assert(m_stack.back().clipStackHeight >=
           m_stack[m_stack.size() - 2].clipStackHeight);
    m_stack.pop_back();
}

void RiveRenderer::transform(const Mat2D& matrix)
{
    m_stack.back().matrix = m_stack.back().matrix * matrix;
}

void RiveRenderer::modulateOpacity(float opacity)
{
    m_stack.back().modulatedOpacity =
        std::max(0.0f, m_stack.back().modulatedOpacity * opacity);
}

void RiveRenderer::drawPath(RenderPath* renderPath, RenderPaint* renderPaint)
{
    RIVE_PROF_SCOPE()
    LITE_RTTI_CAST_OR_RETURN(path, RiveRenderPath*, renderPath);
    LITE_RTTI_CAST_OR_RETURN(paint, RiveRenderPaint*, renderPaint);

    if (path->getRawPath().empty())
    {
        return;
    }

    if (paint->getIsStroked() && m_context->frameDescriptor().strokesDisabled)
    {
        return;
    }
    if (!paint->getIsStroked() && m_context->frameDescriptor().fillsDisabled)
    {
        return;
    }
    if (paint->getIsStroked() &&
        // Use inverse logic to ensure we abort when stroke thickness is NaN.
        !(paint->getThickness() > 0))
    {
        return;
    }
    // Use inverse logic to ensure we abort when stroke thickness is NaN.
    if (!(paint->getFeather() >= 0))
    {
        return;
    }
    if (m_stack.back().clipIsEmpty)
    {
        return;
    }

    if (paint->getFeather() != 0 && !paint->getIsStroked())
    {
        if (path->getFillRule() != FillRule::clockwise &&
            !m_context->frameDescriptor().clockwiseFillOverride)
        {
            // Don't draw feathered fills that aren't clockwise.
            return;
        }
        float matrixMaxScale = m_stack.back().matrix.findMaxScale();
        if (paint->getFeather() * matrixMaxScale > 1)
        {
            clipAndPushDraw(gpu::PathDraw::Make(
                m_context,
                m_stack.back().matrix,
                path->makeSoftenedCopyForFeathering(paint->getFeather(),
                                                    matrixMaxScale),
                path->getFillRule(),
                paint,
                m_stack.back().modulatedOpacity,
                &m_scratchPath));
            return;
        }
    }

    clipAndPushDraw(gpu::PathDraw::Make(m_context,
                                        m_stack.back().matrix,
                                        ref_rcp(path),
                                        path->getFillRule(),
                                        paint,
                                        m_stack.back().modulatedOpacity,
                                        &m_scratchPath));
}

void RiveRenderer::clipPath(RenderPath* renderPath)
{
    RIVE_PROF_SCOPE()
    LITE_RTTI_CAST_OR_RETURN(path, RiveRenderPath*, renderPath);

    if (m_context->frameInterlockMode() == gpu::InterlockMode::clockwiseAtomic)
    {
        // Just discard clips in clockwiseAtomic mode for now.
        // TODO: Implement clipping in clockwiseAtomic mode.
        return;
    }

    if (m_stack.back().clipIsEmpty)
    {
        return;
    }

    if (path->getRawPath().empty())
    {
        m_stack.back().clipIsEmpty = true;
        return;
    }

    // First try to handle axis-aligned rectangles using the "ENABLE_CLIP_RECT"
    // shader feature. Multiple axis-aligned rectangles can be intersected into
    // a single rectangle if their matrices are compatible.
    AABB clipRectCandidate;
    if (m_context->frameSupportsClipRects() &&
        IsAABB(path->getRawPath(), &clipRectCandidate))
    {
        clipRectImpl(clipRectCandidate, path);
    }
    else
    {
        clipPathImpl(path);
    }
}

// Finds a new rect, if such a rect exists, such that:
//
//     currentMatrix * rect == newMatrix * newRect
//
// Returns true if *rect was replaced with newRect.
static bool transform_rect_to_new_space(AABB* rect,
                                        const Mat2D& currentMatrix,
                                        const Mat2D& newMatrix)
{
    if (currentMatrix == newMatrix)
    {
        return true;
    }
    Mat2D currentToNew;
    if (!newMatrix.invert(&currentToNew))
    {
        return false;
    }
    currentToNew = currentToNew * currentMatrix;
    float maxSkew = fmaxf(fabsf(currentToNew.xy()), fabsf(currentToNew.yx()));
    float maxScale = fmaxf(fabsf(currentToNew.xx()), fabsf(currentToNew.yy()));
    if (maxSkew > math::EPSILON && maxScale > math::EPSILON)
    {
        // Transforming this rect to the new view matrix would turn it into
        // something that isn't a rect.
        return false;
    }
    Vec2D pts[2] = {{rect->left(), rect->top()},
                    {rect->right(), rect->bottom()}};
    currentToNew.mapPoints(pts, pts, 2);
    float4 p = simd::load4f(pts);
    float2 topLeft = simd::min(p.xy, p.zw);
    float2 botRight = simd::max(p.xy, p.zw);
    *rect = {topLeft.x, topLeft.y, botRight.x, botRight.y};
    return true;
}

void RiveRenderer::clipRectImpl(AABB rect, const RiveRenderPath* originalPath)
{
    RIVE_PROF_SCOPE()
    bool hasClipRect = m_stack.back().clipRectInverseMatrix != nullptr;
    if (rect.isEmptyOrNaN())
    {
        m_stack.back().clipIsEmpty = true;
        return;
    }

    // If there already is a clipRect, we can only accept another one by
    // intersecting it with the existing one. This means the new rect must be
    // axis-aligned with the existing clipRect.
    if (hasClipRect &&
        !transform_rect_to_new_space(&rect,
                                     m_stack.back().matrix,
                                     m_stack.back().clipRectMatrix))
    {
        // 'rect' is not axis-aligned with the existing clipRect. Fall back to
        // clipPath.
        clipPathImpl(originalPath);
        return;
    }

    if (!hasClipRect)
    {
        // There wasn't an existing clipRect. This is the one!
        m_stack.back().clipRect = rect;
        m_stack.back().clipRectMatrix = m_stack.back().matrix;
    }
    else
    {
        // Both rects are in the same space now. Intersect the two
        // geometrically.
        float4 a = simd::load4f(&m_stack.back().clipRect);
        float4 b = simd::load4f(&rect);
        float4 intersection =
            simd::join(simd::max(a.xy, b.xy), simd::min(a.zw, b.zw));
        simd::store(&m_stack.back().clipRect, intersection);
    }

    m_stack.back().clipRectInverseMatrix =
        m_context->make<gpu::ClipRectInverseMatrix>(
            m_stack.back().clipRectMatrix,
            m_stack.back().clipRect);
}

void RiveRenderer::clipPathImpl(const RiveRenderPath* path)
{
    RIVE_PROF_SCOPE()
    if (path->getBounds().isEmptyOrNaN())
    {
        m_stack.back().clipIsEmpty = true;
        return;
    }
    // Only write a new clip element if this path isn't already on the stack
    // from before. e.g.:
    //
    //     clipPath(samePath);
    //     restore();
    //     save();
    //     clipPath(samePath); // <-- reuse the ClipElement (and clipID!)
    //     already in m_clipStack.
    //
    const size_t clipStackHeight = m_stack.back().clipStackHeight;
    assert(m_clipStack.size() >= clipStackHeight);
    if (m_clipStack.size() == clipStackHeight ||
        !m_clipStack[clipStackHeight].isEquivalent(m_stack.back().matrix, path))
    {
        m_clipStack.resize(clipStackHeight);
        m_clipStack.emplace_back(m_stack.back().matrix,
                                 path,
                                 path->getFillRule());
    }
    m_stack.back().clipStackHeight = clipStackHeight + 1;
}

void RiveRenderer::drawImage(const RenderImage* renderImage,
                             ImageSampler imageSampler,
                             BlendMode blendMode,
                             float opacity)
{
    RIVE_PROF_SCOPE()
    LITE_RTTI_CAST_OR_RETURN(image, const RiveRenderImage*, renderImage);

    rcp<gpu::Texture> imageTexture = image->refTexture();
    if (imageTexture == nullptr)
    {
        // imageTexture may be null if the backend uses a custom factory and/or
        // updates out-of-band assets asynchronously. If there's no texture yet,
        // just don't draw anything.
        return;
    }

    // Apply modulated opacity (clamp to prevent negative values)
    float finalOpacity =
        std::max(0.0f, opacity * m_stack.back().modulatedOpacity);

    // Scale the view matrix so we can draw this image as the rect [0, 0, 1, 1].
    save();
    scale(image->width(), image->height());

    if (!m_context->frameSupportsImagePaintForPaths())
    {
        // Fall back on ImageRectDraw if the current frame doesn't support
        // drawing paths with image paints.
        if (!m_stack.back().clipIsEmpty)
        {
            const Mat2D& m = m_stack.back().matrix;
            clipAndPushDraw(
                gpu::DrawUniquePtr(m_context->make<gpu::ImageRectDraw>(
                    m_context,
                    m.mapBoundingBox(AABB{0, 0, 1, 1}).roundOut(),
                    m,
                    blendMode,
                    std::move(imageTexture),
                    imageSampler,
                    finalOpacity)));
        }
    }
    else
    {
        // Implement drawImage() as drawPath() with a rectangular path and an
        // image paint.
        if (m_unitRectPath == nullptr)
        {
            m_unitRectPath = make_rcp<RiveRenderPath>();
            m_unitRectPath->line({1, 0});
            m_unitRectPath->line({1, 1});
            m_unitRectPath->line({0, 1});
        }

        RiveRenderPaint paint;
        paint.image(std::move(imageTexture), finalOpacity);
        paint.blendMode(blendMode);
        paint.imageSampler(imageSampler);
        drawPath(m_unitRectPath.get(), &paint);
    }

    restore();
}

void RiveRenderer::drawImageMesh(const RenderImage* renderImage,
                                 ImageSampler imageSampler,
                                 rcp<RenderBuffer> vertices_f32,
                                 rcp<RenderBuffer> uvCoords_f32,
                                 rcp<RenderBuffer> indices_u16,
                                 uint32_t vertexCount,
                                 uint32_t indexCount,
                                 BlendMode blendMode,
                                 float opacity)
{
    RIVE_PROF_SCOPE()
    LITE_RTTI_CAST_OR_RETURN(image, const RiveRenderImage*, renderImage);

    rcp<gpu::Texture> imageTexture = image->refTexture();
    if (imageTexture == nullptr)
    {
        // imageTexture may be null if the backend uses a custom factory and/or
        // updates out-of-band assets asynchronously. If there's no texture yet,
        // just don't draw anything.
        return;
    }

    assert(vertices_f32);
    assert(uvCoords_f32);
    assert(indices_u16);

    if (m_stack.back().clipIsEmpty)
    {
        return;
    }

    // Apply modulated opacity (clamp to prevent negative values)
    float finalOpacity =
        std::max(0.0f, opacity * m_stack.back().modulatedOpacity);

    clipAndPushDraw(gpu::DrawUniquePtr(
        m_context->make<gpu::ImageMeshDraw>(gpu::Draw::FULLSCREEN_PIXEL_BOUNDS,
                                            m_stack.back().matrix,
                                            blendMode,
                                            std::move(imageTexture),
                                            imageSampler,
                                            std::move(vertices_f32),
                                            std::move(uvCoords_f32),
                                            std::move(indices_u16),
                                            indexCount,
                                            finalOpacity)));
}

void RiveRenderer::clipAndPushDraw(gpu::DrawUniquePtr draw)
{
    RIVE_PROF_SCOPE()
    assert(!m_stack.back().clipIsEmpty);
    if (draw.get() == nullptr)
    {
        return;
    }
    if (m_context->isOutsideCurrentFrame(draw->pixelBounds()))
    {
        return;
    }

    // Make two attempts to issue the draw: once on the context as-is and once
    // with a clean flush.
    for (int i = 0; i < 2; ++i)
    {
        // Always make sure we begin this loop with the internal draw batch
        // empty, and clear it when we're done.
        struct AutoResetInternalDrawBatch
        {
        public:
            AutoResetInternalDrawBatch(RiveRenderer* renderer) :
                m_renderer(renderer)
            {
                assert(m_renderer->m_internalDrawBatch.empty());
            }
            ~AutoResetInternalDrawBatch()
            {
                m_renderer->m_internalDrawBatch.clear();
            }

        private:
            RiveRenderer* m_renderer;
        };

        AutoResetInternalDrawBatch aridb(this);

        auto applyClipResult = applyClip(draw.get());
        if (applyClipResult == ApplyClipResult::failure)
        {
            // There wasn't room in the GPU buffers for this path draw. Flush
            // and try again.
            m_context->logicalFlush();
            continue;
        }
        else if (applyClipResult == ApplyClipResult::clipEmpty)
        {
            return;
        }

        m_internalDrawBatch.push_back(std::move(draw));
        if (!m_context->pushDraws(m_internalDrawBatch.data(),
                                  m_internalDrawBatch.size()))
        {
            // There wasn't room in the GPU buffers for this path draw. Flush
            // and try again.
            m_context->logicalFlush();
            // Reclaim "draw" because we will use it again on the next
            // iteration.
            draw = std::move(m_internalDrawBatch.back());
            assert(draw != nullptr);
            m_internalDrawBatch.pop_back();
            continue;
        }

        // Success!
        return;
    }

    // We failed to process the draw. Release its refs.
    fprintf(stderr,
            "RiveRenderer::clipAndPushDraw failed. The draw and/or clip stack "
            "are too complex.\n");
}

RiveRenderer::ApplyClipResult RiveRenderer::applyClip(gpu::Draw* draw)
{
    RIVE_PROF_SCOPE()
    if (m_stack.back().clipIsEmpty)
    {
        return ApplyClipResult::clipEmpty;
    }
    draw->setClipRect(m_stack.back().clipRectInverseMatrix);

    const size_t clipStackHeight = m_stack.back().clipStackHeight;
    if (clipStackHeight == 0)
    {
        assert(draw->clipID() == 0);
        return ApplyClipResult::success;
    }

    // Find which clip element in the stack (if any) is currently rendered to
    // the clip buffer.
    size_t clipIdxCurrentlyInClipBuffer = -1; // i.e., "none".
    if (m_context->getClipContentID() != 0)
    {
        for (size_t i = clipStackHeight - 1; i != -1; --i)
        {
            if (m_clipStack[i].clipID == m_context->getClipContentID())
            {
                clipIdxCurrentlyInClipBuffer = i;
                break;
            }
        }
    }

    // Draw the necessary updates to the clip buffer (i.e., draw every clip
    // element after clipIdxCurrentlyInClipBuffer).
    uint32_t lastClipID =
        clipIdxCurrentlyInClipBuffer == -1
            ? 0 // The next clip to be drawn is not nested.
            : m_clipStack[clipIdxCurrentlyInClipBuffer].clipID;
    if (m_context->frameInterlockMode() == gpu::InterlockMode::msaa)
    {
        if (lastClipID == 0 && m_context->getClipContentID() != 0)
        {
            // Time for a new stencil clip! Erase the clip currently in the
            // stencil buffer before we draw the new one.
            auto stencilClipClear =
                gpu::DrawUniquePtr(m_context->make<gpu::StencilClipReset>(
                    m_context,
                    m_context->getClipContentID(),
                    gpu::DrawContents::none,
                    gpu::StencilClipReset::ResetAction::clearPreviousClip));
            if (!m_context->isOutsideCurrentFrame(
                    stencilClipClear->pixelBounds()))
            {
                m_internalDrawBatch.push_back(std::move(stencilClipClear));
            }
        }
    }

    for (size_t i = clipIdxCurrentlyInClipBuffer + 1; i < clipStackHeight; ++i)
    {
        ClipElement& clip = m_clipStack[i];
        assert(clip.pathBounds == clip.path->getBounds());

        IAABB clipDrawBounds;
        RiveRenderPaint clipUpdatePaint;
        clipUpdatePaint.clipUpdate(/*clip THIS clipDraw against:*/ lastClipID);

        gpu::DrawUniquePtr clipDraw =
            gpu::PathDraw::Make(m_context,
                                clip.matrix,
                                clip.path,
                                clip.fillRule,
                                &clipUpdatePaint,
                                1.0f, // no opacity modulation for clips
                                &m_scratchPath);

        if (clipDraw == nullptr)
        {
            return ApplyClipResult::clipEmpty;
        }
        clipDrawBounds = clipDraw->pixelBounds();

        // Generate a new clipID every time we (re-)render an element to the
        // clip buffer. (Each embodiment of the element needs its own
        // separate readBounds.)
        clip.clipID = m_context->generateClipID(clipDrawBounds);
        assert(clip.clipID != m_context->getClipContentID());
        if (clip.clipID == 0)
        {
            return ApplyClipResult::failure; // The context is out of
                                             // clipIDs. We will flush and
                                             // try again.
        }
        clipDraw->setClipID(clip.clipID);

        gpu::DrawContents clipDrawContents = clipDraw->drawContents();
        if (!m_context->isOutsideCurrentFrame(clipDrawBounds))
        {
            m_internalDrawBatch.push_back(std::move(clipDraw));
        }

        if (lastClipID != 0)
        {
            m_context->addClipReadBounds(lastClipID, clipDrawBounds);
            if (m_context->frameInterlockMode() == gpu::InterlockMode::msaa)
            {
                // When drawing nested stencil clips, we need to intersect them,
                // which involves erasing the region of the current clip in the
                // stencil buffer that is outside the the one we just drew.
                auto stencilClipIntersect =
                    gpu::DrawUniquePtr(m_context->make<gpu::StencilClipReset>(
                        m_context,
                        lastClipID,
                        clipDrawContents,
                        gpu::StencilClipReset::ResetAction::
                            intersectPreviousClip));
                if (!m_context->isOutsideCurrentFrame(
                        stencilClipIntersect->pixelBounds()))
                {
                    m_internalDrawBatch.push_back(
                        std::move(stencilClipIntersect));
                }
            }
        }

        lastClipID = clip.clipID; // Nest the next clip (if any) inside the one
                                  // we just rendered.
    }
    assert(lastClipID == m_clipStack[clipStackHeight - 1].clipID);
    draw->setClipID(lastClipID);
    m_context->addClipReadBounds(lastClipID, draw->pixelBounds());
    m_context->setClipContentID(lastClipID);
    return ApplyClipResult::success;
}
} // namespace rive
