/*
 * Copyright 2022 Rive
 */

#pragma once

#include "rive/math/raw_path.hpp"
#include "rive/renderer.hpp"
#include "rive/renderer/draw.hpp"
#include "rive_render_paint.hpp"

namespace rive
{
// RenderPath implementation for Rive's pixel local storage renderer.
class RiveRenderPath : public LITE_RTTI_OVERRIDE(RenderPath, RiveRenderPath)
{
public:
    RiveRenderPath() = default;
    RiveRenderPath(FillRule fillRule, RawPath& rawPath);

    void rewind() override;
    void fillRule(FillRule rule) override
    {
        if (m_fillRule == rule)
        {
            return;
        }
        m_fillRule = rule;
        // Most cached draws can be used interchangeably with any fill rule, but
        // if there is a triangulator, it needs to be invalidated when the fill
        // rule changes.
        if (m_cachedElements[CACHE_FILLED].draw != nullptr &&
            m_cachedElements[CACHE_FILLED].draw->triangulator() != nullptr)
        {
            invalidateDrawCache(CACHE_FILLED);
        }
    }

    void moveTo(float x, float y) override;
    void lineTo(float x, float y) override;
    void cubicTo(float ox, float oy, float ix, float iy, float x, float y)
        override;
    void close() override;

    void addPath(CommandPath* p, const Mat2D& m) override
    {
        addRenderPath(p->renderPath(), m);
    }
    void addRenderPath(RenderPath* path, const Mat2D& matrix) override;

    const RawPath& getRawPath() const { return m_rawPath; }
    FillRule getFillRule() const { return m_fillRule; }

    const AABB& getBounds() const;
    // Approximates the area of the path by linearizing it with a coarse
    // tolerance of 8px in artboard space.
    constexpr static float kCoarseAreaTolerance = 8;
    float getCoarseArea() const;
    // Determine if the path's signed, post-transform area is positive.
    bool isClockwiseDominant(const Mat2D& viewMatrix) const;
    uint64_t getRawPathMutationID() const;

    // Feathering does not always look like a blur when there is strong
    // curvature. This method returns a copy of the path with flatter curves
    // that will more accurately depict a gaussian blur when drawn with the
    // given feather.
    //
    // TODO: Move this work to the GPU.
    rcp<RiveRenderPath> makeSoftenedCopyForFeathering(float feather,
                                                      float matrixMaxScale);

#ifdef DEBUG
    // Allows ref holders to guarantee the rawPath doesn't mutate during a
    // specific time.
    void lockRawPathMutations() const { ++m_rawPathMutationLockCount; }
    void unlockRawPathMutations() const
    {
        assert(m_rawPathMutationLockCount > 0);
        --m_rawPathMutationLockCount;
    }
#endif

private:
    FillRule m_fillRule = FillRule::nonZero;
    RawPath m_rawPath;
    mutable AABB m_bounds;
    mutable float m_coarseArea;
    mutable uint64_t m_rawPathMutationID;

    enum Dirt
    {
        kPathBoundsDirt = 1 << 0,
        kRawPathMutationIDDirt = 1 << 1,
        kPathCoarseAreaDirt = 1 << 2,
        kAllDirt = ~0,
    };

    mutable uint32_t m_dirt = kAllDirt;
    RIVE_DEBUG_CODE(mutable int m_rawPathMutationLockCount = 0;)

public:
    void invalidateDrawCache() const
    {
        invalidateDrawCache(CACHE_STROKED);
        invalidateDrawCache(CACHE_FILLED);
    }

    void invalidateDrawCache(int index) const
    {
        m_cachedElements[index].draw = nullptr;
    }

    void setDrawCache(gpu::RiveRenderPathDraw* drawCache,
                      const Mat2D& mat,
                      rive::RiveRenderPaint* riveRenderPaint) const;

    gpu::DrawUniquePtr getDrawCache(const Mat2D& matrix,
                                    const RiveRenderPaint* paint,
                                    FillRule fillRule,
                                    TrivialBlockAllocator* allocator,
                                    const gpu::RenderContext::FrameDescriptor&,
                                    gpu::InterlockMode interlockMode) const;

private:
    enum
    {
        CACHE_STROKED,
        CACHE_FILLED,
        NUM_CACHES,
    };
    struct CacheElements
    {
        gpu::RiveRenderPathDraw* draw = nullptr;
        float xx;
        float xy;
        float yx;
        float yy;
    };
    mutable CacheElements m_cachedElements[NUM_CACHES];
    mutable float m_cachedThickness;
    mutable StrokeJoin m_cachedJoin;
    mutable StrokeCap m_cachedCap;
    mutable float m_cachedFeather;
};
} // namespace rive
