#pragma once

#include <memory>
#include <vector>

#include "adapters/eft/items/catalog/ItemTemplateCatalogService.h"
#include "adapters/eft/runtime/EftGameContext.h"
#include "adapters/eft/items/wishlist/WishlistService.h"
#include "adapters/persistence/FileConfigPersistence.h"
#include "application/actions/UiActionDispatcher.h"
#include "application/config/ConfigService.h"
#include "application/diagnostics/DiagnosticsRegistry.h"
#include "application/contracts/UiCommands.h"
#include "application/contracts/UiReadModel.h"
#include "application/scheduling/TickSchedulers.h"
#include "bootstrap/modules/ChamsModule.h"
#include "bootstrap/modules/EspModule.h"
#include "bootstrap/modules/ItemModule.h"
#include "bootstrap/modules/PlayerModule.h"
#include "bootstrap/modules/QuestModule.h"
#include "bootstrap/modules/WatermarkModule.h"
#include "bootstrap/modules/WorldModule.h"
#include "presentation/localization/UiLocaleController.h"
#include "presentation/MenuPorts.h"

#ifdef INCLUDE_AIMBOT
#include "bootstrap/modules/AimbotModule.h"
#endif

namespace ta::bootstrap
{
    class ApplicationRuntime final : public ta::ui::UiReadModel,
                                     public ta::ui::UiCommands
    {
    public:
        ApplicationRuntime();
        ~ApplicationRuntime() noexcept override;

        ApplicationRuntime(const ApplicationRuntime&) = delete;
        ApplicationRuntime& operator=(const ApplicationRuntime&) = delete;

        void initialize();
        void reset_session() noexcept;

        void application_update();
        void gameworld_update(const Il2CppClass* game_world_class,
                              ta::adapters::il2cpp::Il2CppObjectInstance game_world_instance,
                              ta::adapters::il2cpp::Il2CppObjectInstance main_player);

        [[nodiscard]] ta::ui::UiShellSnapshot capture_ui_shell(bool include_diagnostics) const override;
        void submit_config_command(ta::ui::ConfigCommand command) override;

        [[nodiscard]] ta::presentation::MenuPorts menu_ports(ta::application::IKeyInput& key_input) noexcept;

    private:
        void register_module(const ta::bootstrap::modules::ModulePorts& ports);
        void create_config_service();
        void register_diagnostics();
        void reset_raid_features() noexcept;
        void reset_modules(ta::bootstrap::modules::ModuleResetScope scope) noexcept;

        ta::adapters::eft::items::ItemTemplateCatalogService item_catalog_service_;
        ta::adapters::eft::items::WishlistService wishlist_service_;
        ta::adapters::eft::runtime::EftGameContext game_context_;
        ta::application::UiActionDispatcher action_dispatcher_;

#ifdef INCLUDE_AIMBOT
        ta::bootstrap::modules::AimbotModule aimbot_module_;
#endif
        ta::bootstrap::modules::EspModule esp_module_;
        ta::bootstrap::modules::ChamsModule chams_module_;
        ta::bootstrap::modules::PlayerModule player_module_;
        ta::bootstrap::modules::WorldModule world_module_;
        ta::bootstrap::modules::ItemModule item_module_;
        ta::bootstrap::modules::QuestModule quest_module_;
        ta::bootstrap::modules::WatermarkModule watermark_module_;

        ta::adapters::persistence::FileConfigPersistence config_persistence_;
        ta::application::ApplicationTickScheduler application_ticks_;
        ta::application::GameTickScheduler game_ticks_;
        std::vector<const ta::bootstrap::modules::ModulePorts*> module_ports_;
        std::vector<ta::application::config::ConfigOwner*> config_owners_;
        ta::presentation::localization::UiLocaleController locale_controller_;
        std::unique_ptr<ta::application::config::ConfigService> config_;
        ta::application::diagnostics::DiagnosticsRegistry diagnostics_;
        bool was_in_raid_ = false;
    };
}
