#ifndef ENGINEERING_TABLE_CONTROLLER_HPP_
#define ENGINEERING_TABLE_CONTROLLER_HPP_

#include <memory>
#include <vector>
#include <Controller/InventoryController/InventoryController.hpp>
#include <Machine/MEngineeringTable/MEngineeringTable.hpp>
#include <DataLink/DataLink.hpp>
#include <MachineComponent/DataCableComponent/DataCableComponent.hpp>
#include <RemoteDataComponent/RemoteDataComponent.hpp>

/**
 * @brief The engineering table controller.
 */
class EngineeringTableController : public InventoryController
{
private:
    std::shared_ptr<MEngineeringTable> table;

    int storedEnergy = 0;
    int energyCapacity = 0;
    int progress = 0;
    int completedProgress = 0;
    bool isSwitchedOnPriv = false;
    std::vector<ItemStack> inputStacks;
    ItemStack outputStack;
    int recipeUpdateCounter = -1;
    MEngineeringTable::ChannelTable channelTable;
    MEngineeringTable::ItemInputChannelTable itemInputChannelTable;
    std::vector<DataCableComponent::InputRule> inputRules;

    Command<
        uint32_t,
        int,
        int,
        bool,
        std::vector<ItemStack>,
        ItemStack,
        int,
        MEngineeringTable::ChannelTable,
        MEngineeringTable::ItemInputChannelTable,
        std::vector<DataCableComponent::InputRule>
    > updateTableState;
    Command<uint32_t, bool> setSwitch;
    Command<uint32_t, uint32_t> setRecipe;
    Command<uint32_t, MEngineeringTable::Trigger, std::optional<DataLink::Channel>> setTriggerToChannel;
    Command<uint32_t, uint32_t, uint32_t, std::optional<DataLink::Channel>> setInputItemToChannel;

    RemoteDataComponent remoteDataComponent;

    Widget* makeTable();
    Widget* makeRecipeBook();
    Widget* makeDataOutputsTab();
    Widget* makeTriggerSetter(std::string label, MEngineeringTable::Trigger trigger);
    void onTriggerUpdated(MEngineeringTable::Trigger trigger);
    Widget* makeInputItemChannelSetter(size_t index);
    void onInputItemChannelUpdated(uint32_t index);

public:    
    EngineeringTableController(ControllerChannel &channel);

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

    virtual Widget* getRightPanel() override;
    virtual void update() override;
    virtual glm::vec4 getSlotHighlight(const std::string &id, int slot, ItemStack &stack) override;
};

#endif