#include "rive/data_bind/data_bind.hpp"
#include "rive/artboard.hpp"
#include "rive/layout_component.hpp"
#include "rive/data_bind_flags.hpp"
#include "rive/generated/core_registry.hpp"
#include "rive/data_bind/bindable_property_artboard.hpp"
#include "rive/data_bind/bindable_property_asset.hpp"
#include "rive/data_bind/bindable_property_number.hpp"
#include "rive/data_bind/bindable_property_string.hpp"
#include "rive/data_bind/bindable_property_color.hpp"
#include "rive/data_bind/bindable_property_enum.hpp"
#include "rive/data_bind/bindable_property_list.hpp"
#include "rive/data_bind/bindable_property_boolean.hpp"
#include "rive/data_bind/bindable_property_trigger.hpp"
#include "rive/data_bind/bindable_property_integer.hpp"
#include "rive/data_bind/bindable_property_viewmodel.hpp"
#include "rive/data_bind/data_bind_container.hpp"
#include "rive/data_bind/context/context_value.hpp"
#include "rive/data_bind/context/context_value_any.hpp"
#include "rive/data_bind/context/context_value_asset_image.hpp"
#include "rive/data_bind/context/context_value_asset_font.hpp"
#include "rive/data_bind/context/context_value_asset_blob.hpp"
#include "rive/data_bind/context/context_value_artboard.hpp"
#include "rive/data_bind/context/context_value_boolean.hpp"
#include "rive/data_bind/context/context_value_number.hpp"
#include "rive/data_bind/context/context_value_string.hpp"
#include "rive/data_bind/context/context_value_enum.hpp"
#include "rive/data_bind/context/context_value_list.hpp"
#include "rive/data_bind/context/context_value_color.hpp"
#include "rive/data_bind/context/context_value_trigger.hpp"
#include "rive/data_bind/context/context_value_symbol_list_index.hpp"
#include "rive/data_bind/context/context_value_viewmodel.hpp"
#include "rive/data_bind/data_values/data_type.hpp"
#include "rive/data_bind/converters/data_converter.hpp"
#include "rive/data_bind/converters/formula/formula_token.hpp"
#include "rive/constraints/scrolling/scroll_constraint.hpp"
#include "rive/animation/transition_viewmodel_condition.hpp"
#include "rive/animation/state_machine.hpp"
#include "rive/artboard_component_list.hpp"
#include "rive/generated/node_base.hpp"
#include "rive/importers/artboard_importer.hpp"
#include "rive/importers/state_machine_importer.hpp"
#include "rive/importers/backboard_importer.hpp"
#include "rive/component.hpp"

using namespace rive;

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

    return StatusCode::Ok;
}

StatusCode DataBind::import(ImportStack& importStack)
{
    auto backboardImporter =
        importStack.latest<BackboardImporter>(Backboard::typeKey);
    if (backboardImporter == nullptr)
    {
        return StatusCode::MissingObject;
    }
    file(backboardImporter->file());
    backboardImporter->addDataConverterReferencer(this);
    if (target())
    {
        initialize();
        auto input = ScriptInput::from(target());
        if (input != nullptr)
        {
            bool ownsDataBind = true;
            if (input->scriptedObject() != nullptr)
            {
                if (input->scriptedObject()->component() != nullptr)
                {
                    auto importer = importStack.latest<ArtboardImporter>(
                        ArtboardBase::typeKey);
                    if (importer != nullptr)
                    {
                        ownsDataBind = false;
                        importer->addDataBind(this);
                    }
                }
                else if (input->scriptedObject()->addDataBindFromScriptedObject(
                             this))
                {
                    ownsDataBind = false;
                }
            }
            input->dataBind(this, ownsDataBind);
        }
        else if (target()->is<DataConverter>())
        {
            target()->as<DataConverter>()->addDataBind(this);
        }
        else if (target()->is<FormulaToken>())
        {
            target()->as<FormulaToken>()->addDataBind(this);
        }
        else
        {
            switch (target()->coreType())
            {
                case BindablePropertyNumberBase::typeKey:
                case BindablePropertyStringBase::typeKey:
                case BindablePropertyBooleanBase::typeKey:
                case BindablePropertyEnumBase::typeKey:
                case BindablePropertyArtboardBase::typeKey:
                case BindablePropertyColorBase::typeKey:
                case BindablePropertyTriggerBase::typeKey:
                case BindablePropertyIntegerBase::typeKey:
                case BindablePropertyAssetBase::typeKey:
                case BindablePropertyViewModelBase::typeKey:
                case BindablePropertyListBase::typeKey:
                case TransitionPropertyViewModelComparatorBase::typeKey:
                case StateTransitionBase::typeKey:
                {
                    auto stateMachineImporter =
                        importStack.latest<StateMachineImporter>(
                            StateMachineBase::typeKey);
                    if (stateMachineImporter != nullptr)
                    {
                        stateMachineImporter->addDataBind(
                            std::unique_ptr<DataBind>(this));
                        return Super::import(importStack);
                    }
                    break;
                }
                default:
                {
                    // Prefer the artboard that actually owns the target object.
                    // Relying on latest<ArtboardImporter> can attach binds to
                    // the wrong source artboard when multiple artboards are
                    // loaded.
                    if (target()->is<Component>())
                    {
                        auto comp = target()->as<Component>();
                        auto parentArtboard = comp->artboard();
                        if (parentArtboard != nullptr)
                        {
                            parentArtboard->addDataBind(this);
                            return Super::import(importStack);
                        }
                    }

                    auto artboardImporter =
                        importStack.latest<ArtboardImporter>(
                            ArtboardBase::typeKey);
                    if (artboardImporter != nullptr)
                    {
                        artboardImporter->addDataBind(this);
                        return Super::import(importStack);
                    }
                    break;
                }
            }
        }
    }

    return Super::import(importStack);
}

DataType DataBind::outputType()
{
    if (converter() && converter()->outputType() != DataType::input &&
        converter() && converter()->outputType() != DataType::none)
    {
        return converter()->outputType();
    }
    return sourceOutputType();
}

DataType DataBind::sourceOutputType()
{
    if (m_Source != nullptr)
    {
        switch (m_Source->coreType())
        {
            case ViewModelInstanceNumberBase::typeKey:
                return DataType::number;
            case ViewModelInstanceStringBase::typeKey:
                return DataType::string;
            case ViewModelInstanceEnumBase::typeKey:
                return DataType::enumType;
            case ViewModelInstanceColorBase::typeKey:
                return DataType::color;
            case ViewModelInstanceBooleanBase::typeKey:
                return DataType::boolean;
            case ViewModelInstanceListBase::typeKey:
                return DataType::list;
            case ViewModelInstanceTriggerBase::typeKey:
                return DataType::trigger;
            case ViewModelInstanceSymbolListIndexBase::typeKey:
                return DataType::symbolListIndex;
            case ViewModelInstanceAssetImageBase::typeKey:
                return DataType::assetImage;
            case ViewModelInstanceAssetFontBase::typeKey:
                return DataType::assetFont;
            case ViewModelInstanceAssetBlobBase::typeKey:
                return DataType::assetBlob;
            case ViewModelInstanceArtboardBase::typeKey:
                return DataType::artboard;
            case ViewModelInstanceViewModelBase::typeKey:
                return DataType::viewModel;
        }
    }
    return DataType::none;
}

void DataBind::source(rcp<ViewModelInstanceValue> value)
{
    if (!bindsOnce())
    {
        value->addDependent(this);
    }
    m_Source = value;

    // We treat this as a special case. If an ArtboardComponentList's list
    // property is bound to a number instance, we know that the component
    // will be provided with dettached view model instances that need to be
    // advanced explicitly
    if (m_Source && target() && target()->is<ArtboardComponentList>())
    {
        target()->as<ArtboardComponentList>()->shouldResetInstances(
            m_Source->coreType() == ViewModelInstanceNumberBase::typeKey);
    }
}

void DataBind::clearSource()
{
    if (m_Source != nullptr)
    {

        if (!bindsOnce())
        {
            m_Source->removeDependent(this);
        }
        m_Source = nullptr;
    }
}

DataBind::~DataBind()
{
    unbind();
    delete m_ContextValue;
    m_ContextValue = nullptr;
    delete m_dataConverter;
    m_dataConverter = nullptr;
}

void DataBind::bind()
{
    delete m_ContextValue;
    m_ContextValue = nullptr;
    switch (outputType())
    {
        case DataType::number:
            m_ContextValue = new DataBindContextValueNumber(this);
            break;
        case DataType::string:
            m_ContextValue = new DataBindContextValueString(this);
            break;
        case DataType::boolean:
            m_ContextValue = new DataBindContextValueBoolean(this);
            break;
        case DataType::color:
            m_ContextValue = new DataBindContextValueColor(this);
            break;
        case DataType::enumType:
            m_ContextValue = new DataBindContextValueEnum(this);
            break;
        case DataType::list:
            m_ContextValue = new DataBindContextValueList(this);
            break;
        case DataType::trigger:
            m_ContextValue = new DataBindContextValueTrigger(this);
            break;
        case DataType::symbolListIndex:
            m_ContextValue = new DataBindContextValueSymbolListIndex(this);
            break;
        case DataType::assetImage:
            m_ContextValue = new DataBindContextValueAssetImage(this);
            break;
        case DataType::assetFont:
            m_ContextValue = new DataBindContextValueAssetFont(this);
            break;
        case DataType::assetBlob:
            m_ContextValue = new DataBindContextValueAssetBlob(this);
            break;
        case DataType::artboard:
            m_ContextValue = new DataBindContextValueArtboard(this);
            break;
        case DataType::viewModel:
            m_ContextValue = new DataBindContextValueViewModel(this);
            break;
        case DataType::any:
            m_ContextValue = new DataBindContextValueAny(this);
            break;
        default:
            break;
    }
    if (m_dataConverter)
    {
        m_dataConverter->reset();
    }
    // if this is a toSource bind on a push-capable target,
    // subscribe to the target's notifyPropertyChanged stream instead of
    // relying on per-frame polling. The container consults targetSupportsPush()
    // to decide whether to also enroll the bind in m_persistingDataBinds.
    //
    // bind() can be called more than once on the same DataBind (e.g. when
    // ArtboardComponentList rebinds list items as the viewmodel changes).
    // Unsubscribe first if we previously subscribed — otherwise
    // addPropertyObserver would prepend the same node twice and form a cycle
    // that makes notifyPropertyChanged loop forever. The Observing flag
    // gates this so we don't deref m_target when we never subscribed (which
    // would be a UAF if the target was freed first).
    if (hasFlag(Flag::Observing) && m_target != nullptr)
    {
        m_target->removePropertyObserver(this);
        setFlag(Flag::Observing, false);
    }
    if (toSource() && m_target != nullptr && targetSupportsPush())
    {
        m_target->addPropertyObserver(this);
        setFlag(Flag::Observing, true);
    }
    // (Re)bind is a reconcile, not a one-sided change: mark every direction the
    // bind supports so both sides sync in favor order (as before origin gating
    // existed). A one-sided change instead marks only its own direction bit.
    addDirt(reconcileDirt(), true);
}

#ifndef WITH_RIVE_EDITOR
void DataBind::target(Core* value)
{
    if (m_target == value)
    {
        return;
    }
    // Drop the subscription only when we actually have one — otherwise
    // dereferencing m_target is a UAF if the old target was freed before us
    // (we wouldn't have been notified via onTargetDestroyed because we
    // weren't in its observer list).
    if (hasFlag(Flag::Observing) && m_target != nullptr)
    {
        m_target->removePropertyObserver(this);
        setFlag(Flag::Observing, false);
    }
    m_target = value;
    // `clip` is bindable; a layout bound on clip needs its DrawableProxy up
    // front so it exists before the artboard's one-time proxy injection, even
    // while clip is currently false. Stamped here so it also covers instance
    // clones, whose targets are re-assigned through this setter.
    if (m_target != nullptr &&
        propertyKey() == LayoutComponentBase::clipPropertyKey &&
        m_target->is<LayoutComponent>())
    {
        m_target->as<LayoutComponent>()->markClipMayBeDynamic();
    }
    if (toSource() && m_target != nullptr && targetSupportsPush())
    {
        m_target->addPropertyObserver(this);
        setFlag(Flag::Observing, true);
    }
}
#endif

void DataBind::unbind()
{
    clearSource();
    if (hasFlag(Flag::Observing) && m_target != nullptr)
    {
        m_target->removePropertyObserver(this);
        setFlag(Flag::Observing, false);
    }
    if (m_dataConverter != nullptr)
    {
        m_dataConverter->unbind();
    }
    if (m_ContextValue != nullptr)
    {
        delete m_ContextValue;
        m_ContextValue = nullptr;
    }
}

bool DataBind::targetSupportsPush() const
{
    if (m_target == nullptr)
    {
        return false;
    }
    // Push works for any property whose value is exposed via a generated
    // setter that calls notifyPropertyChanged (i.e. anything in *_base.hpp).
    // The following targets are computed/derived and don't fit the push
    // model — leave them on the polling path:
    //
    //   * Solo's activeComponentId — derived from active child, no setter
    //   * BindablePropertyAsset's image — loaded asynchronously, no setter
    //   * BindablePropertyViewModel's value — set via dedicated method
    //   * ViewModelInstanceViewModel's reference — set via dedicated method
    //   * Node's computed* properties — written multiple times per frame by
    //     the transform/layout pipeline; pushing on every intermediate write
    //     triggers dependent binds mid-computation and shifts per-frame
    //     ordering. Polling at end of frame captures only the settled value.
    auto key = propertyKey();
    if (key == SoloBase::activeComponentIdPropertyKey ||
        key == NodeBase::computedLocalXPropertyKey ||
        key == NodeBase::computedLocalYPropertyKey ||
        key == NodeBase::computedWorldXPropertyKey ||
        key == NodeBase::computedWorldYPropertyKey ||
        key == NodeBase::computedRootXPropertyKey ||
        key == NodeBase::computedRootYPropertyKey ||
        key == NodeBase::computedWidthPropertyKey ||
        key == NodeBase::computedHeightPropertyKey ||
        key == ShapeBase::lengthPropertyKey ||
        key == ScrollConstraintBase::scrollIndexPropertyKey ||
        key == ScrollConstraintBase::scrollPercentXPropertyKey ||
        key == ScrollConstraintBase::scrollPercentYPropertyKey ||
        key == ScrollConstraintBase::velocityXPropertyKey ||
        key == ScrollConstraintBase::velocityYPropertyKey ||
        key == ScrollConstraintBase::scrollActivePropertyKey ||
        key == ScrollConstraintBase::computedContentWidthPropertyKey ||
        key == ScrollConstraintBase::computedContentHeightPropertyKey ||
        key == ColorChannelsBase::colorAlphaPropertyKey ||
        key == ColorChannelsBase::colorRedPropertyKey ||
        key == ColorChannelsBase::colorBluePropertyKey ||
        key == ColorChannelsBase::colorGreenPropertyKey)
    {
        return false;
    }
    auto t = m_target->coreType();
    if (t == BindablePropertyAssetBase::typeKey ||
        t == BindablePropertyViewModelBase::typeKey ||
        t == ViewModelInstanceViewModelBase::typeKey)
    {
        return false;
    }
    return true;
}

bool DataBind::canSkip()
{
    auto* t = target();
    return t && t->is<Component>() && t->as<Component>()->isCollapsed() &&
           propertyKey() != LayoutComponentStyleBase::displayValuePropertyKey;
}

void DataBind::update(ComponentDirt value)
{
    if (m_Source != nullptr && m_ContextValue != nullptr)
    {
        if ((value & ComponentDirt::Bindings) == ComponentDirt::Bindings)
        {
            // TODO: @hernan review how dirt and mode work together. If dirt is
            // not set for certain modes, we might be able to skip the mode
            // validation.
            auto flagsValue = static_cast<DataBindFlags>(flags());
            if (toTarget())
            {
                // Alternative A: a TwoWay bind subscribes to its target via
                // Core::notifyPropertyChanged. Without suppression, writing
                // the target here would push-notify ourselves and add a
                // spurious dirt entry, causing an extra updateSourceBinding
                // pass in the same frame (silver tests collapse_data_binds-
                // test_2 / virtualize_blendmode regress). Mirror the
                // suppressDirt pattern used by the source-apply path.
                suppressDirt(true);
                m_ContextValue->apply(target(),
                                      propertyKey(),
                                      (flagsValue & DataBindFlags::Direction) ==
                                          DataBindFlags::ToTarget,
                                      this);
                // We just wrote the target; sync the cached target value so it
                // reflects what we wrote instead of what was there before.
                m_ContextValue->refreshTargetValue(this);
                suppressDirt(false);
            }
        }
    }
}

void DataBind::updateDependents()
{
    if (m_dataConverter)
    {
        m_dataConverter->update();
    }
}

void DataBind::updateSourceBinding(bool invalidate)
{
    if (toSource() && target() && m_ContextValue != nullptr)
    {
        if (invalidate)
        {
            m_ContextValue->invalidate();
        }
        m_ContextValue->applyToSource(target(),
                                      propertyKey(),
                                      isMainToSource(),
                                      this);
    }
}

bool DataBind::isMainToSource()
{
    auto flagsValue = static_cast<DataBindFlags>(flags());
    return (flagsValue & DataBindFlags::Direction) == DataBindFlags::ToSource;
}

bool DataBind::sourceToTargetRunsFirst()
{
    auto flagsValue = static_cast<DataBindFlags>(flags());
    return (flagsValue & DataBindFlags::SourceToTargetRunsFirst) ==
           DataBindFlags::SourceToTargetRunsFirst;
}

ComponentDirt DataBind::reconcileDirt()
{
    return (toTarget() ? ComponentDirt::Bindings : ComponentDirt::None) |
           (toSource() ? ComponentDirt::BindingsTarget : ComponentDirt::None);
}

void DataBind::addDirt(ComponentDirt value, bool recurse)
{
    if (hasFlag(Flag::SuppressDirt) || (m_Dirt & value) == value)
    {
        // Already marked.
        return;
    }

    // Latch the direction this change came from so a converter that re-dirties
    // us over multiple frames (interpolators) re-asserts the same direction —
    // per-frame dirt gets cleared and can't carry the origin forward. Placed
    // after the guards above so a suppressed self-notify (from applying either
    // direction) can't flip the origin. Record a single origin, never the OR:
    // a reconcile marks both bits, in which case the favored direction wins.
    bool hasSource = enums::is_flag_set(value, ComponentDirt::Bindings);
    bool hasTarget = enums::is_flag_set(value, ComponentDirt::BindingsTarget);
    if (hasSource && hasTarget)
    {
        setFlag(Flag::TargetOrigin, !sourceToTargetRunsFirst());
    }
    else if (hasTarget)
    {
        setFlag(Flag::TargetOrigin, true);
    }
    else if (hasSource)
    {
        setFlag(Flag::TargetOrigin, false);
    }

    m_Dirt |= value;
#ifdef WITH_RIVE_TOOLS
    if (m_changedCallback != nullptr)
    {
        m_changedCallback();
    }
#endif
    if (enums::is_flag_set(m_Dirt, ComponentDirt::Dependents) &&
        m_ContextValue != nullptr)
    {
        m_ContextValue->invalidate();
    }
    if (m_container && !hasFlag(Flag::Collapsed))
    {
        m_container->addDirtyDataBind(this);
    }
}

void DataBind::container(DataBindContainer* container)
{
    m_container = container;
}

void DataBind::relinkDataBind() { m_container->rebuildDataBind(this); }

bool DataBind::bindsOnce()
{
    auto flagsValue = static_cast<DataBindFlags>(flags());
    return enums::is_flag_set(flagsValue, DataBindFlags::Once);
}

bool DataBind::toSource()
{
    auto flagsValue = static_cast<DataBindFlags>(flags());
    return enums::any_flag_set(flagsValue,
                               DataBindFlags::TwoWay | DataBindFlags::ToSource);
}

bool DataBind::toTarget()
{
    auto flagsValue = static_cast<DataBindFlags>(flags());
    return enums::is_flag_set(flagsValue, DataBindFlags::TwoWay) ||
           !enums::is_flag_set(flagsValue, DataBindFlags::ToSource);
}

bool DataBind::isNameBased()
{
    auto flagsValue = static_cast<DataBindFlags>(flags());
    return enums::is_flag_set(flagsValue, DataBindFlags::NameBased);
}

bool DataBind::advance(float elapsedTime)
{
    if (converter() && m_Source && !hasFlag(Flag::Collapsed))
    {
        return converter()->advance(elapsedTime);
    }
    return false;
}

void DataBind::file(File* value) { m_file = value; };

File* DataBind::file() const { return m_file; };

void DataBind::collapse(bool isCollapsed)
{
    if (hasFlag(Flag::Collapsed) == isCollapsed ||
        propertyKey() == LayoutComponentStyleBase::displayValuePropertyKey ||
        !targetSupportsPush())
    {
        return;
    }
    setFlag(Flag::Collapsed, isCollapsed);
    if (!isCollapsed && m_Dirt != ComponentDirt::None && m_container)
    {
        m_container->addDirtyDataBind(this);
    }
}

void DataBind::initialize()
{
    if (target() && target()->is<Component>())
    {
        target()->as<Component>()->addCollapsable(this);
    }
}