#ifndef BELT_MANAGER_HPP_
#define BELT_MANAGER_HPP_

#include <vector>

#include <Belt/Belt.hpp>

class LocalWorld;

/**
 * @brief Manages belts associated with a world.
 */
class BeltManager
{
private:
    LocalWorld &world;
    std::vector<std::shared_ptr<Belt>> belts;

public:
    BeltManager(LocalWorld &world);

    /**
     * @brief Load the belt data.
     */
    void load();

    /**
     * @brief Save the belt data.
     */
    void save();

    /**
     * @brief Returns, creating if necessary, an operational belt at a given source position and direction.
     *
     * @param sourcePos The source position from which the belt originates.
     * @param dir The direction in which the belt propagates.
     * @return A shared pointer to the operational belt.
     */
    std::shared_ptr<Belt> acquireOperationalBelt(glm::ivec3 sourcePos, Side dir);

    /**
     * @brief Add a segment of a belt.
     *
     * This handles merging with other belts as well. If no merging is performed, then a new,
     * non-operational belt is created.
     * 
     * @param pos The position of the segment.
     * @param dir The direction we propagate in.
     */
    void addBeltSegment(glm::ivec3 pos, Side dir);

    /**
     * @brief Removes any belt segments at the specified position.
     */
    void removeBeltSegment(glm::ivec3 pos);

    /**
     * @brief Try inserting an item into the specified position.
     * 
     * @param pos The position of the block to insert into.
     * @param side The side from which we are inserting.
     * @param stack The stack to insert.
     */
    void tryInsertInto(glm::ivec3 pos, Side side, ItemStack &stack);

    /**
     * @brief The advancing the belt at the specified position.
     */
    void tryAdvanceBelt(glm::ivec3 pos);
};

#endif