#include "cheats.hpp"

#include <algorithm>
#include <ranges>

#include "../../util/imgui/input_int_ex.hpp"
#include "../../util/imgui/widget.hpp"

using namespace game::util::imgui;
using namespace game::util;
using namespace game::resource::xml;

namespace game::state::play
{
  void Cheats::update(Resources&, Entity& character, menu::Inventory& inventory)
  {
    auto& strings = character.data.strings;

    if (ImGui::BeginChild("##Cheats"))
    {
      auto stage = character.stage + 1;
      auto maxCapacity = (float)character.max_capacity();
      auto capacityMin = (float)character.data.root()->capacityMinCalories;
      auto capacityMax = (float)character.data.root()->capacityMaxCalories;
      auto weightMin = (float)character.data.root()->weightKilograms;
      auto weightMax = (float)character.data.root()->weightMaxKilograms;
      auto digestionRateMin = (float)character.data.root()->digestionRateMin * Entity::UPDATE_RATE;
      auto digestionRateMax = (float)character.data.root()->digestionRateMax * Entity::UPDATE_RATE;
      auto digestionRate = character.digestion_rate_get();
      auto eatSpeedMin = (float)character.data.root()->eatSpeedMinMultiplier;
      auto eatSpeedMax = (float)character.data.root()->eatSpeedMaxMultiplier;

      auto weight_update = [&]()
      {
        character.play({.animation = character.idle_animation_get(), .appendID = character.animation_append_id_get()});
      };

      WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsCalories).c_str(), &character.calories, 0.0f, maxCapacity,
                                   "%0.0f kcal"));
      WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsCapacity).c_str(), &character.capacity, capacityMin,
                                   capacityMax, "%0.0f kcal"));

      if (WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsWeight).c_str(), &character.weight, weightMin,
                                       weightMax,
                                        strings.get(Strings::CheatsWeightFormat).c_str())))
        weight_update();

      auto stages = character.data.stages_get();
      if (WIDGET_FX(ImGui::SliderInt(strings.get(Strings::CheatsStage).c_str(), &stage, 1,
                                     (int)stages.size() + 1)))
      {
        character.stage = glm::clamp(0, stage - 1, (int)stages.size());
        character.weight =
            character.stage == 0 ? character.data.root()->weightKilograms : stages.at(character.stage - 1)->thresholdKilograms;
        weight_update();
      }

      if (WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsDigestionRate).c_str(), &digestionRate,
                                       digestionRateMin, digestionRateMax,
                                       strings.get(Strings::CheatsDigestionRateFormat).c_str())))
        character.digestionRate = digestionRate / Entity::UPDATE_RATE;
      WIDGET_FX(ImGui::SliderFloat(strings.get(Strings::CheatsEatSpeed).c_str(), &character.eatSpeed, eatSpeedMin,
                                   eatSpeedMax,
                                    strings.get(Strings::CheatsEatSpeedFormat).c_str()));

      if (WIDGET_FX(ImGui::Button(strings.get(Strings::CheatsDigestButton).c_str())))
        character.digestionProgress = Entity::DIGESTION_MAX;

      ImGui::SeparatorText(strings.get(Strings::CheatsInventory).c_str());

      if (ImGui::BeginChild("##Inventory", ImGui::GetContentRegionAvail(), ImGuiChildFlags_Borders))
      {
        auto& schema = character.data.itemSchema;

        ImGui::PushItemWidth(100);
        for (int i = 0; i < (int)schema.items.size(); i++)
        {
          auto& item = schema.items[i];
          ImGui::PushID(i);
          WIDGET_FX(input_int_range(item.name.c_str(), &inventory.values[i], 0, schema.quantityMax, 1, 5));
          ImGui::SetItemTooltip("%s", item.name.c_str());
          ImGui::PopID();
        }
        ImGui::PopItemWidth();
      }
      ImGui::EndChild();
    }
    ImGui::EndChild();
  }
}
