#ifndef CONVEYOR_BELT_HPP_
#define CONVEYOR_BELT_HPP_

#include <Block/SpriteBlock/SpriteBlock.hpp>
#include <BlockAtlas/BlockAtlas.hpp>

class ConveyorBelt : public SpriteBlock
{
private:
    /*

        #            Conveyor Belt Meta Byte
        +-------+---+---+---+---+---+---+---+---+
        | Bit   | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
        +-------+---+---+---+---+---+---+---+---+
        | Field |   |   |   | A | frame | orient|
        +-------+---+---+---+---+---+---+---+---+

        orient
            The side towards which the conveyor belt points.
        
        frame
            The frame offset to apply to the animation.
        
        A
            If set, the belt is active. (Note: this is never actually set on the block,
            but is used during BeltView rendering.)

    */

    static constexpr uint8_t metaActive = 1 << 4;
    static constexpr uint8_t numStates = 1 << 5;

    static constexpr Side getMetaOrientation(uint8_t meta)
    {
        return Side(meta & 3);
    }

    static constexpr int getMetaFrameOffset(uint8_t meta)
    {
        return (meta >> 2) & 3;
    }

    static const std::vector<std::string>& getStateNames();

    void onInteractWithRollers(LocalWorld &world, Player &player, glm::ivec3 pos, Side side, const RGBABytes &collisionKey);
    void onInteractWithBelt(LocalWorld &world, Player &player, glm::ivec3 pos, Side side, const RGBABytes &collisionKey);

public:
    static constexpr uint64_t ticksPerVoxel = 6;
    static constexpr double entityPushSpeed = 1.0 / 8.0 / 6.0;

    ConveyorBelt(std::string name);

    // TODO: Find a better way than this hack.
    BlockAtlas::SpriteID getBeltSpriteForMeta(uint8_t meta);

    virtual bool canManuallyDig() override;
    virtual bool canPlace(LocalWorld &world, IWorldActor &actor, glm::ivec3 pos, Side side, uint8_t &meta) override;
    virtual void onPlaced(LocalWorld &world, Chunk &chunk, glm::ivec3 pos) override;
    virtual void onRemoved(LocalWorld &world, Chunk &chunk, glm::ivec3 pos, uint8_t meta) override;
    virtual void onInteract(LocalWorld &world, Player &player, glm::ivec3 pos, Side side, const RGBABytes &collisionKey) override;
    virtual void onWalkingOver(World &world, glm::ivec3 pos, PhysicsEntity &entity) override;
    virtual BlockAtlas::SpriteID getBlockSprite(glm::ivec3 pos, uint8_t meta, World &world) override;
};

#endif