/*
 * Copyright 2022 Rive
 */

#include "rive_render_path.hpp"

#include "rive/math/bezier_utils.hpp"
#include "rive/math/simd.hpp"
#include "rive/math/wangs_formula.hpp"

namespace rive
{

RiveRenderPath::RiveRenderPath(FillRule fillRule, RawPath& rawPath)
{
    m_rawPath.swap(rawPath);
    m_rawPath.pruneEmptySegments();
}

void RiveRenderPath::rewind()
{
    assert(m_rawPathMutationLockCount == 0);
    m_rawPath.rewind();
    m_dirt = kAllDirt;
}

void RiveRenderPath::moveTo(float x, float y)
{
    assert(m_rawPathMutationLockCount == 0);
    m_rawPath.moveTo(x, y);
    m_dirt = kAllDirt;
}

void RiveRenderPath::lineTo(float x, float y)
{
    assert(m_rawPathMutationLockCount == 0);

    // Make sure to start a new contour, even if this line is empty.
    m_rawPath.injectImplicitMoveIfNeeded();

    Vec2D p1 = {x, y};
    if (m_rawPath.points().back() != p1)
    {
        m_rawPath.line(p1);
    }

    m_dirt = kAllDirt;
}

void RiveRenderPath::cubicTo(float ox,
                             float oy,
                             float ix,
                             float iy,
                             float x,
                             float y)
{
    assert(m_rawPathMutationLockCount == 0);

    // Make sure to start a new contour, even if this cubic is empty.
    m_rawPath.injectImplicitMoveIfNeeded();

    Vec2D p1 = {ox, oy};
    Vec2D p2 = {ix, iy};
    Vec2D p3 = {x, y};
    if (m_rawPath.points().back() != p1 || p1 != p2 || p2 != p3)
    {
        m_rawPath.cubic(p1, p2, p3);
    }

    m_dirt = kAllDirt;
}

void RiveRenderPath::close()
{
    assert(m_rawPathMutationLockCount == 0);
    m_rawPath.close();
    m_dirt = kAllDirt;
}

void RiveRenderPath::addRenderPath(RenderPath* path, const Mat2D& matrix)
{
    assert(m_rawPathMutationLockCount == 0);
    RiveRenderPath* riveRenderPath = static_cast<RiveRenderPath*>(path);
    RawPath::Iter transformedPathIter =
        m_rawPath.addPath(riveRenderPath->m_rawPath, &matrix);
    if (matrix != Mat2D())
    {
        // Prune any segments that became empty after the transform.
        m_rawPath.pruneEmptySegments(transformedPathIter);
    }
    m_dirt = kAllDirt;
}

const AABB& RiveRenderPath::getBounds() const
{
    if (m_dirt & kPathBoundsDirt)
    {
        m_bounds = m_rawPath.bounds();
        m_dirt &= ~kPathBoundsDirt;
    }
    return m_bounds;
}

float RiveRenderPath::getCoarseArea() const
{
    if (m_dirt & kPathCoarseAreaDirt)
    {
        float a = 0;
        Vec2D contourP0 = {0, 0}, lastPt = {0, 0};
        for (auto [verb, pts] : m_rawPath)
        {
            switch (verb)
            {
                case PathVerb::move:
                    a += Vec2D::cross(lastPt, contourP0);
                    contourP0 = lastPt = pts[0];
                    break;
                case PathVerb::close:
                    break;
                case PathVerb::line:
                    a += Vec2D::cross(lastPt, pts[1]);
                    lastPt = pts[1];
                    break;
                case PathVerb::quad:
                    RIVE_UNREACHABLE();
                case PathVerb::cubic:
                {
                    // Linearize the cubic in artboard space, then add up the
                    // area for each segment.
                    float n = ceilf(
                        wangs_formula::cubic(pts, 1.f / kCoarseAreaTolerance));
                    if (n > 1)
                    {
                        n = std::min(n, 64.f);
                        float4 t = float4{1, 1, 2, 2} * (1 / n);
                        float4 dt = t.w;
                        math::EvalCubic evalCubic(pts);
                        for (; t.x < 1; t += dt)
                        {
                            float4 p = evalCubic(t);
                            Vec2D lo = {p.x, p.y};
                            a += Vec2D::cross(lastPt, lo);
                            lastPt = lo;
                            if (t.y < 1)
                            {
                                Vec2D hi = {p.z, p.w};
                                a += Vec2D::cross(lastPt, hi);
                                lastPt = hi;
                            }
                        }
                    }
                    a += Vec2D::cross(lastPt, pts[3]);
                    lastPt = pts[3];
                    break;
                }
            }
        }
        a += Vec2D::cross(lastPt, contourP0);
        m_coarseArea = a * .5f;
        m_dirt &= ~kPathCoarseAreaDirt;
    }
    return m_coarseArea;
}

bool RiveRenderPath::isClockwiseDominant(const Mat2D& viewMatrix) const
{
    float matrixDeterminant =
        viewMatrix[0] * viewMatrix[3] - viewMatrix[2] * viewMatrix[1];
    return getCoarseArea() * matrixDeterminant >= 0;
}

uint64_t RiveRenderPath::getRawPathMutationID() const
{
    static std::atomic<uint64_t> uniqueIDCounter = 0;
    if (m_dirt & kRawPathMutationIDDirt)
    {
        m_rawPathMutationID = ++uniqueIDCounter;
        m_dirt &= ~kRawPathMutationIDDirt;
    }
    return m_rawPathMutationID;
}

void RiveRenderPath::setDrawCache(gpu::RiveRenderPathDraw* drawCache,
                                  const Mat2D& mat,
                                  rive::RiveRenderPaint* riveRenderPaint) const
{
    CacheElements& cache =
        m_cachedElements[riveRenderPaint->getIsStroked() ? CACHE_STROKED
                                                         : CACHE_FILLED];

    cache.draw = drawCache;

    cache.xx = mat.xx();
    cache.xy = mat.xy();
    cache.yx = mat.yx();
    cache.yy = mat.yy();

    if (riveRenderPaint->getIsStroked())
    {
        m_cachedThickness = riveRenderPaint->getThickness();
        m_cachedJoin = riveRenderPaint->getJoin();
        m_cachedCap = riveRenderPaint->getCap();
    }
}

gpu::DrawUniquePtr RiveRenderPath::getDrawCache(
    const Mat2D& matrix,
    const RiveRenderPaint* paint,
    FillRule fillRule,
    TrivialBlockAllocator* allocator,
    const gpu::RenderContext::FrameDescriptor& frameDesc,
    gpu::InterlockMode interlockMode) const
{
    const CacheElements& cache =
        m_cachedElements[paint->getIsStroked() ? CACHE_STROKED : CACHE_FILLED];

    if (cache.draw == nullptr)
    {
        return nullptr;
    }

    if (paint->getIsStroked())
    {
        if (m_cachedThickness != paint->getThickness())
        {
            return nullptr;
        }

        if (m_cachedJoin != paint->getJoin())
        {
            return nullptr;
        }

        if (m_cachedCap != paint->getCap())
        {
            return nullptr;
        }
    }

    if (matrix.xx() != cache.xx || matrix.xy() != cache.xy ||
        matrix.yx() != cache.yx || matrix.yy() != cache.yy)
    {
        return nullptr;
    }

    return gpu::DrawUniquePtr(
        allocator->make<gpu::RiveRenderPathDraw>(*cache.draw,
                                                 matrix.tx(),
                                                 matrix.ty(),
                                                 ref_rcp(this),
                                                 fillRule,
                                                 paint,
                                                 frameDesc,
                                                 interlockMode));
}
} // namespace rive
