#include "rive/solo.hpp"
#include "rive/constraints/constraint.hpp"
#include "rive/shapes/clipping_shape.hpp"
#include "rive/layer_mask.hpp"
#include "rive/focus_data.hpp"
#include "rive/semantic/semantic_data.hpp"
#include "rive/artboard.hpp"
#include "rive/node.hpp"
#include "rive/container_component.hpp"
#include "rive/transform_component.hpp"
#include "rive/layout_component.hpp"
#include "rive/layout/layout_node_provider.hpp"

using namespace rive;

// Some child components shouldn't be considered as part of the solo set as they
// are more akin to properties/metadata of the solo itself (constraints,
// clipping shapes, layer masks, focus and semantic data) rather than selectable
// solo options. These are excluded both from collapse propagation and from
// index/name based selection so that data binding targets only the real solo
// options.
static bool isSoloSetMember(Component* child)
{
  return !(
      child->is<Constraint>() || child->is<ClippingShape>() ||
      child->is<LayerMask>() || child->is<FocusData>() ||
      child->is<SemanticData>());
}

Component* Solo::activeComponent()
{
  auto* ab = artboard();
  Core* active = ab != nullptr ? ab->resolve(activeComponentId()) : nullptr;
  // The active id refers to one of our children; match by pointer so we get
  // it typed as a Component.
  for (Component* child : children())
  {
    if (child == active)
    {
      return child;
    }
  }
  return nullptr;
}

#ifdef WITH_RIVE_LAYOUT
bool Solo::optionsReachLayout()
{
  // Asked on every switch rather than cached, so Solo doesn't grow and an
  // edited hierarchy is always seen. It walks only this Solo's options, where
  // a re-collection walks the owning layout's whole tree.
  for (Component* child : children())
  {
    if (reachesLayoutProvider(child))
    {
      return true;
    }
  }
  return false;
}

void Solo::recollectOwningLayout()
{
  // We are not a LayoutComponent, so walk up for the layout that owns the
  // slot our active child occupies.
  for (Component* p = parent(); p != nullptr; p = p->parent())
  {
    if (p->is<LayoutComponent>())
    {
      p->as<LayoutComponent>()->syncLayoutChildren();
      return;
    }
  }
}
#endif

void Solo::propagateCollapse(bool collapse)
{
  Core* active = collapse ? nullptr : artboard()->resolve(activeComponentId());
  for (Component* child : children())
  {
    // For components that aren't part of the solo set, simply pass on the
    // collapse value of the solo itself.
    if (!isSoloSetMember(child))
    {
      child->collapse(collapse);
      continue;
    }

    // This child is part of the solo set so only make it active if it's the
    // currently marked solo object.
    child->collapse(child != active);
  }
}

bool Solo::collapse(bool value)
{
  // Intentionally using Component instead of Super as we don't want to call
  // collapse on the Container logic which just propagates blindly to
  // children.
  if (!Component::collapse(value))
  {
    return false;
  }
  propagateCollapse(value);
  return true;
}

void Solo::activeComponentIdChanged()
{
  propagateCollapse(isCollapsed());
#ifdef WITH_RIVE_LAYOUT
  // Only the active child is exposed to layout, so a swap changes the owning
  // layout's child set -- unless no option leads to a provider, when that set
  // is the same before and after.
  if (optionsReachLayout())
  {
    recollectOwningLayout();
  }
#endif
}

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

#ifdef WITH_RIVE_EDITOR
  // Coop-apply runs Pass 4 onAddedClean before a renderer is attached;
  // `propagateCollapse` fires `onDirty` on every child, which in
  // subclasses like Image/Mesh allocates render buffers via the
  // factory — so skip during hydration (post-validation edits re-fire
  // it via activeComponentIdChanged). Runtime .riv imports are marked
  // validated at read time and need it now or inactive Solo children
  // render un-collapsed.
  if (hasValidated())
#endif
  {
    propagateCollapse(isCollapsed());
#ifdef WITH_RIVE_LAYOUT
    // Parent chain + active child are resolved now; make sure the owning
    // layout has collected the active child, when any option is something it
    // would collect.
    if (optionsReachLayout())
    {
      recollectOwningLayout();
    }
#endif
  }
  return StatusCode::Ok;
}

void Solo::updateByIndex(size_t index)
{
  // The number of solo options is always <= children().size(), so any index
  // that big can never match. Bail early to avoid an O(n) walk every frame
  // for out-of-range indices (the data-binding path casts rounded floats to
  // size_t without clamping, so negative values arrive as huge indices).
  if (!artboard() || index >= children().size())
  {
    return;
  }
  // The index refers to the Nth solo option, skipping property-like children
  // (constraints, clipping shapes, focus/semantic data) so it matches the
  // ordering exposed by getActiveChildIndex.
  size_t soloIndex = 0;
  for (auto& child : children())
  {
    if (!isSoloSetMember(child))
    {
      continue;
    }
    if (soloIndex == index)
    {
      activeComponentId(artboard()->idOf(child));
      return;
    }
    soloIndex++;
  }
}

void Solo::updateByName(const std::string& name)
{
  if (!artboard())
  {
    return;
  }
  for (auto& child : children())
  {
    if (!isSoloSetMember(child))
    {
      continue;
    }
    if (child->name() == name)
    {

      int globalIndex = artboard()->idOf(child);
      activeComponentId(globalIndex);
      break;
    }
  }
}

int Solo::getActiveChildIndex()
{
  if (!artboard())
  {
    return -1;
  }
  Core* active = artboard()->resolve(activeComponentId());
  if (active)
  {
    int index = 0;
    for (auto& child : children())
    {
      if (!isSoloSetMember(child))
      {
        continue;
      }
      if (child == active)
      {
        return index;
      }
      index++;
    }
  }
  return -1;
}

std::string Solo::getActiveChildName()
{
  if (!artboard())
  {
    return "";
  }
  Core* active = artboard()->resolve(activeComponentId());
  if (active && active->is<Component>())
  {
    return active->as<Component>()->name();
  }
  return "";
}
