#ifndef BLOCK_ITEM_HPP_
#define BLOCK_ITEM_HPP_

#include <Item/StatefulItem/StatefulItem.hpp>
#include <Block/Block.hpp>
#include <Serialize/Serialize.hpp>

struct BlockItemState
{
    Block *block;
};

bool operator==(const BlockItemState &a, const BlockItemState &b);

/**
 * @brief Represents the block item (a block represented as an item).
 */
class BlockItem : public StatefulItem<BlockItemState>
{
public:
    BlockItem(std::string name);

    /**
     * @brief Return the block contained in the specified stack.
     * 
     * Only call this if the stack contains a `BlockItem`!
     * 
     * @param stack The stack.
     * @return Reference to the block.
     */
    Block& getBlockInStack(ItemStack &stack);

    virtual void onUse(LocalWorld &world, IWorldActor &actor, ItemStack &stack, glm::ivec3 pos, Side side) override;
    virtual void draw(GraphicsContext &context, int x, int y, const ItemStack &stack) override;
    virtual std::string getDisplayName(const ItemStack &stack) override;
    virtual bool canMerge(const ItemStack &a, const ItemStack &b) override;
    virtual void draw3D(GraphicsContext &context, WorldDisplay &worldDisplay, glm::vec3 pos, ItemStack &stack) override;
    virtual void drawFlat(GraphicsContext &context, WorldDisplay &worldDisplay, glm::mat4 matrix, ItemStack &stack) override;
    virtual ItemStack getGrindingOutput(ItemStack &stack) override;
    virtual glm::vec3 getGlowColor(ItemStack &stack) override;
    virtual void onCollectedBy(Player &player, const ItemStack &stack) override;
    virtual void onMovedBy(Player &player, const ItemStack &stack) override;
};

template<>
struct SerialCodec<BlockItemState>
{
    static void encode(std::vector<uint8_t> &outBytes, const BlockItemState &state);
    static size_t decode(const uint8_t *data, size_t size, BlockItemState &state);
};

#endif