#include "rive/constraints/constraint.hpp"
#include "rive/hittest_command_path.hpp"
#include "rive/shapes/deformer.hpp"
#include "rive/shapes/path.hpp"
#include "rive/shapes/points_path.hpp"
#include "rive/shapes/parametric_path.hpp"
#include "rive/shapes/shape.hpp"
#include "rive/layout/layout_participant.hpp"
#include "rive/shapes/clipping_shape.hpp"
#include "rive/shapes/paint/blend_mode.hpp"
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/shapes/path_composer.hpp"
#include "rive/artboard.hpp"
#include "rive/clip_result.hpp"
#include "rive/math/contour_measure.hpp"
#include "rive/math/raw_path.hpp"
#include "rive/profiler/profiler_macros.h"
#include <algorithm>

using namespace rive;

Shape::Shape() : m_PathComposer(this) {}

void Shape::addPath(Path* path)
{
    // Make sure the path is not already in the shape.
    assert(std::find(m_Paths.begin(), m_Paths.end(), path) == m_Paths.end());
    m_Paths.push_back(path);
    invalidateIntrinsicBounds();
}

void Shape::addFlags(PathFlags flags) { m_pathFlags |= flags; }
bool Shape::isFlagged(PathFlags flags) const
{
    return (int)(pathFlags() & flags) != 0x00;
}

bool Shape::canDeferPathUpdate()
{
    auto canDefer =
        renderOpacity() == 0 &&
        !isFlagged(PathFlags::clipping | PathFlags::neverDeferUpdate);
    if (canDefer)
    {
        // If we have a dependent Skin, don't defer the update
        for (auto d : dependents())
        {
            if (d->is<PointsPath>() && d->as<PointsPath>()->skin() != nullptr)
            {
                return false;
            }
        }
    }
    return canDefer;
}

void Shape::update(ComponentDirt value)
{
    Super::update(value);

    if (hasDirt(value, ComponentDirt::RenderOpacity))
    {
        propagateOpacity(renderOpacity());
    }
}

bool Shape::collapse(bool value)
{
    if (!Super::collapse(value))
    {
        return false;
    }
    m_PathComposer.collapse(value);
    // Collapsed paths are skipped when measuring, so the bounds change.
    invalidateIntrinsicBounds();
    return true;
}

float Shape::length()
{
    if (m_WorldLength < 0)
    {
        float l = 0;
        for (auto path : m_Paths)
        {
            const bool pathDirty = path->hasDirt(ComponentDirt::Path |
                                                 ComponentDirt::WorldTransform |
                                                 ComponentDirt::NSlicer);
            RawPath temp;
            const RawPath& base =
                pathDirty ? (path->buildPath(temp), temp) : path->rawPath();
            RawPath source = base.transform(path->pathTransform());
            ContourMeasureIter iter(&source);
            while (auto contour = iter.next())
            {
                l += contour->length();
            }
        }
        m_WorldLength = l;
    }
    return m_WorldLength;
}

void Shape::pathChanged()
{
    m_PathComposer.addDirt(ComponentDirt::Path, true);
    m_WorldLength = -1;
    invalidateIntrinsicBounds();
    for (auto constraint : constraints())
    {
        constraint->addDirt(ComponentDirt::Path);
    }
    invalidateStrokeEffects();
}

void Shape::addToRenderPath(RenderPath* path, const Mat2D& transform)
{
    if (isFlagged(PathFlags::local))
    {
        path->addPath(m_PathComposer.localPath()->renderPath(this),
                      transform * worldTransform());
    }
    else
    {
        path->addPath(m_PathComposer.worldPath()->renderPath(this), transform);
    }
}

void Shape::addToRawPath(RawPath& path, const Mat2D* transform)
{
    if (isFlagged(PathFlags::local))
    {
        Mat2D xform = transform == nullptr ? worldTransform()
                                           : (*transform) * worldTransform();
        path.addPath(*m_PathComposer.localPath()->rawPath(), &xform);
    }
    else
    {
        path.addPath(*m_PathComposer.worldPath()->rawPath(), transform);
    }
}

void Shape::draw(Renderer* renderer)
{
    RIVE_PROF_SCOPE_L(2)
    auto needsSaveOperation = m_needsSaveOperation || m_ShapePaints.size() > 1;
    for (auto shapePaint : m_ShapePaints)
    {
        if (!shapePaint->isVisible())
        {
            continue;
        }
        auto shapePaintPath = shapePaint->pickPath(this);
        if (shapePaintPath == nullptr)
        {
            continue;
        }
        shapePaint->draw(renderer,
                         shapePaintPath,
                         worldTransform(),
                         false,
                         nullptr,
                         needsSaveOperation);
    }
}

bool Shape::hitTestAABB(const Vec2D& position)
{
    return worldBounds().contains(position);
}

bool Shape::hitTestHiFi(const Vec2D& position, float hitRadius)
{
    auto hitArea = AABB(position.x - hitRadius,
                        position.y - hitRadius,
                        position.x + hitRadius,
                        position.y + hitRadius)
                       .round();
    HitTestCommandPath tester(hitArea);

    for (auto path : m_Paths)
    {
        if (!path->isCollapsed())
        {
            tester.setXform(path->pathTransform());
            path->rawPath().addTo(&tester);
        }
    }
    return tester.wasHit();
}

Core* Shape::hitTest(HitInfo* hinfo, const Mat2D& xform)
{
    if (renderOpacity() == 0.0f)
    {
        return nullptr;
    }

    // TODO: clip:

    const bool shapeIsLocal =
        isFlagged(PathFlags::local | PathFlags::localClockwise);

    for (auto rit = m_ShapePaints.rbegin(); rit != m_ShapePaints.rend(); ++rit)
    {
        auto shapePaint = *rit;
        if (shapePaint->isTranslucent())
        {
            continue;
        }
        if (!shapePaint->isVisible())
        {
            continue;
        }

        auto paintIsLocal =
            shapePaint->isFlagged(PathFlags::local | PathFlags::localClockwise);

        auto mx = xform;
        if (paintIsLocal)
        {
            mx *= worldTransform();
        }

        HitTestCommandPath tester(hinfo->area);

        for (auto path : m_Paths)
        {
            if (shapeIsLocal)
            {
                tester.setXform(xform * path->pathTransform());
            }
            else
            {
                tester.setXform(mx * path->pathTransform());
            }
            path->rawPath().addTo(&tester);
        }
        if (tester.wasHit())
        {
            return this;
        }
    }
    return nullptr;
}

bool Shape::hitTestPoint(const Vec2D& position,
                         bool skipOnUnclipped,
                         bool isPrimaryHit)
{
    // If we're NOT the primary hit test, don't perform the AABB hit test
    // just keep walking up the tree
    if (!isPrimaryHit)
    {
        return Component::hitTestPoint(position, skipOnUnclipped, isPrimaryHit);
    }
    // Only perform the AABB hit test if we're the primary hit test
    // This prevents walking up the tree and having another shape return a
    // false hit test because we're not hitting their AABB
    if (hitTestAABB(position) &&
        Component::hitTestPoint(position, skipOnUnclipped, isPrimaryHit))
    {
        return hitTestHiFi(position, 2);
    }
    return false;
}

void Shape::buildDependencies()
{
    // Make sure to propagate the call to PathComposer as it's no longer part of
    // Core and owned only by the Shape.
#ifdef WITH_RIVE_EDITOR
    // PathComposer is constructed as a Shape member; it's not a Core in the
    // arena and not reachable via parentId. Component::onAddedDirty's
    // editor branch (parentId chain walk) leaves its m_Artboard null and
    // m_DependencyHelper.m_dependecyRoot uninitialized. Any subsequent
    // `addDirt` from `m_PathComposer` (e.g. Shape::pathChanged →
    // m_PathComposer.addDirt(Path, true)) calls onComponentDirty on a
    // garbage pointer and crashes. The runtime path side-steps this
    // because Component::onAddedDirty's runtime branch sets
    // `m_Artboard = static_cast<Artboard*>(context)` unconditionally
    // before any subsequent addDirt path runs. Mirror that here:
    // forward Shape's wired artboard to its owned PathComposer.
    if (artboard() != nullptr)
    {
        m_PathComposer.setArtboardForEditor(artboard());
    }
    // PathComposer isn't an arena Core (lives as a value member of
    // Shape), so editor_native's Pass B-prep-dependents `forEachLive`
    // sweep doesn't reach it — its `m_Dependents` accumulates entries
    // across batches and never gets cleaned. Components that depend
    // on PathComposer (e.g. ClippingShape, via
    // `shape->pathComposer()->addDependent(this)` in their
    // buildDependencies) leave dangling pointers after they're freed,
    // and the next dirt cascade through pathComposer crashes on the
    // stale entries. Mirror Pass B-prep's effect here so PathComposer
    // also starts each batch with a clean dependents list — Pass B's
    // buildDependencies loop re-adds the live edges (this calls
    // `PathComposer::buildDependencies` below, and per-type editor
    // overrides like `ClippingShape`, `Feather`, `FollowPathConstraint`,
    // `TextFollowPathModifier` re-register themselves in their own
    // buildDependencies calls).
    m_PathComposer.editorClearDependents();
#endif
    m_PathComposer.buildDependencies();

    Super::buildDependencies();

    // Set the blend mode on all the shape paints. If we ever animate this
    // property, we'll need to update it in the update cycle/mark dirty when the
    // blend mode changes.
    for (auto paint : m_ShapePaints)
    {
        paint->blendMode(blendMode());
    }
}

StatusCode Shape::onAddedDirty(CoreContext* context)
{
    auto code = Super::onAddedDirty(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }
#ifdef WITH_RIVE_EDITOR
    // PathComposer is a Shape value-member, not in the arena, with no
    // CoopId. `Component::onAddedDirty`'s editor branch tries to
    // resolve its (empty) `parentId()` and returns MissingObject,
    // which propagates here and gets the entire Shape culled in
    // Pass 4-cull, leaving the artboard with zero drawables.
    //
    // Mirrors Dart `Shape` (rive_core/lib/shapes/shape.dart:374-380),
    // which only propagates `buildDependencies()` to pathComposer —
    // never `onAddedDirty`. The runtime branch's optimization
    // (`m_Artboard = static_cast<Artboard*>(context)` via Component's
    // runtime branch) makes onAddedDirty work in runtime build only.
    // In editor mode, PathComposer's artboard wiring happens via the
    // `setArtboardForEditor` workaround in `Shape::buildDependencies`.
    //
    // TODO(value-member helpers): a more general fix would be to give
    // value-member helpers like PathComposer an arena registration so
    // `Component::onAddedDirty`'s editor branch can detect "no arena,
    // run runtime branch instead." Would auto-handle future helpers
    // without per-callsite ifdefs. For now, mirror Dart with a
    // targeted skip.
    return StatusCode::Ok;
#else
    // This ensures context propagates to path composer too.
    return m_PathComposer.onAddedDirty(context);
#endif
}

StatusCode Shape::onAddedClean(CoreContext* context)
{
    StatusCode code = Super::onAddedClean(context);
    if (code != StatusCode::Ok)
    {
        return code;
    }

    // Find the deformer, if any.
    m_deformer = nullptr;
    for (auto currentParent = parent(); currentParent != nullptr;
         currentParent = currentParent->parent())
    {
        RenderPathDeformer* deformer = RenderPathDeformer::from(currentParent);
        if (deformer)
        {
            m_deformer = deformer;
            return StatusCode::Ok;
        }
    }

    return StatusCode::Ok;
}

bool Shape::isEmpty()
{
    for (auto path : m_Paths)
    {
        if (!path->isHidden() && !path->isCollapsed())
        {
            return false;
        }
    }
    return true;
}

bool Shape::willDraw() { return Super::willDraw() && renderOpacity() != 0.0f; }

// Do constraints need to be marked as dirty too? From tests it doesn't seem
// they do.
void Shape::pathCollapseChanged() { m_PathComposer.pathCollapseChanged(); }

class ComputeBoundsCommandPath : public CommandPath
{
public:
    ComputeBoundsCommandPath() {}

    AABB bounds(const Mat2D& xform)
    {
        m_rawPath.transformInPlace(xform);
        return m_rawPath.bounds();
    }

    // Tight curve bounds (solves cubic extrema) rather than the control-point
    // box, so a participant sizing to its geometry scales to fill exactly.
    AABB preciseBounds(const Mat2D& xform)
    {
        m_rawPath.transformInPlace(xform);
        return m_rawPath.preciseBounds();
    }

    void rewind() override { m_rawPath.rewind(); }
    void fillRule(FillRule value) override {}
    void addPath(CommandPath* path, const Mat2D& transform) override
    {
        assert(false);
    }

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

    RenderPath* renderPath() override
    {
        assert(false);
        return nullptr;
    }

    const RenderPath* renderPath() const override
    {
        assert(false);
        return nullptr;
    }

private:
    RawPath m_rawPath;
};

AABB Shape::computeWorldBounds(const Mat2D* xform) const
{
    bool first = true;
    AABB computedBounds = AABB::forExpansion();

    ComputeBoundsCommandPath boundsCalculator;
    for (auto path : m_Paths)
    {
        if (path->isCollapsed())
        {
            continue;
        }
        path->rawPath().addTo(&boundsCalculator);

        AABB aabb = boundsCalculator.bounds(
            xform == nullptr ? path->pathTransform()
                             : path->pathTransform() * *xform);

        if (first)
        {
            first = false;
            computedBounds = aabb;
        }
        else
        {
            computedBounds.expand(aabb);
        }
        boundsCalculator.rewind();
    }

    return computedBounds;
}

AABB Shape::computeLocalBounds() const
{
    const Mat2D& world = worldTransform();
    Mat2D inverseWorld = world.invertOrIdentity();
    return computeWorldBounds(&inverseWorld);
}

AABB Shape::computeIntrinsicBounds() const
{
    // Only a participant caches (and only a participant calls this); without
    // one we just compute, so a plain Shape stores nothing.
    auto* participant = layoutParticipant();
    if (participant != nullptr && participant->hostBoundsValid())
    {
        return participant->hostBounds();
    }
    // Like computeWorldBounds but in this shape's local space, using each
    // path's local transform directly instead of round-tripping through our
    // (non-invertible when the layout fold is 0) world transform.
    bool first = true;
    AABB computedBounds = AABB::forExpansion();

    ComputeBoundsCommandPath boundsCalculator;
    RawPath pendingPath;
    bool usedPendingBuild = false;
    for (auto path : m_Paths)
    {
        if (path->isCollapsed())
        {
            continue;
        }
        AABB aabb;
        AABB propertyBounds;
        if (!path->needsPathBuild())
        {
            path->rawPath().addTo(&boundsCalculator);
            aabb = boundsCalculator.preciseBounds(path->transform());
            boundsCalculator.rewind();
        }
        else if (path->tryPropertyBounds(propertyBounds))
        {
            // Layout (and a participant's fit scale) runs before Path::update
            // in the update pass. A parametric path only positions its vertices
            // there, so building it here would measure an unpositioned path —
            // take its declared box instead, which is what it will occupy.
            usedPendingBuild = true;
            aabb = path->transform().mapBoundingBox(propertyBounds);
        }
        else
        {
            // Vertex-driven: the vertices are authored, so building a throwaway
            // copy measures real geometry. Without this a fill participant
            // computes a scale of 1 and renders at its hugged size on frame 1.
            usedPendingBuild = true;
            pendingPath.rewind();
            path->buildPath(pendingPath);
            pendingPath.addTo(&boundsCalculator);
            aabb = boundsCalculator.preciseBounds(path->transform());
            boundsCalculator.rewind();
        }
        // An empty (vertex-less) path leaves preciseBounds at its expansion
        // sentinel, which is inverted (+/-FLT_MAX). Folding that in would
        // poison the bounds, and a participant's anchor derives from them —
        // pushing its world translation to -FLT_MAX. Written as !(>= 0) so a
        // NaN is rejected too; a real but degenerate path (zero width or
        // height) still counts.
        if (!(aabb.width() >= 0.0f && aabb.height() >= 0.0f))
        {
            continue;
        }
        if (first)
        {
            first = false;
            computedBounds = aabb;
        }
        else
        {
            computedBounds.expand(aabb);
        }
    }

    AABB bounds = first ? AABB() : computedBounds;
    if (participant != nullptr)
    {
        // Anything measured before its build is provisional: a declared box can
        // be wider than the precise geometry (a polygon is inscribed in it).
        // Return it, but don't cache it, so the precise bounds win once the
        // paths build — nothing invalidates on the build itself, only when dirt
        // is added.
        participant->hostBounds(bounds, /*cache*/ !usedPendingBuild);
    }
    return bounds;
}

void Shape::invalidateIntrinsicBounds()
{
    if (auto* participant = layoutParticipant())
    {
        participant->invalidateHostBounds();
    }
}

static ParametricPath* firstParametricPath(std::vector<Path*>& paths)
{
    for (auto path : paths)
    {
        if (path->is<ParametricPath>())
        {
            return path->as<ParametricPath>();
        }
    }
    return nullptr;
}

Vec2D Shape::measureLayout(float width,
                           LayoutMeasureMode widthMode,
                           float height,
                           LayoutMeasureMode heightMode)
{
#ifdef WITH_RIVE_LAYOUT
    // A participant sizes to its combined bounds (all paths); controlSize then
    // scales those bounds to fill the slot.
    if (isParticipatingInLayout())
    {
        AABB bounds = computeIntrinsicBounds();
        return Vec2D(bounds.width(), bounds.height());
    }
#endif
    Vec2D size = Vec2D();
    for (auto path : m_Paths)
    {
        Vec2D measured =
            path->measureLayout(width, widthMode, height, heightMode);
        size =
            Vec2D(std::max(size.x, measured.x), std::max(size.y, measured.y));
    }
    return size;
}

void Shape::controlSize(Vec2D size,
                        LayoutScaleType widthScaleType,
                        LayoutScaleType heightScaleType,
                        LayoutDirection direction)
{
#ifdef WITH_RIVE_LAYOUT
    // A participant scales its combined bounds to fill the slot.
    if (isParticipatingInLayout())
    {
        updateLayoutScale(size);
        return;
    }
#endif
    // Content: a parametric shape's size lives on its ParametricPath child.
    if (auto* path = firstParametricPath(m_Paths))
    {
        path->controlSize(size, widthScaleType, heightScaleType, direction);
    }
}

void Shape::updateLayoutScale(Vec2D size)
{
    // Only reached from the participant branch of controlSize.
    auto* participant = layoutParticipant();
    if (participant == nullptr)
    {
        return;
    }
    AABB bounds = computeIntrinsicBounds();
    float w = bounds.width();
    float h = bounds.height();
    // intrinsicBounds is from local geometry (not the world round-trip) so it
    // stays valid even at scale 0.
    float newScaleX = w > 0.0f ? size.x / w : 1.0f;
    float newScaleY = h > 0.0f ? size.y / h : 1.0f;
    if (newScaleX != participant->hostScaleX() ||
        newScaleY != participant->hostScaleY())
    {
        participant->hostScale(newScaleX, newScaleY);
        markWorldTransformDirty();
    }
}

// The whole shape scales to fit, so place the scaled combined-bounds top-left
// at the slot (the origin is irrelevant once we scale).
LayoutParticipant* Shape::layoutParticipant() const
{
    for (auto* child : children())
    {
        if (child->is<LayoutParticipant>())
        {
            return child->as<LayoutParticipant>();
        }
    }
    return nullptr;
}

bool Shape::isParticipatingInLayout() const
{
    return layoutParticipant() != nullptr;
}

Vec2D Shape::layoutBaseTranslation(LayoutParticipant* participant) const
{
    assert(participant != nullptr);
    AABB intrinsic = computeIntrinsicBounds();
    return Vec2D(participant->resolvedLeft() -
                     intrinsic.left() * participant->hostScaleX(),
                 participant->resolvedTop() -
                     intrinsic.top() * participant->hostScaleY());
}

void Shape::composeWorldTransform()
{
#ifdef WITH_RIVE_LAYOUT
    auto* participant = layoutParticipant();
    if (participant != nullptr && m_ParentTransformComponent != nullptr)
    {
        // Scale innermost so it fits the geometry to the resolved box, with
        // our own transform composing on top.
        float scaleX = participant->hostScaleX();
        float scaleY = participant->hostScaleY();
        Mat2D base = Mat2D::fromTranslation(layoutBaseTranslation(participant));
        m_WorldTransform = m_ParentTransformComponent->worldTransform() * base *
                           m_Transform * Mat2D::fromScale(scaleX, scaleY);
        return;
    }
#endif
    Super::composeWorldTransform();
}

void Shape::updateConstraints()
{
#ifdef WITH_RIVE_LAYOUT
    auto* participant = layoutParticipant();
    if (participant != nullptr)
    {
        participant->applyLayoutConstraints();
    }
#endif
    Super::updateConstraints();
}

ShapePaintPath* Shape::worldPath() { return m_PathComposer.worldPath(); }
ShapePaintPath* Shape::localPath() { return m_PathComposer.localPath(); }
ShapePaintPath* Shape::localClockwisePath()
{
    return m_PathComposer.localClockwisePath();
}

Component* Shape::pathBuilder() { return &m_PathComposer; }