#ifndef ITOOL_HPP_
#define ITOOL_HPP_

#include <BoundingBox/BoundingBox.hpp>
#include <Sound/Sound.hpp>
#include <Utilities/FixedPoint.hpp>

class ItemStack;
class Block;
class LocalWorld;
class World;
class Player;

/**
 * @brief An interface which items may implement if they are tools.
 */
class ITool
{
public:
    virtual ~ITool() = default;

    /**
     * @brief Decide if we can dig the specified block.
     * 
     * @param stack The stack containing this tool.
     * @param block The block in question.
     */
    virtual bool canDig(ItemStack &stack, Block &block) = 0;

    /**
     * @brief Get the power against the specified block.
     * 
     * @param stack The stack containing this tool.
     * @param block The block in question.
     */
    virtual float getPowerAgainst(ItemStack &stack, Block &block) = 0;

    /**
     * @brief Get the sound to use for digging the specified block.
     * 
     * @param stack The stack containing this tool.
     * @param block The block in question.
     * @return The sound to play while digging.
     */
    virtual Sound& getDigSoundFor(ItemStack &stack, Block &block) = 0;

    /**
     * @brief Indicate that the specified block has been harvested.
     * 
     * This method is responsible for breaking the block and anything else that is
     * supposed to be harvested.
     * 
     * @param stack The item stack containing this item.
     * @param world The world.
     * @param x Block X position.
     * @param y Block Y position.
     * @param z Block Z position.
     */
    virtual void harvest(ItemStack &stack, LocalWorld &world, glm::ivec3 pos) = 0;

    /**
     * @brief Get the blocks to select based on the tool and primary selection.
     *
     * By default, pushes only the primary block position.
     * 
     * @param stack The tool item stack.
     * @param player The player holding this tool.
     * @param world The world we are in.
     * @param primaryBlockPos The block position of the block the player is pointing at.
     * @param selectedBlocks Push the selected block positions here.
     */
    virtual void getSelectedBlocks(
        ItemStack &stack,
        Player &player,
        World &world,
        glm::ivec3 primaryBlockPos,
        std::vector<glm::ivec3> &selectedBlocks
    );
};

#endif