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

    // 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()
{
    // 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();
}

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; }