#include "pch.hpp"
#include "common.hpp"
#include "core/memory.hpp"
#include "core/interfaces.hpp"

bool i::setup()
{
    bool success = true;

    const auto [client_base, client_size] = m_memory->get_module_info(CLIENT_DLL);
    if (!client_base.has_value() || !client_size.has_value())
    {
        LOG_ERROR("client.dll module info not found");
        return {};
    }
    LOG_INFO("client.dll base=%p size=%zu", (void*)client_base.value(), client_size.value());

    // Check schemasystem.dll module first
    const auto [ss_base, ss_size] = m_memory->get_module_info(SCHEMASYSTEM_DLL);
    if (!ss_base.has_value() || !ss_size.has_value())
    {
        LOG_ERROR("schemasystem.dll module not found in CS2!");
        return {};
    }
    LOG_INFO("schemasystem.dll base=%p size=%zu", (void*)ss_base.value(), ss_size.value());

    auto schema_pattern_result = m_memory->find_pattern(SCHEMASYSTEM_DLL, GET_SCHEMA_SYSTEM);
    if (!schema_pattern_result.has_value())
    {
        LOG_ERROR("pattern GET_SCHEMA_SYSTEM not found in schemasystem.dll!");
        return {};
    }
    LOG_INFO("schema pattern found at %p", (void*)schema_pattern_result.value().as<uintptr_t>());

    m_schema_system = schema_pattern_result.value().rip().as<c_schema_system*>();
    success &= (m_schema_system != nullptr);
    if (!m_schema_system)
    {
        LOG_ERROR("m_schema_system is null after rip()");
    }
    else
    {
        LOG_INFO("m_schema_system = %p", (void*)m_schema_system);
    }

    auto gv_pattern = m_memory->find_pattern(CLIENT_DLL, GET_GLOBAL_VARS);
    if (!gv_pattern.has_value())
    {
        LOG_ERROR("pattern GET_GLOBAL_VARS not found!");
        success = false;
    }
    else
    {
        m_global_vars = m_memory->read_t<c_global_vars*>(gv_pattern.value().rip().as<c_global_vars*>());
        success &= (m_global_vars != nullptr);
        if (!m_global_vars)
        {
            LOG_ERROR("m_global_vars is null");
        }
        else
        {
            LOG_INFO("m_global_vars = %p", (void*)m_global_vars);
        }
    }

    auto el_pattern = m_memory->find_pattern(CLIENT_DLL, GET_ENTITY_LIST);
    if (!el_pattern.has_value())
    {
        LOG_ERROR("pattern GET_ENTITY_LIST not found!");
        success = false;
    }
    else
    {
        m_game_entity_system = m_memory->read_t<c_game_entity_system*>(el_pattern.value().rip().as<c_game_entity_system*>());
        success &= (m_game_entity_system != nullptr);
        if (!m_game_entity_system)
        {
            LOG_ERROR("m_game_entity_system is null");
        }
        else
        {
            LOG_INFO("m_game_entity_system = %p", (void*)m_game_entity_system);
        }
    }

    return success;
}
