#include "MrBotApiType.h"

unique_ptr<MrBotApiType> MrBotApiType::pMrBotApi = make_unique<MrBotApiType>();

bool MrBotApiType::GetMember(LSOBJECTDATA ObjectData, PLSTYPEMEMBER pMember, int argc, char *argv[], LSOBJECT &Dest)
{
    if (ObjectData.Ptr == nullptr)
    {
        return false;
    }

    const auto theMember = memberMap.find(static_cast<MrBotApiTypeMembers>(pMember->ID));
    if (theMember == memberMap.end())
    {
        return false;
    }

    return theMember->second(argc, argv, Dest);
}

bool MrBotApiType::GetMethod(LSOBJECTDATA &ObjectData, PLSTYPEMEMBER pMethod, int argc, char *argv[])
{
    if (ObjectData.Ptr == nullptr)
    {
        return false;
    }

    const auto theMethod = methodMap.find(static_cast<MrBotApiTypeMethods>(pMethod->ID));
    if (theMethod == methodMap.end())
    {
        return false;
    }

    return theMethod->second(argc, argv);
}

bool MrBotApiType::ToText(LSOBJECTDATA ObjectData, char *buf, unsigned int buflen)
{
    return false;
}

unsigned long MrBotApiType::GetActorIdByName(const std::string &actorName, bool exactMatch)
{
    const auto actor = ExtensionTLOs::Actor().GetActorByName(actorName, exactMatch);
    if (actor.has_value())
    {
        return actor->Id();
    }

    return -1;
}

// Members
bool MrBotApiType::Version(const std::vector<std::string> &args, LSOBJECT &dest)
{
    constexpr const char *version = "0.1.0";
    log << "MrBotApiType::Version: " << version << std::endl;
    dest.ConstCharPtr = version;
    dest.Type = pStringType;
    return true;
}

// Methods
bool MrBotApiType::ClickActorByName(const std::string name)
{
    if (name.empty())
    {
        logw << "MrBotApiType::ClickActorByName: Actor name is empty" << std::endl;
        return false;
    }

    const auto actorId = GetActorIdByName(name);
    if (actorId == -1)
    {
        logw << "MrBotApiType::ClickActorByName: Actor not found: " << name << std::endl;
        return false;
    }

    return ClickActorById({std::to_string(actorId)});
}

bool MrBotApiType::ClickActorById(const string id)
{
    if (id.empty())
    {
        logw << "MrBotApiType::ClickActorById: Actor id is empty" << std::endl;
        return false;
    }

    log << "MrBotApiType::ClickActorById " << id << std::endl;
    const auto actor = ExtensionTLOs::Actor().GetActorById(std::stoul(id));

    if (!actor.has_value())
    {
        logw << "MrBotApiType::ClickActorById: Actor not found: " << id << std::endl;
        return false;
    }

    log << "MrBotApiType::ClickActorById: Actor found: " << actor->Name() << std::endl;

    actor->DoubleClick();
    return true;
}

bool MrBotApiType::ApplyVerb(const string actorName, const string verb)
{
    if (actorName.empty() || verb.empty())
    {
        logw << "MrBotApiType::ApplyVerb: Actor name or verb is empty" << std::endl;
        return false;
    }

    const auto actorId = GetActorIdByName(actorName);
    if (actorId == -1)
    {
        logw << "MrBotApiType::ApplyVerb: Actor not found: " << actorName << std::endl;
        return false;
    }

    const auto command = "eq2execute apply_verb " + std::to_string(actorId) + " \"" + verb + "\"";
    log << "MrBotApiType::ApplyVerb: " << command << std::endl;
    const auto response = pISInterface->ExecuteCommand(command.c_str());

    return response == 0;
}

bool MrBotApiType::ConversationBubble(const string option)
{
    return false;
}
