#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).
  // Runtime imports build this graph once, in file order. Clearing here
  // can erase a clip's edge when its source shape follows it in the file.
  if (editorArena() != nullptr)
  {
    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; }