#ifdef WITH_RIVE_SCRIPTING
#include "rive/lua/rive_lua_libs.hpp"
#endif
#include "rive/assets/script_asset.hpp"
#include "rive/artboard.hpp"
#include "rive/file.hpp"
#include "rive/script_input_artboard.hpp"
#include "rive/animation/scripted_listener_action.hpp"
#include "rive/animation/scripted_transition_condition.hpp"
#include "rive/scripted/scripted_data_converter.hpp"
#include "rive/scripted/scripted_drawable.hpp"
#include "rive/scripted/scripted_interpolator.hpp"
#include "rive/scripted/scripted_layout.hpp"
#include "rive/scripted/scripted_path_effect.hpp"
#include "rive/scripted/scripted_object.hpp"
#include "rive/data_bind/data_bind.hpp"

using namespace rive;

ScriptedObject* ScriptedObject::from(Core* object)
{
    switch (object->coreType())
    {
        case ScriptedDataConverter::typeKey:
            return object->as<ScriptedDataConverter>();
        case ScriptedDrawable::typeKey:
            return object->as<ScriptedDrawable>();
        case ScriptedLayout::typeKey:
            return object->as<ScriptedLayout>();
        case ScriptedPathEffect::typeKey:
            return object->as<ScriptedPathEffect>();
        case ScriptedListenerAction::typeKey:
            return object->as<ScriptedListenerAction>();
        case ScriptedTransitionCondition::typeKey:
            return object->as<ScriptedTransitionCondition>();
        case ScriptedInterpolator::typeKey:
            return object->as<ScriptedInterpolator>();
    }
    return nullptr;
}

#ifdef WITH_RIVE_SCRIPTING
void ScriptedObject::setArtboardInput(std::string name, Artboard* artboard)
{
    lua_State* L = state();
    if (L == nullptr || scriptAsset() == nullptr)
    {
        return;
    }
    rive_lua_pushRef(L, m_self);
    auto artboardInstance = artboard->instance();
    artboardInstance->frameOrigin(false);
    lua_newrive<ScriptedArtboard>(L,
                                  L,
                                  scriptAsset()->file(),
                                  std::move(artboardInstance),
                                  nullptr,
                                  dataContext());
    lua_setfield(L, -2, name.c_str());
    rive_lua_pop(L, 1);
    addScriptedDirt(ComponentDirt::ScriptUpdate);
}

void ScriptedObject::setBooleanInput(std::string name, bool value)
{
    lua_State* L = state();
    if (L == nullptr)
    {
        return;
    }
    rive_lua_pushRef(L, m_self);
    lua_pushboolean(L, value);
    lua_setfield(L, -2, name.c_str());
    rive_lua_pop(L, 1);
    addScriptedDirt(ComponentDirt::ScriptUpdate);
}

void ScriptedObject::setNumberInput(std::string name, float value)
{
    lua_State* L = state();
    if (L == nullptr)
    {
        return;
    }
    rive_lua_pushRef(L, m_self);
    lua_pushnumber(L, value);
    lua_setfield(L, -2, name.c_str());
    rive_lua_pop(L, 1);
    addScriptedDirt(ComponentDirt::ScriptUpdate);
}

void ScriptedObject::setIntegerInput(std::string name, int value)
{
    lua_State* L = state();
    if (L == nullptr)
    {
        return;
    }
    rive_lua_pushRef(L, m_self);
    lua_pushunsigned(L, value);
    lua_setfield(L, -2, name.c_str());
    rive_lua_pop(L, 1);
    addScriptedDirt(ComponentDirt::ScriptUpdate);
}

void ScriptedObject::setStringInput(std::string name, std::string value)
{
    lua_State* L = state();
    if (L == nullptr)
    {
        return;
    }
    rive_lua_pushRef(L, m_self);
    lua_pushstring(L, value.c_str());
    lua_setfield(L, -2, name.c_str());
    rive_lua_pop(L, 1);
    addScriptedDirt(ComponentDirt::ScriptUpdate);
}

void ScriptedObject::setViewModelInput(std::string name,
                                       ViewModelInstanceValue* value)
{
    lua_State* L = state();
    if (L == nullptr)
    {
        return;
    }
    rive_lua_pushRef(L, m_self);
    switch (value->coreType())
    {
        case ViewModelInstanceViewModelBase::typeKey:
        {
            auto viewModel = value->as<ViewModelInstanceViewModel>();
            auto vmi = viewModel->referenceViewModelInstance();
            if (vmi == nullptr)
            {
                fprintf(stderr,
                        "riveLuaPushViewModelInstanceValue - passed in a "
                        "ViewModelInstanceViewModel with no associated "
                        "ViewModelInstance.\n");
                return;
            }

            lua_newrive<ScriptedViewModel>(L,
                                           L,
                                           ref_rcp(vmi->viewModel()),
                                           vmi);
            break;
        }
        default:
            break;
    }
    lua_setfield(L, -2, name.c_str());
    rive_lua_pop(L, 1);
    addScriptedDirt(ComponentDirt::ScriptUpdate);
}

void ScriptedObject::trigger(std::string name)
{
    lua_State* L = state();
    if (L == nullptr)
    {
        return;
    }
    rive_lua_pushRef(L, m_self);
    if (static_cast<lua_Type>(lua_getfield(L, -1, name.c_str())) !=
        LUA_TFUNCTION)
    {
        rive_lua_pop(L, 2);
        return;
    }
    lua_pushvalue(L, -2);
    rive_lua_pcall_with_context(L, this, 1, 0);
    rive_lua_pop(L, 1);
    addScriptedDirt(ComponentDirt::ScriptUpdate);
}

bool ScriptedObject::scriptAdvance(float elapsedSeconds)
{
    lua_State* L = state();
    if (!advances() || L == nullptr)
    {
        return false;
    }
    rive_lua_pushRef(L, m_self);
    // implementedMethods may be assumed for legacy files (all-bits default); if
    // the field isn't actually a function, treat it as not implemented.
    if (static_cast<lua_Type>(lua_getfield(L, -1, "advance")) != LUA_TFUNCTION)
    {
        rive_lua_pop(L, 2); // non-function field + self
        return false;
    }
    lua_pushvalue(L, -2);
    lua_pushnumber(L, elapsedSeconds);
    if (static_cast<lua_Status>(rive_lua_pcall_with_context(L, this, 2, 1)) !=
        LUA_OK)
    {
        rive_lua_pop(L, 2);
        return false;
    }
    bool result = lua_toboolean(L, -1);
    rive_lua_pop(L, 2);
    return result;
}

void ScriptedObject::scriptUpdate()
{
    lua_State* L = state();
    if (!updates() || L == nullptr)
    {
        return;
    }
    // Stack: []
    rive_lua_pushRef(L, m_self);
    // Stack: [self]
    if (static_cast<lua_Type>(lua_getfield(L, -1, "update")) != LUA_TFUNCTION)
    {
        // Not actually implemented (assumed for legacy files); no-op. The
        // update phase never started, so there's no flag to reset.
        rive_lua_pop(L, 2); // non-function field + self
        return;
    }
    // Only inside the update phase while the callback actually runs.
    m_inUpdatePhase = true;
    // Stack: [self, field] Swap self and field
    lua_insert(L, -2);
    // Stack: [field, self]
    if (static_cast<lua_Status>(rive_lua_pcall_with_context(L, this, 1, 0)) !=
        LUA_OK)
    {
        rive_lua_pop(L, 1);
    }
    m_inUpdatePhase = false;
}

bool ScriptedObject::tryLuaUserInit(lua_State* L)
{
    rive_lua_pushRef(L, m_self);
    // Stack: [self]
    if (static_cast<lua_Type>(lua_getfield(L, -1, "init")) != LUA_TFUNCTION)
    {
        // init is optional and not implemented (assumed for legacy files);
        // nothing to run — the object is considered initialized.
        rive_lua_pop(L, 2); // non-function field + self
        return true;
    }
    // Stack: [self, field]
    lua_pushvalue(L, -2);
    // Stack: [self, field, self]
    // Reuse the ScriptedContext created during ensureScriptInitialized so
    // the generator and init() both see the same Context instance.
    rive_lua_pushRef(L, m_context);
    // Stack: [self, field, self, ScriptedContext]
    auto pCallResult = rive_lua_pcall_with_context(L, this, 2, 1);
    if (static_cast<lua_Status>(pCallResult) != LUA_OK)
    {
        lua_unref(L, m_self);
        disposeScriptedContext();
        // Stack: [self, status]
        rive_lua_pop(L, 2);
        if (m_vm != nullptr)
        {
            m_vm->unregisterScriptedObject(this);
        }
        m_vm = nullptr;
        m_self = 0;
        return false;
    }
    if (!lua_toboolean(L, -1) || m_contextPtr->missingRequestedData())
    {
        lua_unref(L, m_self);
        disposeScriptedContext();
        rive_lua_pop(L, 2);
        if (m_vm != nullptr)
        {
            m_vm->unregisterScriptedObject(this);
        }
        m_vm = nullptr;
        m_self = 0;
        return false;
    }
    // Stack: [self, result]
    rive_lua_pop(L, 1);
    assert(static_cast<lua_Type>(lua_type(L, -1)) == LUA_TTABLE);
    // Stack: [self]
    rive_lua_pop(L, 1);
    return true;
}

bool ScriptedObject::ensureScriptInitialized(ScriptingVM* vm)
{
    lua_State* L = vm ? vm->state() : nullptr;
    if (L == nullptr)
    {
        return false;
    }
    if (m_self != 0 && m_vm == vm)
    {
        rive_lua_pop(L, 1);
        return true;
    }
    if (m_vm != nullptr)
    {
        lua_State* oldState = state();
        if (m_self != 0)
        {
            lua_unref(oldState, m_self);
            m_self = 0;
        }

        disposeTrackedProperties();
        disposeScriptedContext();
        m_vm->unregisterScriptedObject(this);
    }
    m_userLuaInitDone = false;

    for (auto prop : m_customProperties)
    {
        auto scriptInput = ScriptInput::from(prop);
        if (scriptInput && !scriptInput->validateForColdScriptInit())
        {
            rive_lua_pop(L, 1);
            return false;
        }
    }

    // Create the Context userdata before calling the generator so scripts
    // can request resources at construction time (e.g.
    // `return { canvas = context:gpuCanvas() }`). The same Context is
    // reused in tryLuaUserInit when init(self, context) is called, so a
    // script only ever sees one Context per scripted-object lifetime.
    // Stack: [generator]
    m_contextPtr = lua_newrive<ScriptedContext>(L, this);
    // Stack: [generator, context]
    m_context = lua_ref(L, -1);
    // Stack: [generator, context]  (lua_ref does not pop)

    // m_vm is not yet assigned here, so disposeScriptedContext() cannot
    // resolve a lua_State via state(). Unref/clear directly on failure.
    auto disposeContextDirect = [&]() {
        if (m_contextPtr != nullptr)
        {
            m_contextPtr->clearScriptedObject();
            m_contextPtr = nullptr;
        }
        if (m_context != 0)
        {
            lua_unref(L, m_context);
            m_context = 0;
        }
    };

    if (static_cast<lua_Status>(rive_lua_pcall_with_context(L, this, 1, 1)) !=
        LUA_OK)
    {
        disposeContextDirect();
        rive_lua_pop(L, 1);
        return false;
    }
    if (static_cast<lua_Type>(lua_type(L, -1)) != LUA_TTABLE)
    {
        disposeContextDirect();
        rive_lua_pop(L, 1);
        return false;
    }
    m_self = lua_ref(L, -1);
    m_vm = vm;
    if (vm != nullptr)
    {
        vm->registerScriptedObject(this);
    }
    rive_lua_pop(L, 1);
    return true;
}

bool ScriptedObject::hydrateScriptInputs()
{
    lua_State* L = state();
    if (L == nullptr || m_self == 0)
    {
        return false;
    }
    // First validate that all properties are hydratable.
    // This ensures we don't partially hydrate props and early out on the next
    // step
    for (auto prop : m_customProperties)
    {
        auto scriptInput = ScriptInput::from(prop);
        if (scriptInput != nullptr &&
            !scriptInput->validateHydrationPrerequisites())
        {
            return false;
        }
    }
    // Next hydrate all properties
    for (auto prop : m_customProperties)
    {
        auto scriptInput = ScriptInput::from(prop);
        if (scriptInput != nullptr && !scriptInput->hydrateScriptInput())
        {
            return false;
        }
    }
    // Finally initialize the script if it hasn't been initialized before.
    if (inits() && !m_userLuaInitDone)
    {
        if (!tryLuaUserInit(L))
        {
            return false;
        }
        m_userLuaInitDone = true;
    }
    didHydrateScriptInputs();
    return true;
}

void ScriptedObject::disposeScriptInputs()
{
    for (auto prop : m_customProperties)
    {
        auto scriptInput = ScriptInput::from(prop);
        if (scriptInput != nullptr)
        {
            scriptInput->scriptedObject(nullptr);
        }
    }
    m_customProperties.clear();
}

void ScriptedObject::disposeTrackedProperties()
{

    auto trackedProperties = m_trackedScriptedProperties;
    for (auto* property : trackedProperties)
    {
        if (property != nullptr)
        {
            property->dispose();
        }
    }
}

void ScriptedObject::disposeScriptedContext()
{
    if (m_contextPtr != nullptr)
    {
        m_contextPtr->clearScriptedObject();
        m_contextPtr = nullptr;
    }
    if (m_context != 0)
    {
        lua_State* L = state();
        if (L != nullptr)
        {
            lua_unref(L, m_context);
        }
        m_context = 0;
    }
}

void ScriptedObject::scriptDispose()
{
    disposeScriptInputs();
    disposeTrackedProperties();
    m_trackedScriptedProperties.clear();

    lua_State* L = state();
    if (L != nullptr)
    {
        lua_unref(L, m_self);
        disposeScriptedContext();
    }
    if (m_vm != nullptr)
    {
        m_vm->unregisterScriptedObject(this);
        m_vm = nullptr;
    }
    m_self = 0;
    m_userLuaInitDone = false;
}
#else
void ScriptedObject::setArtboardInput(std::string name, Artboard* artboard) {}

void ScriptedObject::setBooleanInput(std::string name, bool value) {}

void ScriptedObject::setIntegerInput(std::string name, int value) {}

void ScriptedObject::setNumberInput(std::string name, float value) {}

void ScriptedObject::setStringInput(std::string name, std::string value) {}

void ScriptedObject::setViewModelInput(std::string name,
                                       ViewModelInstanceValue* value)
{}

void ScriptedObject::trigger(std::string name) {}

bool ScriptedObject::scriptAdvance(float elapsedSeconds) { return false; }

void ScriptedObject::scriptUpdate() {}

void ScriptedObject::scriptDispose() {}

void ScriptedObject::disposeScriptInputs() {}
#endif

void ScriptedObject::reinit()
{
    if (scriptAsset() != nullptr)
    {
        scriptAsset()->initScriptedObject(this);
#ifdef WITH_RIVE_SCRIPTING
        hydrateScriptInputs();
        didReinit();
#endif
    }
}

ScriptAsset* ScriptedObject::scriptAsset() const
{
    return (ScriptAsset*)m_fileAsset.get();
}

void ScriptedObject::setAsset(rcp<FileAsset> asset)
{
    if (asset != nullptr && asset->is<ScriptAsset>())
    {
        FileAssetReferencer::setAsset(asset);
    }
}

void ScriptedObject::markNeedsUpdate() {}

void ScriptedObject::cloneProperties(CustomPropertyContainer* twin,
                                     DataBindContainer* dataBindContainer) const
{

    for (auto prop : m_customProperties)
    {
        auto clonedValue = prop->clone()->as<CustomProperty>();
        twin->addProperty(clonedValue);
        auto input = ScriptInput::from(prop);
        if (input != nullptr)
        {
            auto dataBind = input->dataBind();
            if (dataBind)
            {
                auto dataBindClone = static_cast<DataBind*>(dataBind->clone());
                dataBindClone->file(dataBind->file());
                if (dataBind->converter() != nullptr)
                {
                    dataBindClone->converter(
                        dataBind->converter()->clone()->as<DataConverter>());
                }
                dataBindClone->target(clonedValue);
                dataBindContainer->addDataBind(dataBindClone);
                if (auto* clonedInput = ScriptInput::from(clonedValue))
                {
                    clonedInput->dataBind(dataBindClone,
                                          /*ownsDataBind=*/false);
                }
            }
        }
    }
}