#include <BlockRegistry/BlockRegistry.hpp>
#include <Controller/InventoryController/AccumulatorController/AccumulatorController.hpp>
#include <Widget/Label/Label.hpp>
#include <Widget/Layout/CompoundWidget/IconText/IconText.hpp>
#include <Widget/StaticItemSlot/ItemSlot/ItemSlot.hpp>
#include <Widget/Layout/Row/Row.hpp>
#include <Widget/Layout/Column/Column.hpp>
#include <Widget/Layout/Center/Center.hpp>
#include <Widget/Builder/Builder.hpp>
#include <Utilities/Utilities.hpp>
#include <Entity/PhysicsEntity/CameraEntity/Player/Player.hpp>
#include <World/World.hpp>
#include <Widget/FlameStatusIndicator/FlameStatusIndicator.hpp>
#include <Widget/BatteryView/BatteryView.hpp>
#include <Widget/Panel/Panel.hpp>
#include <World/World.hpp>
#include <FluidRegistry/FluidRegistry.hpp>
#include <Widget/DownArrow/DownArrow.hpp>
#include <Item/IEnergyContainingItem.hpp>

AccumulatorController::AccumulatorController(ControllerChannel &channel) :
    InventoryController(channel),
    updateAccumulatorState(this, RunsOn::Client,
        [this](int energy) -> uint32_t
    {
        this->energy = energy;

        return 0;
    })
{}

void AccumulatorController::onConnect(std::shared_ptr<Machine> accumulatorMachine)
{
    bindMachine(accumulatorMachine);
    accumulator = std::dynamic_pointer_cast<MAccumulator>(accumulatorMachine);
}

Widget* AccumulatorController::getRightPanel()
{
    return new Column(
        new Center(new IconText(
            blockRegistry.getBlockByName("main:accumulator").iconMaterial,
            "Accumulator"
        )),

        Layout::WithProportion<1>(),
        new Center(
            new Column(
                new Center(new ItemSlot(this, "machine", 0)),
                new Center(new DownArrow()),
                new Center(new BatteryView(energy, MAccumulator::capacity, 1000, 12)),
                new Center(new DownArrow()),
                new Center(new ItemSlot(this, "machine", 1))
            )
        )
    );
}

void AccumulatorController::update()
{
    InventoryController::update();

    if (world.isLocal() && accumulator != nullptr)
    {
        if (energy != accumulator->getEnergy())
        {
            energy = accumulator->getEnergy();
            
            updateAccumulatorState(energy);
        }
    }
}

glm::vec4 AccumulatorController::getSlotHighlight(const std::string &id, int slot, ItemStack &stack)
{
    if (id == "machine")
    {
        return Color::rechargeHighlight;
    }

    if (stack.isEmpty())
    {
        return InventoryController::getSlotHighlight(id, slot, stack);
    }

    IEnergyContainingItem *energyContainer = stack.getItemAs<IEnergyContainingItem>();
    if (energyContainer != nullptr)
    {
        return Color::rechargeHighlight;
    }

    return InventoryController::getSlotHighlight(id, slot, stack);
}