#include <Controller/InventoryController/UraniumRefineryController/UraniumRefineryController.hpp>
#include <Widget/FluidLevelIndicator/FluidLevelIndicator.hpp>
#include <Widget/IconLabel/IconLabel.hpp>
#include <Widget/Label/Label.hpp>
#include <Widget/ProgressIndicator/ProgressIndicator.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>

UraniumRefineryController::UraniumRefineryController(ControllerChannel &channel) :
    InventoryController(channel),
    updateUraniumRefineryState(this, RunsOn::Client,
        [this](int energy, int refuAmount, int progress) -> uint32_t
    {
        this->energy = energy;
        this->refuAmount = refuAmount;
        this->progress = progress;

        return 0;
    })
{}

void UraniumRefineryController::onConnect(std::shared_ptr<Machine> uraniumRefineryMachine)
{
    bindMachine(uraniumRefineryMachine);
    uraniumRefinery = std::dynamic_pointer_cast<MUraniumRefinery>(uraniumRefineryMachine);
}

Widget* UraniumRefineryController::getRightPanel()
{
    static std::string refuName("main:refu");

    return new Column(
        new Center(new Label("Uranium Refinery")),

        Layout::WithProportion<1>(),
        new Center(
            new Row(
                new Center(new ItemSlot(this, "machine", 0)),
                new Center(new ProgressIndicator<int>(progress, MUraniumRefinery::completedProgress)),
                new Panel(glm::ivec2(4, 0)),
                new Center(new FluidLevelIndicator(refuName, refuAmount, MUraniumRefinery::refuCapacity))
            )
        ),

        new Center(
            new Row(
                new Center(new ItemSlot(this, "machine", 1)),
                new Center(new IconLabel(Material::rightArrow)),
                new Panel(glm::ivec2(4, 0)),
                new Center(new BatteryView(energy, MUraniumRefinery::energyCapacity))
            )
        )
    );
}

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

    if (world.isLocal() && uraniumRefinery != nullptr)
    {
        if (
            energy != uraniumRefinery->getEnergy() ||
            refuAmount != uraniumRefinery->getRefuAmount() ||
            progress != uraniumRefinery->getProgress()
        )
        {
            energy = uraniumRefinery->getEnergy();
            refuAmount = uraniumRefinery->getRefuAmount();
            progress = uraniumRefinery->getProgress();
            
            updateUraniumRefineryState(energy, refuAmount, progress);
        }
    }
}

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

    if (id == "machine" && slot == 1)
    {
        return Color::rechargeHighlight;
    }

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

    if (stack.getItem()->name == "main:uraniumDust")
    {
        return Color::inputHighlight;
    }

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

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