#include "preview.hpp"

#include <algorithm>

#include "../../util/imgui.hpp"
#include "../../util/imgui/style.hpp"
#include "../../util/imgui/widget.hpp"
#include "../../util/vector.hpp"

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

namespace game::state::select
{
  void Preview::update(Resources& resources, int characterIndex)
  {
    if (characterIndex != -1 && isInGame) actor.update();

    if (!vector::in_bounds(resources.characterPreviews, characterIndex)) return;

    auto& style = ImGui::GetStyle();
    auto viewport = ImGui::GetMainViewport();
    auto* character = resources.characterPreviews[characterIndex].root();
    if (!character) return;
    auto size = ImVec2(viewport->Size.x / 2.0f - (style.WindowPadding.x * 2.0f),
                       (viewport->Size.y / 2.0f) - (style.WindowPadding.y * 2.0f));
    auto pos = ImVec2(style.WindowPadding.x, style.WindowPadding.y);

    ImGui::SetNextWindowSize(size);
    ImGui::SetNextWindowPos(pos);
    imgui::style::color_set(character->color);

    if (ImGui::Begin("##Preview", nullptr,
                     ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse |
                         ImGuiWindowFlags_NoTitleBar))
    {
      if (ImGui::BeginTabBar("##Preview Tab Bar"))
      {
        auto available = ImGui::GetContentRegionAvail();
        auto availableSize = imgui::to_vec2(available);
        if (WIDGET_FX(ImGui::BeginTabItem("Render")))
        {
          auto textureSize = vec2(character->render.texture.size);

          if (character->render.is_valid())
          {
            auto scale =
                (availableSize.x <= 0.0f || availableSize.y <= 0.0f || textureSize.x <= 0.0f || textureSize.y <= 0.0f)
                    ? 0.0f
                    : std::min(availableSize.x / textureSize.x, availableSize.y / textureSize.y);

            auto renderSize = ImVec2(textureSize.x * scale, textureSize.y * scale);

            ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + (availableSize.x * 0.5f) - (renderSize.x * 0.5f),
                                       ImGui::GetCursorPosY() + (availableSize.y * 0.5f) - (renderSize.y * 0.5f)));

            ImGui::Image(character->render.texture.id, renderSize);
          }
          else
          {
            ImGui::TextUnformatted(character->name.c_str());
            if (!character->description.empty()) ImGui::TextWrapped("%s", character->description.c_str());
          }

          ImGui::EndTabItem();
        }

        if (WIDGET_FX(ImGui::BeginTabItem("In Game")))
        {
          isInGame = true;

          if (previousCharacterIndex != characterIndex)
          {
            actor = Entity(resources.character_get(characterIndex).root()->anm2Entry.anm2);
            canvas.clear();
            previousCharacterIndex = characterIndex;
          }

          auto& rendered = canvas.render(resources, actor, available);

          auto cursorPos = ImGui::GetCursorPos();
          ImGui::SetCursorPos(ImVec2(cursorPos.x + (availableSize.x * 0.5f) - (canvas.imageSize.x * 0.5f),
                                     cursorPos.y + (availableSize.y * 0.5f) - (canvas.imageSize.y * 0.5f)));

          ImGui::Image(rendered.texture, canvas.imageSize);

          ImGui::EndTabItem();
        }
        else
          isInGame = false;

        ImGui::EndTabBar();
      }
    }
    ImGui::End();
    imgui::style::color_set(resources.settings.root()->color);
  }
}
