#ifndef MMINING_RIG_HPP_
#define MMINING_RIG_HPP_

#include <Machine/IElectricMachine.hpp>
#include <Serialize/Serialize.hpp>
#include <vector>
#include <Machine/Machine.hpp>
#include <ItemStack/ItemStack.hpp>
#include <Item/IInventory.hpp>
#include <Machine/IBeltMachine.hpp>
#include <Entity/MiningRigEntity/MiningRigEntity.hpp>

/**
 * @brief The mining rig machine.
 */
class MMiningRig :
    public Machine,
    public IInventory,
    public IBeltMachine,
    public IElectricMachine
{
public:
    struct Stats
    {
        int depth = 0;
        int blocksMined = 0;

        inline bool operator==(const Stats &other) const
        {
            return depth == other.depth && blocksMined == other.blocksMined;
        }
    };

private:
    static constexpr int basePullUpPowerUsage = 50;
    static constexpr int pipesPerSteelIngot = 24;
    static constexpr int powerInputPerLaser = 6;
    static constexpr int miningPowerPerLaser = 4;

    std::vector<ItemStack> stacks;
    std::vector<ItemStack> mineQueue;
    glm::ivec3 drillOffset;
    int pipesLeft = 32;
    int numLasers = 1;
    int currentMiningDamage = 0;
    Stats stats;

    std::shared_ptr<MiningRigEntity> rigEntity;

    void checkMineQueue();

public:
    static constexpr int maxLasers = 64;

    MMiningRig(LocalWorld &world, glm::ivec3 pos);

    glm::ivec3 getDrillPos();
    BoundingBox<int> getDrillAreaBB();

    virtual void serializeState(std::vector<uint8_t> &outBytes) override;
    virtual void deserializeState(const uint8_t *data, size_t size) override;
    virtual int getNumSlots() override;
    virtual ItemStack getStackInSlot(int slot) override;
    virtual void setStackInSlot(int slot, ItemStack stack) override;
    virtual bool isAllowedStackInSlot(int slot, ItemStack stack) override;
    virtual void onItemStackEntering(Side side, ItemStack &stack) override;
    virtual ItemStack tryExtractItem(Side side, ItemFilter &filter, uint32_t modeCode) override;
    virtual bool canConnectExtractor(Side side) override;
    virtual void update() override;
    virtual bool canConnectElectricWire(Side side) override;

    friend class MiningRigController;
};

DERIVE_STRUCT_SERIALIZER(MMiningRig::Stats, self.depth, self.blocksMined);

#endif