#include "rive/component.hpp"
#ifdef WITH_RIVE_EDITOR
#include "rive/scripted/scripted_object.hpp"
#include "rive/focus_data.hpp"
#endif
#include "rive/artboard.hpp"
#include "rive/container_component.hpp"
#include "rive/core_context.hpp"
#include "rive/importers/artboard_importer.hpp"
#include "rive/importers/import_stack.hpp"
#include "rive/layout_component.hpp"
#include "rive/data_bind/data_bind.hpp"
#include <algorithm>

using namespace rive;

#ifdef WITH_RIVE_EDITOR
Component::OnParentIdChangedCallback Component::s_onParentIdChanged = nullptr;

void Component::parentIdChanged()
{
  if (s_onParentIdChanged != nullptr)
  {
    s_onParentIdChanged(this);
  }
}
#endif

bool Component::validate(CoreContext* context)
{
  auto coreObject = context->resolve(parentId());
  return coreObject != nullptr && coreObject->is<ContainerComponent>();
}

StatusCode Component::onAddedDirty(CoreContext* context)
{
#ifdef WITH_RIVE_EDITOR
  // editor_native's coop-apply passes an EditorFile as the
  // CoreContext — NOT an Artboard. The runtime's `static_cast` below
  // is invalid in that case (produces garbage). Mirror Dart's
  // `resolveArtboard()` in `packages/rive_core/lib/component.dart:175`:
  // walk up the parent chain by id to find the Artboard. Uses
  // `parentId()` (populated in Pass 2 of the coop-apply ordering)
  // rather than `parent()` pointers, so result is independent of
  // whether the parent's own `onAddedDirty` has run yet.
  if (this->is<Artboard>())
  {
    m_Artboard = this->as<Artboard>();
    return StatusCode::Ok;
  }
  auto* resolved = context->resolve(parentId());
  if (resolved == nullptr || !resolved->is<ContainerComponent>())
  {
    // Parent not in the file (typeKey unknown to this build,
    // or coop hasn't delivered it yet). Tell subclass
    // `onAddedDirty` to bail too — propagating MissingObject
    // means the subclass's `Super::onAddedDirty()` check at
    // the top of every override returns early without
    // calling typed setup like `initPaintMutator` /
    // `parent()->as<X>()->addY(this)`. This mirrors Dart's
    // `validate()` cull (rive_core/lib/component.dart:409 +
    // rive_file.dart:750-764): orphan Cores are simply not
    // wired into the live graph.
    return StatusCode::MissingObject;
  }
  auto* parentContainer = resolved->as<ContainerComponent>();
  setParentForEditor(parentContainer);
  for (Core* curr = resolved; curr != nullptr;)
  {
    if (curr->is<Artboard>())
    {
      m_Artboard = curr->as<Artboard>();
      break;
    }
    if (!curr->is<Component>())
    {
      break;
    }
    curr = context->resolve(curr->as<Component>()->parentId());
  }
  if (m_Artboard == nullptr)
  {
    // Parent chain broken before reaching the Artboard.
    // Same propagation as no-parent: subclass `onAddedDirty`
    // overrides bail on MissingObject from Super, so
    // typed setup like `initPaintMutator(this)` (which derefs
    // `artboard()->factory()`) never runs and never crashes.
    // Pass G in `EditorFile::finalizeBatch` re-resolves the
    // chain on every batch; if a subsequent coop batch fills
    // the missing ancestor, `m_Artboard` gets populated and
    // a re-validation pass (Slice 6 follow-up) can re-run
    // the typed setup.
    setParentForEditor(nullptr);
    return StatusCode::MissingObject;
  }
  parentContainer->addChild(this);
  return StatusCode::Ok;
#else
  m_Artboard = static_cast<Artboard*>(context);
  if (this == m_Artboard)
  {
    // We're the artboard, don't parent to ourselves.
    return StatusCode::Ok;
  }
  m_Parent = context->resolve(parentId())->as<ContainerComponent>();
  m_Parent->addChild(this);
  return StatusCode::Ok;
#endif
}

bool Component::addDirt(ComponentDirt value, bool recurse)
{
  if ((m_Dirt & value) == value)
  {
    // Already marked.
    return false;
  }

  // Make sure dirt is set before calling anything that can set more dirt.
  m_Dirt |= value;

  onDirty(m_Dirt);

  onComponentDirty(this);

  if (!recurse)
  {
    return true;
  }

  addDirtToDependents(value);
  return true;
}

StatusCode Component::import(ImportStack& importStack)
{
  if (is<Artboard>())
  {
    // Artboards are always their first object.
    assert(as<Artboard>()->objects().size() == 0);
    as<Artboard>()->addObject(this);
    return Super::import(importStack);
  }

  // File::readObjects already put this in the artboard's object list (see
  // claimsArtboardSlot); a component still needs an artboard to belong to.
  auto artboardImporter = importStack.latest<ArtboardImporter>(
      ArtboardBase::typeKey);
  if (artboardImporter == nullptr)
  {
    return StatusCode::MissingObject;
  }
  return Super::import(importStack);
}

bool Component::collapse(bool value)
{
  if (((m_Dirt & ComponentDirt::Collapsed) == ComponentDirt::Collapsed) ==
      value)
  {
    return false;
  }
  if (value)
  {
    m_Dirt |= ComponentDirt::Collapsed;
  }
  else
  {
    m_Dirt &= ~ComponentDirt::Collapsed;
  }
  onDirty(m_Dirt);
  onComponentDirty(this);
  if (m_Artboard != nullptr)
  {
    m_Artboard->collapseChanged();
  }
  updateCollapsables();
  return true;
}

#ifdef WITH_RIVE_EDITOR
void Component::clearDirtForEditor()
{
  bool wasCollapsed = (m_Dirt & ComponentDirt::Collapsed) ==
                      ComponentDirt::Collapsed;
  m_Dirt = ComponentDirt::None;
  if (wasCollapsed && m_Artboard != nullptr)
  {
    m_Artboard->collapseChanged();
  }
}
#endif

bool Component::hitTestPoint(
    const Vec2D& position,
    bool skipOnUnclipped,
    bool isPrimaryHit)
{
  if (parent())
  {
    return parent()->hitTestPoint(position, skipOnUnclipped, false);
  }
  return true;
}

void Component::addCollapsable(DataBind* collapsable)
{
  // pushUnique gives set semantics; the collapse side-effect should only
  // fire on first add, so detect that via size delta.
  auto sizeBefore = m_collapsables.size();
  m_collapsables.pushUnique(collapsable);
  if (m_collapsables.size() != sizeBefore)
  {
    collapsable->collapse(isCollapsed());
  }
}

void Component::updateCollapsables()
{
  auto collapsed = isCollapsed();
  for (auto* collapsable : m_collapsables)
  {
    collapsable->collapse(collapsed);
  }
}
#ifdef WITH_RIVE_EDITOR
void Component::editorPrepareForDestruction()
{
  if (auto* scripted = ScriptedObject::from(this))
  {
    scripted->scriptDispose();
    scripted->dataContext(nullptr);
  }
  if (is<FocusData>())
    as<FocusData>()->detachFocusable();
}

#endif
