#ifndef ITEM_EXTRACTOR_CONTROLLER_HPP_
#define ITEM_EXTRACTOR_CONTROLLER_HPP_

#include <Controller/InventoryController/InventoryController.hpp>
#include <Machine/IBeltMachine.hpp>
#include <RemoteDataComponent/RemoteDataComponent.hpp>
#include <Controller/Controller.hpp>
#include <Entity/PhysicsEntity/CameraEntity/Player/Player.hpp>
#include <Machine/MItemExtractor/MItemExtractor.hpp>
#include <MachineComponent/DataCableComponent/DataCableComponent.hpp>
#include <Widget/EnumSelector/EnumSelector.hpp>
#include <memory>

class ItemExtractorController final : public InventoryController
{
private:
    std::shared_ptr<MItemExtractor> extractor;
    bool switchedOn = false;
    FilterType filterType = FilterType::All;
    std::vector<ItemStack> filterItemStacks;
    int filterUpdateCounter = -1;
    std::optional<std::vector<IBeltMachine::ExtractionModeSpec>> modeSpecs;
    std::vector<EnumSelector<uint32_t>::Option> modeSpecOptions;
    uint32_t modeCode = 0;

    std::vector<DataCableComponent::InputRule> inputRules;

    Command<uint32_t, bool> setSwitch;
    Command<uint32_t, FilterType> setFilterType;
    Command<uint32_t, ItemStack> addItemFilter;
    Command<uint32_t, uint32_t> removeItemFilter;
    Command<
        uint32_t,
        bool,
        FilterType,
        std::vector<DataCableComponent::InputRule>,
        int,
        std::vector<ItemStack>,
        uint32_t
    > updateExtractorState;
    Command<uint32_t, std::vector<IBeltMachine::ExtractionModeSpec>> onModeSpecsLoaded;
    Command<uint32_t, uint32_t> setModeCode;

    RemoteDataComponent remoteDataComponent;

    void parseModeSpecs(const std::vector<IBeltMachine::ExtractionModeSpec> &modeSpecs);
    Widget* makeFilterTab();

public:
    ItemExtractorController(ControllerChannel &channel);

    void onConnect(std::shared_ptr<Machine> itemExtractorMachine);

    virtual Widget* getRightPanel() override;
    virtual bool isBusy() override;
    virtual void update() override;
};

#endif