#include <Item/StatefulItem/BasicTool/BasicTool.hpp>
#include <Model/Model.hpp>
#include <World/LocalWorld/LocalWorld.hpp>
#include <Block/Block.hpp>
#include <Entity/PhysicsEntity/ItemEntity/ItemEntity.hpp>
#include <Utilities/Utilities.hpp>
#include <Display/WidgetDisplay/WorldDisplay/WorldDisplay.hpp>

bool operator==(const BasicToolState &a, const BasicToolState &b)
{
    return a.uses == b.uses;
}

glm::vec4 BasicTool::getUsesColor(int uses)
{
    if (uses > m_maxUses/2)
    {
        return Color::toolUsesLeftHigh;
    }
    else if (uses > m_maxUses/5)
    {
        return Color::toolUsesLeftMedium;
    }
    else
    {
        return Color::toolUsesLeftLow;
    }
}

BasicTool::BasicTool(std::string name, Material &mat, uint32_t maxUses) :
    StatefulItem(name),
    m_material(mat),
    m_maxUses(maxUses)
{}

const uint32_t& BasicTool::uses(const ItemStack &stack)
{
    return state(stack).uses;
}

uint32_t& BasicTool::uses(ItemStack &stack)
{
    return state(stack).uses;
}

void BasicTool::draw(GraphicsContext &context, int x, int y, const ItemStack &stack)
{
    context.color = glm::vec4(1.0f);
    context.drawMaterial(m_material, x, y);

    uint32_t usesLeft = m_maxUses - uses(stack);
    if (usesLeft == m_maxUses)
    {
        return;
    }

    context.color = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
    context.drawRect(x, y+7, 8, 1);

    context.color = getUsesColor(usesLeft);
    context.drawRect(x, y+7, 8 * usesLeft / m_maxUses, 1);
}

void BasicTool::draw3D(GraphicsContext &context, WorldDisplay &worldDisplay, glm::vec3 pos, ItemStack &stack)
{
    worldDisplay.drawMeshedIcon(context, m_material, pos);
}

void BasicTool::drawFlat(GraphicsContext &context, WorldDisplay &worldDisplay, glm::mat4 matrix, ItemStack &stack)
{
    worldDisplay.drawMeshedIconFlat(context, m_material, matrix);
}

void BasicTool::harvest(ItemStack &stack, LocalWorld &world, glm::ivec3 pos)
{
    Block *block = world.getBlockAt(pos);
    if (!block->canManuallyDig())
    {
        uses(stack)++;
    }

    world.breakBlock(pos);
}

void BasicTool::getExtraToolTipLines(const ItemStack &stack, ToolTip &tip)
{
    uint32_t usesLeft = m_maxUses - uses(stack);
    tip.addLine(
        formatString(
            "Uses left: $+$+/$+",
            GraphicsContext::colorstr(getUsesColor(usesLeft)),
            usesLeft,
            m_maxUses
        )
    );
}