#include <AsyncWorldCloner/AsyncWorldCloner.hpp>
#include <DevCommand/WCloneCommand/WCloneCommand.hpp>
#include <Log/Log.hpp>
#include <AtomicDataStore/AtomicDataStore.hpp>
#include <Utilities/Async.hpp>
#include <WorldAvatar/WorldAvatar.hpp>

int WCloneCommand::execute(const std::vector<std::string> &args)
{
    if (args.size() < 4)
    {
        Log::error("Syntax: wclone <filename> <newfilename> [--enable-cheats] [--set-avatar=<number>] [--singleplayer=<player-name>]");
        return 1;
    }

    std::string oldFilename = args[2];
    std::string newFilename = args[3];

    bool enableCheats = false;
    std::optional<WorldAvatar> avatarToSet;
    std::string intoSinglePlayer;

    for (size_t i = 4; i < args.size(); i++)
    {
        if (args[i] == "--enable-cheats")
        {
            enableCheats = true;
        }
        else if (args[i].substr(0, 13) == "--set-avatar=")
        {
            std::string avatarStr = args[i].substr(13);
            int avatarNum;
            try
            {
                avatarNum = std::stoi(avatarStr);
                if (avatarNum < 0 || avatarNum >= static_cast<int>(worldAvatarList.size()))
                {
                    Log::error(formatString("Invalid avatar number: $+", avatarStr));
                    return 1;
                }
            }
            catch (std::exception &)
            {
                Log::error(formatString("Invalid avatar number: $+", avatarStr));
                return 1;
            }

            avatarToSet = worldAvatarList[avatarNum];
        }
        else if (args[i].substr(0, 15) == "--singleplayer=")
        {
            intoSinglePlayer = args[i].substr(15);
        }
        else
        {
            Log::error(formatString("Unknown option: $+", args[i]));
            return 1;
        }
    }

    AsyncWorldCloner cloner(oldFilename, newFilename);
    const std::string &cloneError = cloner.getError();

    if (!cloneError.empty())
    {
        Log::error(formatString("Failed to clone the world: $+", cloneError));
        return 1;
    }

    cloner.start(enableCheats, avatarToSet, intoSinglePlayer);
    awaitAsyncBarrier(AsyncBarrier::CurrentlyDispatched);

    if (!cloneError.empty())
    {
        Log::error(formatString("Failed to clone the world: $+", cloneError));
        return 1;
    }

    Log::info("World successfully cloned.");
    return 0;
}