/*
 * 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"
#include "shaders/constants.glsl"

namespace rive
{

RiveRenderPath::RiveRenderPath(FillRule fillRule, RawPath& rawPath)
{
    m_fillRule = fillRule;
    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;
}

// When a blurred shape curves away from the convolution matrix, the curvature
// makes the blur softer, which does not happen naturally in feathering.
//
// To simulate the softening effect from curving away, we flatten curves
// proportionaly to curvature. This works really well for gaussian feathers, but
// we may also split the curve and recurse if there is enough flattening to
// become noticeable.
//
// TODO: Move this work to the GPU.
static void add_softened_cubic_for_feathering(RawPath* featheredPath,
                                              const Vec2D p[4],
                                              float feather,
                                              float matrixMaxScale,
                                              int maxDepth = 3)
{
    float2 p0 = simd::load2f(p), p1 = simd::load2f(p + 1),
           p2 = simd::load2f(p + 2), p3 = simd::load2f(p + 3);
    math::CubicCoeffs coeffs(p);

    // Find the point of maximum height on the cubic.
    float maxHeightT;
    float height = math::find_cubic_max_height(p, &maxHeightT);

    // Measure curvature across one standard deviation of the feather.
    // ("feather" is 2 std devs.)
    float desiredSpread = feather * .5f;

    // The feather gets dimmer with curvature. Find a dimming factor based on
    // the strength of curvature at maximum height.
    float theta = math::measure_cubic_local_curvature(p,
                                                      coeffs,
                                                      maxHeightT,
                                                      desiredSpread);
    float dimming = 1 - theta * (1 / math::PI);

    // Always dim a little bit in order to avoid artifacts on tight cusps.
    // FIXME: This is unfortunate. There must be a better way to handle cusps.
    dimming = fminf(dimming, .925f);

    // Find a new height such that the center of the feather (currently 50%
    // opacity) is reduced to "50% * dimming".
    float desiredOpacityOnCenter = .5f * dimming;
    float x = gpu::inverse_gaussian_integral(desiredOpacityOnCenter) - .5f;
    float newHeight = height + feather * FEATHER_TEXTURE_STDDEVS * x;

    if (maxDepth > 0 && (height - newHeight) * matrixMaxScale > 8)
    {
        // The curve would be flattened too much. Chop at max height and
        // recurse.
        Vec2D pp[7];
        math::chop_cubic_at(p, pp, maxHeightT);
        add_softened_cubic_for_feathering(featheredPath,
                                          pp,
                                          feather,
                                          matrixMaxScale,
                                          maxDepth - 1);
        add_softened_cubic_for_feathering(featheredPath,
                                          pp + 3,
                                          feather,
                                          matrixMaxScale,
                                          maxDepth - 1);
        return;
    }

    // Flatten the curve down to "newHeight". (Height scales linearly as we lerp
    // the control points to "flatLinePoints".)
    float4 flatLinePoints =
        simd::mix(p0.xyxy, p3.xyxy, float4{1.f / 3, 1.f / 3, 2.f / 3, 2.f / 3});
    float softness = height != 0 ? 1 - newHeight / height : 1;
    // Do the "min" first so softness is 1 if anything went NaN.
    softness = fmaxf(0, fminf(softness, 1));
    assert(softness >= 0 && softness <= 1);
    float4 softenedPoints = simd::unchecked_mix(simd::join(p1, p2),
                                                flatLinePoints,
                                                float4(softness));
    featheredPath->cubic(math::bit_cast<Vec2D>(softenedPoints.xy),
                         math::bit_cast<Vec2D>(softenedPoints.zw),
                         p[3]);
}

rcp<RiveRenderPath> RiveRenderPath::makeSoftenedCopyForFeathering(
    float feather,
    float matrixMaxScale)
{
    RawPath featheredPath;
    // Reserve a generous amount of space upfront so we hopefully don't have to
    // reallocate -- enough for each verb to be chopped 4 times.
    featheredPath.reserve(m_rawPath.verbs().size() * 4,
                          m_rawPath.points().size() * 4);
    for (auto [verb, pts] : m_rawPath)
    {
        switch (verb)
        {
            case PathVerb::move:
                featheredPath.move(pts[0]);
                break;
            case PathVerb::line:
                featheredPath.line(pts[1]);
                break;
            case PathVerb::cubic:
            {
                // Start by chopping all cubics so they are convex and rotate no
                // more than 90 degrees. The stroke algorithm requires them not
                // to have inflections
                float T[4];
                Vec2D chops[(std::size(T) + 1) * 3 + 1]; // 4 chops will produce
                                                         // 16 cubic vertices.
                bool areCusps;
                // A generous cusp padding looks better empirically.
                constexpr static float CUSP_PADDING = 1e-2f;
                int n = math::find_cubic_convex_90_chops(pts,
                                                         T,
                                                         CUSP_PADDING,
                                                         &areCusps);
                math::chop_cubic_at(pts, chops, T, n);
                Vec2D* p = chops;
                for (int i = 0; i <= n; ++i, p += 3)
                {
                    if (areCusps && (i & 1))
                    {
                        // If the chops are straddling cusps, odd-numbered chops
                        // are the ones that pass through a cusp.
                        featheredPath.line(p[3]);
                    }
                    else
                    {
                        add_softened_cubic_for_feathering(&featheredPath,
                                                          p,
                                                          feather,
                                                          matrixMaxScale);
                    }
                }
                break;
            }
            case PathVerb::close:
                featheredPath.close();
                break;
            case PathVerb::quad:
                RIVE_UNREACHABLE();
        }
    }
    return make_rcp<RiveRenderPath>(m_fillRule, featheredPath);
}

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();
    }
    m_cachedFeather = riveRenderPaint->getFeather();
}

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 (m_cachedFeather != paint->getFeather())
    {
        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
