#ifndef DOOR_HPP_
#define DOOR_HPP_

#include <Block/SpriteBlock/SpriteBlock.hpp>

class Door : public SpriteBlock
{
private:
    /*
        #              Door Meta Byte
        +-------+---+---+---+---+---+---+---+---+
        | Bit   | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
        +-------+---+---+---+---+---+---+---+---+
        | Field |   |   |   | O |  dir  |segment|
        +-------+---+---+---+---+---+---+---+---+

        segment
            Which segment of the door it is ('11' is invalid).
        
        dir
            The side number on which the door would lay in its closed position.
        
        O
            If set, the door is open.
    */

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

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

    static constexpr Side metaGetClosingSide(uint8_t meta)
    {
        return Side((meta >> 2) & 3);
    }

    static constexpr bool metaIsOpen(uint8_t meta)
    {
        return (meta & metaOpen) != 0;
    }

    static std::vector<Sprite> makeSprites();

public:
    Door(std::string name);

    virtual bool canManuallyDig() override;
    virtual bool canPlace(LocalWorld &world, IWorldActor &actor, glm::ivec3 pos, Side side, uint8_t &meta) 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 bool isIntersectedBy(World &world, glm::ivec3 pos, const BoundingBox<wfixed> &box) override;
};

#endif