#include "rive/shapes/clipping_shape.hpp"
#include "rive/artboard.hpp"
#include "rive/core_context.hpp"
#include "rive/factory.hpp"
#include "rive/node.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/paint/fill.hpp"
#include "rive/shapes/path_composer.hpp"
#include "rive/shapes/shape.hpp"

using namespace rive;

void ClippingShapeStart::draw(Renderer* renderer, bool needsSaveOperation)
{
  if (!m_clippingShape->isVisible())
  {
    return;
  }
  if (needsSaveOperation)
  {

    renderer->save();
  }
  if (m_clippingShape)
  {
    ShapePaintPath* path = m_clippingShape->path();
    if (!path)
    {
      return;
    }
    RenderPath* renderPath = path->renderPath(m_clippingShape);
    renderer->clipPath(renderPath);
  }
}

int ClippingShapeStart::emptyClipCount()
{
  if (m_clippingShape && m_clippingShape->isVisible())
  {
    ShapePaintPath* path = m_clippingShape->path();
    if (!path)
    {
      return 1;
    }
  }
  return 0;
}

bool ClippingShapeStart::isVisible()
{
  if (m_clippingShape)
  {
    return m_clippingShape->isVisible();
  }
  return false;
}

int ClippingShapeEnd::emptyClipCount()
{
  if (m_clippingShape && m_clippingShape->isVisible())
  {
    ShapePaintPath* path = m_clippingShape->path();
    if (!path)
    {
      return -1;
    }
  }
  return 0;
}

void ClippingShapeEnd::draw(Renderer* renderer, bool needsSaveOperation)
{
  if (!m_clippingShape->isVisible() || !needsSaveOperation)
  {
    return;
  }
  renderer->restore();
}

ClippingShape::~ClippingShape()
{
  for (auto& proxy : m_proxyDrawables)
  {
    delete proxy;
  }
  for (auto& proxy : m_pooledProxyDrawables)
  {
    delete proxy;
  }
}

StatusCode ClippingShape::onAddedClean(CoreContext* context)
{
  // Find drawables parented (directly or transitively) to this clipping
  // shape's parent; they need to know they'll be clipped by this shape.
  parent()->forAll([this](Component* component) -> bool {
    if (component->is<Drawable>())
    {
      component->as<Drawable>()->addClippingShape(this);
    }
    return true;
  });

  // Find shapes parented (directly or transitively) to the source node;
  // their paths will need to be RenderPaths in order to be used for
  // clipping operations.
  if (m_Source)
  {
    m_Source->forAll([this](Component* component) -> bool {
      if (component->is<Shape>())
      {
        auto shape = component->as<Shape>();
        shape->addFlags(PathFlags::world | PathFlags::clipping);
        m_Shapes.push_back(shape);
      }
      return true;
    });
  }

  return StatusCode::Ok;
}

StatusCode ClippingShape::onAddedDirty(CoreContext* context)
{
  StatusCode code = Super::onAddedDirty(context);
  if (code != StatusCode::Ok)
  {
    return code;
  }
  auto coreObject = context->resolve(sourceId());
  if (coreObject == nullptr || !coreObject->is<Node>())
  {
    return StatusCode::MissingObject;
  }

#ifdef WITH_RIVE_EDITOR
  setSourceForEditor(static_cast<Node*>(coreObject));
#else
  m_Source = static_cast<Node*>(coreObject);
#endif

  return StatusCode::Ok;
}

void ClippingShape::buildDependencies()
{
#ifdef WITH_RIVE_EDITOR
  // Dart parity: every dep-rebuild clears + re-walks the source
  // subtree. Runtime builds rely on `onAddedClean`'s one-shot init;
  // editor needs to re-walk because `source` can change mid-edit
  // (sourceIdChanged → setSourceForEditor → next Pass B re-runs us).
  // `editorClearDependents` in Pass B-prep wipes stale dependent
  // entries on every Component, so re-adding the pathComposer edges
  // below is safe and required even when m_Shapes contents didn't
  // change.
  m_Shapes.clear();
  if (auto* src = source())
  {
    src->forAll([this](Component* c) -> bool {
      if (c->is<Shape>())
      {
        auto* shape = c->as<Shape>();
        shape->addFlags(PathFlags::world | PathFlags::clipping);
        m_Shapes.push_back(shape);
      }
      return true;
    });
  }
#endif
  for (auto shape : m_Shapes)
  {
    shape->pathComposer()->addDependent(this);
    // We read what a fill resolves in its own update, so we sort after it.
    for (auto paint : shape->shapePaints())
    {
      if (paint->is<Fill>() && paint->hasEffects())
      {
        paint->addDependent(this);
      }
    }
  }
  clipStart.clippingShape(this);
  clipEnd.clippingShape(this);
#ifdef WITH_RIVE_EDITOR
  // Dart parity (clipping_shape.dart:97): force the clip path to
  // rebuild next update cycle. Without this, anything that triggers
  // a Pass B re-run without an accompanying property dirt (e.g. a
  // downstream Fill/Stroke removal that only touches m_ShapePaints)
  // leaves the cached m_path stale or empty — drawables clipped by
  // this ClippingShape render incorrectly until something else
  // dirties the source (moving the source shape rebuilds it).
  addDirt(ComponentDirt::Path);
  // Dirty each source shape's PathComposer directly so its next
  // update rebuilds m_worldPath (consumed by our own update reading
  // `shape->pathComposer()->worldPath()`).
  //
  // We target the PathComposer specifically rather than cascading
  // from the Shape via `addDirt(Path, recurse=true)`. The cascade
  // would traverse the Shape's m_Dependents → PathComposer →
  // PathComposer's m_Dependents — and PathComposer isn't an arena
  // Component, so Pass B-prep's m_Dependents wipe sweep doesn't
  // reach it. Stale ClippingShape* entries from previous batches
  // (where a clip was created then freed via undo/redo) accumulate
  // in pathComposer->m_Dependents and the cascade dereferences
  // them, crashing in the recurse step.
  //
  // The direct addDirt(Path) on pathComposer sets its dirt bit +
  // schedules onComponentDirty via the dependency root, without
  // walking the contaminated dependents list. PathComposer.update
  // then rebuilds m_worldPath in the topological walk, before
  // ClippingShape.update reads it.
  for (auto shape : m_Shapes)
  {
    shape->pathComposer()->addDirt(ComponentDirt::Path);
  }
#endif
}

// Strokes are skipped: their effect output is a centerline, meaningless filled.
bool ClippingShape::addFillPaths(Shape* shape)
{
  bool addedEffected = false;
  bool needsRawPath = false;
  for (auto paint : shape->shapePaints())
  {
    if (!paint->is<Fill>())
    {
      continue;
    }
    auto effected = paint->hasEffects() ? paint->lastEffectPath(paint)
                                        : nullptr;
    if (effected == nullptr)
    {
      // No effect: this fill draws the whole shape.
      needsRawPath = true;
      continue;
    }
    if (!effected->empty())
    {
      const Mat2D& world = shape->worldTransform();
      m_path.addPath(effected, effected->isLocal() ? &world : nullptr);
    }
    addedEffected = true;
  }

  if (addedEffected && !needsRawPath)
  {
    return true;
  }
  auto path = shape->pathComposer()->worldPath();
  if (path == nullptr)
  {
    return addedEffected;
  }
  m_path.addPath(path);
  return true;
}

void ClippingShape::update(ComponentDirt value)
{
  if (hasDirt(
          value,
          ComponentDirt::Path | ComponentDirt::WorldTransform |
              ComponentDirt::NSlicer))
  {
    m_path.rewind(false, (FillRule)fillRule());
    m_clipPath = nullptr;
    for (auto shape : m_Shapes)
    {
      if (!shape->isEmpty() && addFillPaths(shape))
      {
        m_clipPath = &m_path;
      }
    }
  }
}

void ClippingShape::isVisibleChanged()
{
  artboard()->addDirt(ComponentDirt::Clipping);
}