#include "adapters/eft/world/EftWorldGateway.h"

#include "adapters/eft/items/catalog/ItemTemplateCatalogService.h"
#include "adapters/eft/world/DoorUnlockService.h"
#include "adapters/eft/world/ItemTeleportService.h"
#include "foundation/diagnostics/ExecutionPath.h"

namespace ta::adapters::eft::world
{
EftWorldGateway::EftWorldGateway(ta::adapters::eft::runtime::EftGameContext& context,
                                 ta::adapters::eft::items::WishlistService& wishlist_service,
                                 ta::adapters::eft::items::ItemTemplateCatalogService& item_catalog_service)
    : context_(context), wishlist_service_(wishlist_service), item_catalog_service_(item_catalog_service)
{
}


void EftWorldGateway::game_tick(const ta::features::world::WorldSettings& settings,
                                std::vector<ta::features::world::WorldCommand> commands)
{
    const auto context = context_.snapshot();
    for (const ta::features::world::WorldCommand& command : commands)
        execute(settings, command, context);
}

void EftWorldGateway::execute(const ta::features::world::WorldSettings& settings,
                              const ta::features::world::WorldCommand& command,
                              const ta::adapters::eft::runtime::EftGameContextSnapshot& context)
{
    if (command.type == ta::features::world::WorldCommandType::UnlockDoors)
    {
        ta::foundation::execution_path::step(command.trace_id, "EftWorldGateway", "consume unlock doors request");
        log_result(ta::adapters::eft::world::unlock_doors(context.game_world_class), command.trace_id, "DoorUnlockService");
        return;
    }

    ItemTeleportRequest request = build_teleport_request(settings, command);
    if (request.include_wishlist_items)
        wishlist_service_.request_refresh();

    ta::foundation::execution_path::step(command.trace_id, "EftWorldGateway", "consume item-teleport request");
    log_result(
        ta::adapters::eft::world::teleport_items_to_player(
            context.game_world_instance,
            context.main_player,
            request,
            wishlist_service_.current(),
            item_catalog_service_),
        command.trace_id,
        "ItemTeleportService");
}

ItemTeleportRequest EftWorldGateway::build_teleport_request(
    const ta::features::world::WorldSettings& settings,
    const ta::features::world::WorldCommand& command) const
{
    ItemTeleportRequest request{};
    request.trace_id = command.trace_id;
    request.circle_radius = settings.item_teleport_circle_radius;
    request.height_offset = settings.item_teleport_height_offset;

    switch (command.type)
    {
    case ta::features::world::WorldCommandType::TeleportNormalItems:
        request.include_normal_items = true;
        request.normal_category_mask = settings.normal_category_mask;
        break;
    case ta::features::world::WorldCommandType::TeleportWishlistItems:
        request.include_wishlist_items = true;
        break;
    case ta::features::world::WorldCommandType::TeleportQuestItems:
        request.include_quest_items = true;
        break;
    case ta::features::world::WorldCommandType::TeleportCorpses:
        request.include_corpses = true;
        break;
    case ta::features::world::WorldCommandType::UnlockDoors:
    default:
        break;
    }
    return request;
}

void EftWorldGateway::log_result(const WorldActionResult& result,
                                 const std::uint64_t trace_id,
                                 const char* component)
{
    if (result.executed)
        ta::foundation::execution_path::complete(trace_id, component ? component : "WorldService", result.message);
    else
        ta::foundation::execution_path::fail(trace_id, component ? component : "WorldService", result.message);
}

}
