#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::scriptDrawCanvas()
{
    lua_State* L = state();
    if (!drawsCanvas() || L == nullptr)
    {
        return;
    }
    rive_lua_pushRef(L, m_self);
    if (static_cast<lua_Type>(lua_getfield(L, -1, "drawCanvas")) !=
        LUA_TFUNCTION)
    {
        rive_lua_pop(L, 2); // non-function field + self
        return;
    }
    lua_pushvalue(L, -2);
    if (static_cast<lua_Status>(rive_lua_pcall(L, 1, 0)) != LUA_OK)
    {
        rive_lua_pop(L, 1);
        return;
    }
    rive_lua_pop(L, 1);
}

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::scriptDrawCanvas() {}

void ScriptedObject::scriptUpdate() {}

void ScriptedObject::scriptDispose() {}

void ScriptedObject::disposeScriptInputs() {}
#endif

void ScriptedObject::reinit()
{
    if (scriptAsset() != nullptr)
    {
        scriptAsset()->initScriptedObject(this);
#ifdef WITH_RIVE_SCRIPTING
        hydrateScriptInputs();
#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);
                }
            }
        }
    }
}