#include "rive/scripted/scripted_transition.hpp"
#include "rive/nested_artboard.hpp"
#include "rive/artboard.hpp"
#include "rive/file.hpp"
#include "rive/component.hpp"
#include "rive/component_dirt.hpp"
#include "rive/drawable_flag.hpp"
#include "rive/enums.hpp"
#include "rive/animation/state_machine_instance.hpp"
#include "rive/viewmodel/viewmodel_instance.hpp"
#include "rive/viewmodel/viewmodel_instance_list_item.hpp"
#ifdef WITH_RIVE_LAYOUT
#include "rive/layout_component.hpp"
#endif

using namespace rive;

// v1: only NestedArtboard children participate in the design-time solo set.
static bool isTransitionChild(Component* child)
{
  return child->is<NestedArtboard>();
}

// Toggle the loop-exclusion (Hidden drawable flag) on a design child. Hidden
// removes the child from the artboard draw walk (Drawable::isHidden()) without
// collapsing it, so NestedArtboard::advanceComponent keeps advancing its
// content while the container composites it in draw().
static void setChildHidden(Drawable* drawable, bool hidden)
{
  uint32_t flags = drawable->drawableFlags();
  if (hidden)
  {
    flags |= static_cast<uint32_t>(DrawableFlag::Hidden);
  }
  else
  {
    flags &= ~static_cast<uint32_t>(DrawableFlag::Hidden);
  }
  drawable->drawableFlags(flags);
}

ScriptedTransition::~ScriptedTransition() { clearListInstances(); }

// ---------------------------------------------------------------------------
// Design-time solo set
// ---------------------------------------------------------------------------

int ScriptedTransition::designChildCount()
{
  int count = 0;
  for (Component* child : children())
  {
    if (isTransitionChild(child))
    {
      count++;
    }
  }
  return count;
}

NestedArtboard* ScriptedTransition::designChildAt(int index)
{
  int i = 0;
  for (Component* child : children())
  {
    if (!isTransitionChild(child))
    {
      continue;
    }
    if (i == index)
    {
      return child->as<NestedArtboard>();
    }
    i++;
  }
  return nullptr;
}

int ScriptedTransition::sourceIndex(const TransitionSource& source)
{
  if (source.instance != nullptr)
  {
    for (size_t i = 0; i < m_listInstancesByIndex.size(); i++)
    {
      if (m_listInstancesByIndex[i] == source.instance)
      {
        return designChildCount() + (int)i;
      }
    }
    return -1;
  }
  if (source.design != nullptr)
  {
    int i = 0;
    for (Component* child : children())
    {
      if (!isTransitionChild(child))
      {
        continue;
      }
      if (child == source.design)
      {
        return i;
      }
      i++;
    }
  }
  return -1;
}

Component* ScriptedTransition::activeComponent()
{
  auto* ab = artboard();
  Core* active = ab != nullptr ? ab->resolve(activeComponentId()) : nullptr;
  for (Component* child : children())
  {
    if (child == active && isTransitionChild(child))
    {
      return child;
    }
  }
  return nullptr;
}

bool ScriptedTransition::scriptReady() const
{
#ifdef WITH_RIVE_SCRIPTING
  return m_vm != nullptr && m_self != 0;
#else
  return false;
#endif
}

bool ScriptedTransition::scriptManagesTo() const
{
#ifdef WITH_RIVE_SCRIPTING
  if (m_vm == nullptr || !m_vm->valid() || m_self == 0)
  {
    return true;
  }
  return m_vm->transitionManagesTo(m_self);
#else
  return true;
#endif
}

void ScriptedTransition::propagateCollapse(bool collapse)
{
  Core* active = collapse || artboard() == nullptr
                     ? nullptr
                     : artboard()->resolve(activeComponentId());
  for (Component* child : children())
  {
    if (!isTransitionChild(child))
    {
      child->collapse(collapse);
      continue;
    }
    if (!collapse && m_transitioning &&
        (child == m_from.design || child == m_to.design))
    {
      // Both transitioning design children stay live; drawn by draw().
      child->collapse(false);
    }
    else
    {
      child->collapse(child != active);
    }
  }
}

bool ScriptedTransition::collapse(bool value)
{
  if (!Component::collapse(value))
  {
    return false;
  }
  propagateCollapse(value);
  return true;
}

// ---------------------------------------------------------------------------
// List instancing (lazy) — modeled on ArtboardComponentList
// ---------------------------------------------------------------------------

Artboard* ScriptedTransition::findListArtboard(
    const rcp<ViewModelInstanceListItem>& item)
{
  if (m_file == nullptr || item == nullptr)
  {
    return nullptr;
  }
  auto vmi = item->viewModelInstance();
  if (vmi == nullptr)
  {
    return nullptr;
  }
  uint32_t viewModelId = vmi->viewModelId();
  auto cached = m_artboardsMap.find(viewModelId);
  if (cached != m_artboardsMap.end())
  {
    return cached->second;
  }
  for (auto ab : m_file->artboards())
  {
    if (ab->viewModelId() == viewModelId)
    {
      m_artboardsMap[viewModelId] = ab;
      return ab;
    }
  }
  return nullptr;
}

ArtboardInstance* ScriptedTransition::ensureListInstance(int index)
{
  if (index < 0 || index >= (int)m_listItems.size())
  {
    return nullptr;
  }
  if (index < (int)m_listInstancesByIndex.size() &&
      m_listInstancesByIndex[index] != nullptr)
  {
    return m_listInstancesByIndex[index];
  }
  auto& item = m_listItems[index];
  auto existing = m_listInstances.find(item);
  if (existing != m_listInstances.end())
  {
    return existing->second.get();
  }
  Artboard* source = findListArtboard(item);
  if (source == nullptr)
  {
    return nullptr;
  }
  std::unique_ptr<ArtboardInstance> inst = source->instance();
  ArtboardInstance* raw = inst.get();
  if (raw == nullptr)
  {
    return nullptr;
  }
  if (artboard() != nullptr)
  {
    raw->bindViewModelInstance(
        item->viewModelInstance(),
        artboard()->dataContext());
    raw->updateDataBinds();
  }
  raw->frameOrigin(false);
  // Default state machine so the instanced artboard animates.
  int smIndex = raw->defaultStateMachineIndex();
  std::unique_ptr<StateMachineInstance> sm = raw->stateMachineAt(
      smIndex >= 0 ? (size_t)smIndex : 0u);
  if (sm != nullptr)
  {
    sm->dataContext(raw->dataContext());
    sm->updateDataBinds(false);
    m_listStateMachines[raw] = std::move(sm);
  }
  m_listInstances[item] = std::move(inst);
  if ((int)m_listInstancesByIndex.size() <= index)
  {
    m_listInstancesByIndex.resize(m_listItems.size(), nullptr);
  }
  m_listInstancesByIndex[index] = raw;
  return raw;
}

void ScriptedTransition::forgetInstance(ArtboardInstance* instance)
{
  if (instance == nullptr)
  {
    return;
  }
  if (m_transitioning &&
      (m_from.instance == instance || m_to.instance == instance))
  {
    // The transition can't run against a source that's about to be freed:
    // settle it now, which also un-hides any design child it had hidden.
    completeTransition();
  }
  if (m_current.instance == instance)
  {
    // completeTransition() may have just seated it as current.
    m_current = TransitionSource();
  }
}

void ScriptedTransition::disposeListItem(
    const rcp<ViewModelInstanceListItem>& item)
{
  auto instIt = m_listInstances.find(item);
  if (instIt != m_listInstances.end())
  {
    forgetInstance(instIt->second.get());
    // State machine before artboard (avoids use-after-free in teardown).
    m_listStateMachines.erase(instIt->second.get());
    m_listInstances.erase(instIt);
  }
}

void ScriptedTransition::clearListInstances()
{
  if (m_transitioning &&
      (m_from.instance != nullptr || m_to.instance != nullptr))
  {
    completeTransition();
  }
  if (m_current.instance != nullptr)
  {
    m_current = TransitionSource();
  }
  m_listStateMachines.clear(); // state machines before artboards
  m_listInstances.clear();
  m_listInstancesByIndex.clear();
  m_listItems.clear();
  m_artboardsMap.clear();
  m_activeListIndex = -1;
}

static bool listsAreEqual(
    const std::vector<rcp<ViewModelInstanceListItem>>& current,
    std::vector<rcp<ViewModelInstanceListItem>>* incoming)
{
  if (incoming == nullptr)
  {
    return current.empty();
  }
  if (current.size() != incoming->size())
  {
    return false;
  }
  for (size_t i = 0; i < current.size(); i++)
  {
    if (current[i] != (*incoming)[i])
    {
      return false;
    }
  }
  return true;
}

void ScriptedTransition::updateList(
    std::vector<rcp<ViewModelInstanceListItem>>* list)
{
  if (listsAreEqual(m_listItems, list))
  {
    return;
  }
  std::vector<rcp<ViewModelInstanceListItem>> old = m_listItems;
  if (list != nullptr)
  {
    m_listItems = *list;
  }
  else
  {
    m_listItems.clear();
  }
  // Dispose cached instances for items no longer present.
  for (auto& item : old)
  {
    bool present = false;
    for (auto& current : m_listItems)
    {
      if (current == item)
      {
        present = true;
        break;
      }
    }
    if (!present)
    {
      disposeListItem(item);
    }
  }
  // Assign each item its `index` symbol (if any) + rebuild the lazy index
  // cache, keeping instances that survived.
  m_listInstancesByIndex.assign(m_listItems.size(), nullptr);
  for (size_t i = 0; i < m_listItems.size(); i++)
  {
    m_listItems[i]->assignListIndex((uint32_t)i);
    auto it = m_listInstances.find(m_listItems[i]);
    if (it != m_listInstances.end())
    {
      m_listInstancesByIndex[i] = it->second.get();
    }
  }
  addDirt(ComponentDirt::Components);
  applySelection(); // clamps m_activeListIndex and (re)selects
  wakeAdvance();
}

void ScriptedTransition::listSourceChanged()
{
  // Unbound: clear the instanced children.
  if (listSource() == (uint32_t)-1)
  {
    std::vector<rcp<ViewModelInstanceListItem>> empty;
    updateList(&empty);
  }
}

// ---------------------------------------------------------------------------
// Unified selection over the combined solo set
// ---------------------------------------------------------------------------

ScriptedTransition::TransitionSource ScriptedTransition::intendedSource()
{
  TransitionSource source;
  if (m_activeListIndex >= 0 && m_activeListIndex < (int)m_listItems.size())
  {
    source.instance = ensureListInstance(m_activeListIndex);
    if (source.instance != nullptr)
    {
      return source;
    }
  }
  Component* design = activeComponent();
  if (design != nullptr && design->is<NestedArtboard>())
  {
    source.design = design->as<NestedArtboard>();
  }
  return source;
}

void ScriptedTransition::applySelection()
{
  selectActiveSource(intendedSource());
}

void ScriptedTransition::selectActiveSource(const TransitionSource& next)
{
  if (next == m_current)
  {
    return;
  }
  TransitionSource prev = m_current;
  m_current = next;
  if (scriptReady() && !prev.empty() && !next.empty())
  {
    startTransition(prev, next);
    return;
  }
  // Instant: clear any in-flight transition and settle collapse.
  if (m_transitioning)
  {
    if (m_from.design != nullptr)
    {
      setChildHidden(m_from.design, false);
    }
    if (m_to.design != nullptr)
    {
      setChildHidden(m_to.design, false);
    }
    m_transitioning = false;
    m_from = TransitionSource();
    m_to = TransitionSource();
    m_manageTo = true;
  }
  propagateCollapse(isCollapsed());
  addScriptedDirt(ComponentDirt::Paint);
}

void ScriptedTransition::startTransition(
    const TransitionSource& from,
    const TransitionSource& to)
{
  TransitionSource previousFrom = m_transitioning ? m_from : TransitionSource();

  m_from = from;
  m_to = to;
  m_transitioning = true;

  // Interruption: retire a previously-outgoing design child not in the new
  // pair (list instances need no un-hide — they are never in the draw loop).
  if (!previousFrom.empty() && previousFrom != m_from && previousFrom != m_to &&
      previousFrom.design != nullptr)
  {
    setChildHidden(previousFrom.design, false);
    previousFrom.design->collapse(true);
  }

  // Keep design sources live; list instances are host-drawn regardless.
  if (m_from.design != nullptr)
  {
    m_from.design->collapse(false);
  }
  if (m_to.design != nullptr)
  {
    m_to.design->collapse(false);
  }
  propagateCollapse(isCollapsed());

  callChanged(m_from, m_to);

  // A list `to` has no draw-loop entry to fall back to, so it must always be
  // script-composited; a design `to` may opt out via `managesTo`.
  m_manageTo = m_to.instance != nullptr ? true : scriptManagesTo();
  if (m_from.design != nullptr)
  {
    setChildHidden(m_from.design, true);
  }
  if (m_to.design != nullptr)
  {
    setChildHidden(m_to.design, m_manageTo);
  }

  wakeAdvance();
  addScriptedDirt(ComponentDirt::Components);
}

void ScriptedTransition::completeTransition()
{
  if (!m_transitioning)
  {
    return;
  }
  TransitionSource from = m_from;
  TransitionSource to = m_to;
  m_transitioning = false;
  m_from = TransitionSource();
  m_to = TransitionSource();
  m_manageTo = true;
  if (from.design != nullptr)
  {
    setChildHidden(from.design, false);
  }
  if (to.design != nullptr)
  {
    setChildHidden(to.design, false);
  }
  m_current = to;
  propagateCollapse(isCollapsed());
  addScriptedDirt(ComponentDirt::Paint);
}

void ScriptedTransition::activeComponentIdChanged()
{
  // A genuine design child was chosen -> leave list mode.
  if (activeComponent() != nullptr)
  {
    m_activeListIndex = -1;
  }
  applySelection();
#ifdef WITH_RIVE_LAYOUT
  recollectOwningLayout();
#endif
}

StatusCode ScriptedTransition::onAddedClean(CoreContext* context)
{
  StatusCode code = Super::onAddedClean(context);
  if (code != StatusCode::Ok)
  {
    return code;
  }
  m_current = intendedSource();
  propagateCollapse(isCollapsed());
#ifdef WITH_RIVE_LAYOUT
  recollectOwningLayout();
#endif
  return StatusCode::Ok;
}

// ---------------------------------------------------------------------------
// Advance / draw / update
// ---------------------------------------------------------------------------

void ScriptedTransition::advanceLiveInstance(
    const TransitionSource& source,
    float elapsedSeconds,
    AdvanceFlags flags,
    bool& keepGoing)
{
  if (source.instance == nullptr)
  {
    return;
  }
  auto smIt = m_listStateMachines.find(source.instance);
  StateMachineInstance* sm = smIt != m_listStateMachines.end()
                                 ? smIt->second.get()
                                 : nullptr;
  if (sm != nullptr && enums::is_flag_set(flags, AdvanceFlags::AdvanceNested))
  {
    if (sm->advanceAndApply(elapsedSeconds, false))
    {
      keepGoing = true;
    }
  }
  else if (source.instance->advanceInternal(elapsedSeconds, flags))
  {
    keepGoing = true;
  }
}

bool ScriptedTransition::advanceComponent(
    float elapsedSeconds,
    AdvanceFlags flags)
{
  bool keepGoing = false;

  if (m_transitioning)
  {
    // In design mode (no nested/real time), settle immediately rather than
    // freezing mid-blend.
    if (!enums::is_flag_set(flags, AdvanceFlags::AdvanceNested))
    {
      completeTransition();
    }
    else if (elapsedSeconds == 0)
    {
      // Waiting for real elapsed time; keep requesting frames.
      keepGoing = true;
    }
    else
    {
      bool scriptGoing = scriptAdvance(elapsedSeconds);
      addScriptedDirt(ComponentDirt::Paint);
      if (!scriptGoing)
      {
        completeTransition();
      }
      else
      {
        keepGoing = true;
      }
    }
  }

  // Advance the live list instance(s). Design sources advance via the
  // artboard's own advancing-component loop, so only list instances here.
  if (m_transitioning)
  {
    advanceLiveInstance(m_from, elapsedSeconds, flags, keepGoing);
    advanceLiveInstance(m_to, elapsedSeconds, flags, keepGoing);
  }
  else
  {
    advanceLiveInstance(m_current, elapsedSeconds, flags, keepGoing);
  }
  return keepGoing;
}

void ScriptedTransition::draw(Renderer* renderer)
{
#ifdef WITH_RIVE_SCRIPTING
  if (m_transitioning && m_vm != nullptr && m_vm->valid() && draws())
  {
    ScriptBackend::TransitionChildRef from = childRef(m_from);
    ScriptBackend::TransitionChildRef to = childRef(m_to);
    // When the script opts out of managing the to child (design only) it
    // renders through the normal loop, so hand the script nil instead.
    if (!m_manageTo)
    {
      to.artboard = nullptr;
    }

    renderer->save();
    m_vm->callTransitionDraw(this, m_self, renderer, from, to);
    renderer->restore();
    return;
  }
#endif
  // Idle: an active LIST instance has no draw-loop entry, so draw it here
  // (design children draw through the normal loop, gated by collapse).
  if (m_current.instance != nullptr)
  {
    renderer->save();
    renderer->transform(worldTransform());
    artboard()->drawHosted(m_current.instance, renderer);
    renderer->restore();
  }
}

bool ScriptedTransition::willDraw()
{
  return Super::willDraw() &&
         (m_transitioning || m_current.instance != nullptr);
}

void ScriptedTransition::update(ComponentDirt value)
{
  Super::update(value);

  auto forward = [this, value](const TransitionSource& source) {
    ArtboardInstance* inst = source.instance;
    if (inst == nullptr)
    {
      return;
    }
    if ((value & ComponentDirt::RenderOpacity) == ComponentDirt::RenderOpacity)
    {
      inst->opacity(renderOpacity());
    }
    if ((value & ComponentDirt::Components) == ComponentDirt::Components)
    {
      inst->updatePass(false);
    }
  };
  if (m_transitioning)
  {
    forward(m_from);
    forward(m_to);
  }
  else
  {
    forward(m_current);
  }
}

void ScriptedTransition::callChanged(
    const TransitionSource& from,
    const TransitionSource& to)
{
#ifdef WITH_RIVE_SCRIPTING
  if (m_vm == nullptr || !m_vm->valid())
  {
    return;
  }
  // 1 when the incoming child is at a higher combined index than the
  // outgoing one, -1 when lower, 0 when unknown (e.g. first show).
  int fromIndex = sourceIndex(from);
  int toIndex = sourceIndex(to);
  int direction = (fromIndex >= 0 && toIndex >= 0)
                      ? (toIndex > fromIndex ? 1
                                             : (toIndex < fromIndex ? -1 : 0))
                      : 0;
  m_vm->callTransitionChanged(
      this,
      m_self,
      childRef(from),
      childRef(to),
      direction);
#endif
}

#ifdef WITH_RIVE_SCRIPTING
ScriptBackend::TransitionChildRef ScriptedTransition::childRef(
    const TransitionSource& source) const
{
  ScriptBackend::TransitionChildRef ref;
  if (source.design != nullptr)
  {
    ref.artboard = static_cast<Artboard*>(source.design->sourceArtboard());
    ref.transform = source.design->worldTransform();
  }
  else
  {
    ref.artboard = static_cast<Artboard*>(source.instance);
    ref.transform = worldTransform();
  }
  return ref;
}
#endif

Core* ScriptedTransition::clone() const
{
  ScriptedTransition* twin = ScriptedTransitionBase::clone()
                                 ->as<ScriptedTransition>();
  if (m_fileAsset != nullptr)
  {
    twin->setAsset(m_fileAsset);
  }
  twin->file(m_file);
  return twin;
}

#ifdef WITH_RIVE_LAYOUT
void ScriptedTransition::recollectOwningLayout()
{
  for (Component* p = parent(); p != nullptr; p = p->parent())
  {
    if (p->is<LayoutComponent>())
    {
      p->as<LayoutComponent>()->syncLayoutChildren();
      return;
    }
  }
}
#endif

// ---------------------------------------------------------------------------
// Combined-index selectors (design children then list instances)
// ---------------------------------------------------------------------------

void ScriptedTransition::updateByIndex(size_t index)
{
  int designCount = designChildCount();
  // The data-binding path casts rounded floats to size_t without clamping,
  // so a negative binding arrives as a huge index. Reject it before the
  // narrowing below turns it back into a negative int, which would pass the
  // design-child test and clear an active list selection (mirrors
  // Solo::updateByIndex).
  if (index >= (size_t)designCount + m_listItems.size())
  {
    return;
  }
  if ((int)index < designCount)
  {
    m_activeListIndex = -1;
    NestedArtboard* child = designChildAt((int)index);
    if (child != nullptr && artboard() != nullptr)
    {
      activeComponentId(artboard()->idOf(child));
    }
    applySelection();
    return;
  }
  size_t listIndex = index - (size_t)designCount;
  if (listIndex >= m_listItems.size())
  {
    return;
  }
  m_activeListIndex = (int)listIndex;
  // Neutralize the design selection (0 == runtime "missing"); resolves to no
  // child, so activeComponentIdChanged leaves m_activeListIndex intact.
  if (activeComponentId() != 0)
  {
    activeComponentId(0);
  }
  applySelection();
}

void ScriptedTransition::updateByName(const std::string& name)
{
  // v1: name selection covers design children only (list items have no
  // stable names).
  if (!artboard())
  {
    return;
  }
  for (auto& child : children())
  {
    if (!isTransitionChild(child))
    {
      continue;
    }
    if (child->name() == name)
    {
      m_activeListIndex = -1;
      activeComponentId(artboard()->idOf(child));
      break;
    }
  }
}

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

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