#include <Item/Item.hpp>
#include <ItemStack/ItemStack.hpp>
#include <PlayerTriggerRegistry/PlayerTriggerRegistry.hpp>

Item::Item(std::string name) : maxStackSize(256), name(name) {}

void Item::onUse(LocalWorld &world, IWorldActor &actor, ItemStack &stack, glm::ivec3 pos, Side side)
{
    // NOP
}

void Item::getExtraToolTipLines(const ItemStack &stack, ToolTip &tip)
{
    // NOP
}

int Item::getMaxStackSize()
{
    return maxStackSize;
}

Item& Item::setMaxStackSize(int size)
{
    maxStackSize = size;
    return *this;
}

bool Item::canMerge(const ItemStack &a, const ItemStack &b)
{
    return a.getItem() == b.getItem();
}

ItemStack Item::getGrindingOutput(ItemStack &stack)
{
    return ItemStack();
}

glm::vec3 Item::getGlowColor(ItemStack &stack)
{
    return glm::vec3(0.0f);
}

void Item::onCollectedBy(Player &player, const ItemStack &stack)
{
    playerTriggerRegistry.raise(player, formatString("main:ItemCollected::$+", name));
}

void Item::onMovedBy(Player &player, const ItemStack &stack)
{
    playerTriggerRegistry.raise(player, formatString("main:ItemMoved::$+", name));
}

void Item::onEquippedBy(Player &player, const ItemStack &stack)
{
    playerTriggerRegistry.raise(player, formatString("main:ItemEquipped::$+", name));
}

void Item::getCheatStacks(ItemStack &baseStack, std::vector<ItemStack> &outStacks)
{
    outStacks.push_back(baseStack);
}

void Item::onPickedUpInCheatBook(ItemStack &stack)
{
    // NOP
}

std::string Item::trySetOption(ItemStack &stack, const std::string &optionStr)
{
    size_t colonPos = optionStr.find('=');
    if (colonPos == optionStr.npos)
    {
        return formatString("Invalid argument '$+': must have form 'option=value'.", optionStr);
    }

    std::string option = optionStr.substr(0, colonPos);
    std::string value = optionStr.substr(colonPos + 1);

    if (option.empty() || value.empty())
    {
        return formatString("Invalid argument '$+': must have form 'option=value'.", optionStr);
    }

    auto it = optionSetters.find(option);
    if (it == optionSetters.end())
    {
        return formatString("Invalid option '$+' for item '$+'.", option, name);
    }

    AbstractOptionSetter &setter = it->second;
    return setter(stack, value);
}