#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/shapes/paint/paint_outset.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>
#include <limits>

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);
    if (path->is<PointsPath>() && path->as<PointsPath>()->skin() != nullptr)
    {
        // Bones deform a skinned path whether or not the shape is visible.
        addFlags(PathFlags::neverDeferUpdate);
    }
    invalidateIntrinsicBounds();
}

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

bool Shape::canDeferPathUpdate()
{
    if (renderOpacity() != 0 ||
        isFlagged(PathFlags::clipping | PathFlags::neverDeferUpdate))
    {
        return false;
    }
#ifdef WITH_RIVE_EDITOR
    // Skins come and go under the editor, after addPath set its flag.
    for (auto path : m_Paths)
    {
        if (path->is<PointsPath>() && path->as<PointsPath>()->skin() != nullptr)
        {
            return false;
        }
    }
#endif
    return true;
}

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;
    // Drop the local bounds here rather than only in markBoundsDirty(): this is
    // raised for every input they have (Path geometry and Path transform), and
    // it still fires when the composer defers its update (a transparent,
    // non-clipping shape), where markBoundsDirty() never runs.
    m_LocalBoundsClean = false;
    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 =
        Drawable::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();

    syncShapePaintBlendModes();
}

void Shape::syncShapePaintBlendModes()
{
    for (auto paint : m_ShapePaints)
    {
        paint->blendMode(blendMode(), additiveAmount());
    }
}

// blendModeValue itself never animates, but additiveAmount does (and data
// binds), so the buildDependencies sync above is not enough on its own.
void Shape::additiveAmountChanged() { syncShapePaintBlendModes(); }

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()
{
    // Collapsed paths are skipped when measuring, so which paths are in the
    // bounds just changed. Drop the cache here for the same reason
    // pathChanged() does: the composer's update, and with it markBoundsDirty(),
    // is deferred for a transparent, non-clipping shape.
    m_LocalBoundsClean = false;
    m_PathComposer.pathCollapseChanged();
}

BoundsFidelity Shape::paintedWorldBounds(AABB* out)
{
    AABB bounds = worldBounds();
    if (bounds.isEmptyOrNaN())
    {
        // Every path collapsed, so worldBounds() is still the forExpansion()
        // sentinel -- (+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX). Hand back an
        // empty box instead: nothing is painted, and letting the sentinel out
        // would blow any union it lands in out to the float range.
        *out = AABB();
        return BoundsFidelity::exact;
    }

    // worldBounds() is geometry. A stroke straddles it, a miter join overshoots
    // the corners, a feather blurs outward past all of it -- so pad by the
    // furthest-reaching paint.
    const PaintReach reach = shapePaintsWorldReach(this, worldTransform());
    if (reach.worldOutset > 0.0f)
    {
        bounds = bounds.outset(reach.worldOutset, reach.worldOutset);
    }
    *out = bounds;
    return reach.trustworthy ? BoundsFidelity::exact
                             : BoundsFidelity::approximate;
}

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

    for (auto path : m_Paths)
    {
        if (path->isCollapsed())
        {
            continue;
        }
        // The control point hull, transformed: Mat2D::mapBoundingBox fuses the
        // transform and the min/max into one SIMD pass over the points, so we
        // never copy the path just to measure it. (A Path's raw path only ever
        // holds moves, lines and cubics, so there are no quadratic control
        // points needing conversion first.)
        const Mat2D transform = xform == nullptr
                                    ? path->pathTransform()
                                    : *xform * path->pathTransform();
        AABB aabb = transform.mapBoundingBox(path->rawPath().points());

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

    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();

    RawPath pendingPath;
    bool usedPendingBuild = false;
    for (auto path : m_Paths)
    {
        if (path->isCollapsed())
        {
            continue;
        }
        AABB aabb;
        AABB propertyBounds;
        if (!path->needsPathBuild())
        {
            aabb = path->rawPath().preciseBounds(path->transform());
        }
        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);
            aabb = pendingPath.preciseBounds(path->transform());
        }
        // 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. Clamps to the available space like
    // the parametric path below, so hug means the same thing in both models.
    if (isParticipatingInLayout())
    {
        AABB bounds = computeIntrinsicBounds();
        return Vec2D(std::min(widthMode == LayoutMeasureMode::undefined
                                  ? std::numeric_limits<float>::max()
                                  : width,
                              bounds.width()),
                     std::min(heightMode == LayoutMeasureMode::undefined
                                  ? std::numeric_limits<float>::max()
                                  : height,
                              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();
    }
}

void Shape::addChild(Component* component)
{
    Super::addChild(component);
    if (component->is<LayoutParticipant>())
    {
        m_hasLayoutParticipant = true;
    }
}

// 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
{
#ifndef WITH_RIVE_EDITOR
    // Children are fixed at runtime and few shapes have one to look for.
    if (!m_hasLayoutParticipant)
    {
        return nullptr;
    }
#endif
    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; }