#include <Item/StatefulItem/ElectricDrill/ElectricDrill.hpp>
#include <Milestone/DiggingDeeperMilestone/DiggingDeeperMilestone.hpp>
#include <Model/Model.hpp>
#include <FluidRegistry/FluidRegistry.hpp>
#include <Utilities/Utilities.hpp>
#include <Block/FluidBlock/FluidBlock.hpp>
#include <BlockRegistry/BlockRegistry.hpp>
#include <Block/AirBlock/AirBlock.hpp>
#include <World/LocalWorld/LocalWorld.hpp>
#include <Display/WidgetDisplay/WorldDisplay/WorldDisplay.hpp>

ElectricDrill::ElectricDrill(std::string name) : StatefulItem(name)
{
    setMaxStackSize(1);
}

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

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

    int chargeHeight = 8 * state(stack) / capacity;
    context.color = Color::toolUsesLeftHigh;
    context.drawRect(x+7, y+8-chargeHeight, 1, chargeHeight);
}

std::string ElectricDrill::getDisplayName(const ItemStack &stack)
{
    return "Electric Drill";
}

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

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

void ElectricDrill::getExtraToolTipLines(const ItemStack &stack, ToolTip &tip)
{
    tip.addLine(formatString("$+/$+ J", state(stack), capacity));
}

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

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

    ItemStack fullStack = baseStack;
    state(fullStack) = capacity;
    outStacks.push_back(fullStack);
}

int ElectricDrill::pullEnergy(ItemStack &stack, int energy)
{
    int &storedEnergy = state(stack);
    if (energy > storedEnergy)
    {
        energy = storedEnergy;
    }

    storedEnergy -= energy;
    return energy;
}

int ElectricDrill::pushEnergy(ItemStack &stack, int energy)
{
    int &storedEnergy = state(stack);
    int maxToPush = capacity - storedEnergy;

    if (energy > maxToPush)
    {
        energy = maxToPush;
    }

    storedEnergy += energy;
    return energy;
}

bool ElectricDrill::canDig(ItemStack &stack, Block &block)
{
    return state(stack) != 0;
}

float ElectricDrill::getPowerAgainst(ItemStack &stack, Block &block)
{
    return block.hardness * 0.5f;
}

void ElectricDrill::harvest(ItemStack &stack, LocalWorld &world, glm::ivec3 pos)
{
    world.breakBlock(pos);
    state(stack)--;
}

Sound& ElectricDrill::getDigSoundFor(ItemStack &stack, Block &block)
{
    return Sound::drill;
}

void ElectricDrill::onMovedBy(Player &player, const ItemStack &stack)
{
    StatefulItem::onMovedBy(player, stack);

    const int &storedEnergy = state(stack);
    if (storedEnergy > 0)
    {
        player.achieve(DiggingDeeperMilestone::ID, DiggingDeeperMilestone::ChargeElectricDrill);
    }
}