#include "menu.hpp"

#include "style.hpp"

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

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

namespace game::state::play
{
  void Menu::update(Resources& resources, ItemManager& itemManager, Entity& character, Text& text, Autofeed& autofeed)
  {
    static constexpr auto WIDTH_MULTIPLIER = 0.30f;
    static constexpr auto HALF_MULTIPLIER = 0.5f;
    static constexpr auto BAR_DIVIDER_THICKNESS = 1.0f;
    static constexpr auto PADDING_SIZE_MULTIPLIER = 2.0f;
    static constexpr auto ZERO_FLOAT = 0.0f;
    static constexpr auto ONE_FLOAT = 1.0f;
    static constexpr auto MENU_STYLE_VAR_COUNT = 2;
    static constexpr auto MENU_BAR_STYLE_VAR_COUNT = 4;
    static constexpr auto MENU_BAR_FLAGS = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar |
                                           ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
                                           ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;

    auto& schema = character.data.menuSchema;
    auto& strings = character.data.strings;

    auto style = ImGui::GetStyle();
    auto& io = ImGui::GetIO();

    slide.update(isOpen, io.DeltaTime);
    fullscreenSlide.update(isOpen && isFullscreen, io.DeltaTime);

    ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0);
    ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);

    auto windowSize = imgui::to_ivec2(ImGui::GetMainViewport()->Size);
    auto barSize =
        ImVec2(imgui::side_bar_width_get(), windowSize.y - style.WindowPadding.y * PADDING_SIZE_MULTIPLIER);
    auto fullscreenOffset = barSize.x;

    auto normalSize =
        ImVec2(windowSize.x * WIDTH_MULTIPLIER, windowSize.y - style.WindowPadding.y * PADDING_SIZE_MULTIPLIER);
    auto fullscreenSize =
        ImVec2(windowSize.x - fullscreenOffset, windowSize.y - style.WindowPadding.y * PADDING_SIZE_MULTIPLIER);
    auto fullscreenT = fullscreenSlide.eased_get();
    auto size = ImVec2(normalSize.x + (fullscreenSize.x - normalSize.x) * fullscreenT,
                       normalSize.y + (fullscreenSize.y - normalSize.y) * fullscreenT);
    auto targetX = windowSize.x - size.x;
    auto t = slide.value_get();
    auto eased = slide.eased_get();
    auto isFullscreenVisible = fullscreenSlide.value_get() > ZERO_FLOAT;
    auto isFullscreenResizeSettled =
        isFullscreen ? fullscreenSlide.value_get() >= ONE_FLOAT : fullscreenSlide.value_get() <= ZERO_FLOAT;
    auto posX = windowSize.x + (targetX - windowSize.x) * eased;

    auto pos = ImVec2(posX, style.WindowPadding.y);
    auto barPos = ImVec2(pos.x - barSize.x, style.WindowPadding.y);

    if (slide.is_visible())
    {
      ImGui::SetNextWindowSize(size);
      ImGui::SetNextWindowPos(pos);

      if (ImGui::Begin("##Menu", nullptr,
                       ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
                           ImGuiWindowFlags_NoMove))
      {
        if (ImGui::BeginTabBar("##Options"))
        {

          if (WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabInteract).c_str())))
          {
            interact.update(resources, text, character, isFullscreenVisible);
            ImGui::EndTabItem();
          }

          if (WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabGather).c_str())))
          {
            gather.update(isFullscreen, isFullscreenResizeSettled);
            ImGui::EndTabItem();
          }

          if (WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabInventory).c_str())))
          {
            inventory.update(resources, itemManager, character, autofeed);
            ImGui::EndTabItem();
          }

          if (WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabSettings).c_str())))
          {
            settingsMenu.update(resources, SettingsMenu::PLAY, &strings);
            if (settingsMenu.isJustColorSet) style::color_set(resources, character);
            ImGui::EndTabItem();
          }

          if (isCheats && WIDGET_FX(ImGui::BeginTabItem(strings.get(Strings::MenuTabCheats).c_str())))
          {
            cheats.update(resources, character, inventory);
            ImGui::EndTabItem();
          }
        }
        ImGui::EndTabBar();
      }
      ImGui::End();
    }

    ImGui::SetNextWindowSize(barSize);
    ImGui::SetNextWindowPos(barPos);

    ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0);
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2());
    ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2());
    ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, barSize);
    if (ImGui::Begin("##Menu Open Bar", nullptr, MENU_BAR_FLAGS))
    {
      auto buttonSize = ImGui::GetContentRegionAvail();
      auto cursorPos = ImGui::GetCursorScreenPos();
      auto halfButtonSize = ImVec2(buttonSize.x, buttonSize.y * HALF_MULTIPLIER);
      auto activeButtonSize = isOpen && !isFullscreenVisible ? halfButtonSize : buttonSize;

      auto tooltip_set = [&](const std::string& tooltip)
      {
        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding);
        ImGui::SetItemTooltip("%s", tooltip.c_str());
        ImGui::PopStyleVar();
      };

      auto isMainResult = WIDGET_FX(ImGui::Button("##MenuToggleNormal", activeButtonSize));
      if (t <= 0.0f || t >= 1.0f)
      {
        tooltip_set(strings.get(isFullscreenVisible ? Strings::MenuRestoreTooltip
                                             : isOpen ? Strings::MenuCloseTooltip
                                                      : Strings::MenuOpenTooltip));
        if (isMainResult)
        {
          if (isFullscreenVisible)
          {
            if (isFullscreen) schema.root()->soundClose.play();
            isFullscreen = false;
          }
          else
          {
            isOpen = !isOpen;
            isFullscreen = false;
            if (isOpen)
              schema.root()->soundOpen.play();
            else
              schema.root()->soundClose.play();
          }
        }
        if (!isOpen && !isMainResult && ImGui::IsItemHovered())
        {
          isOpen = true;
          isFullscreen = false;
          schema.root()->soundOpen.play();
        }
      }

      auto fullscreenCursorPos = ImGui::GetCursorScreenPos();
      auto isFullscreenResult = false;
      if (isOpen && !isFullscreenVisible)
      {
        isFullscreenResult = WIDGET_FX(ImGui::Button("##MenuToggleFullscreen", halfButtonSize));
        if (t <= 0.0f || t >= 1.0f)
        {
          tooltip_set(strings.get(Strings::MenuOpenFullscreenTooltip));
          if (isFullscreenResult)
          {
            isFullscreen = true;
            schema.root()->soundOpen.play();
          }
        }
      }

      auto direction = !isOpen ? imgui::TriangleDirection::LEFT : imgui::TriangleDirection::RIGHT;
      imgui::triangle_draw(*ImGui::GetWindowDrawList(), cursorPos, activeButtonSize, direction,
                           ImGui::GetColorU32(ImGuiCol_Text));
      if (isOpen && !isFullscreenVisible)
      {
        auto separatorY = cursorPos.y + halfButtonSize.y;
        ImGui::GetWindowDrawList()->AddLine(ImVec2(cursorPos.x, separatorY),
                                            ImVec2(cursorPos.x + buttonSize.x, separatorY),
                                            ImGui::GetColorU32(ImGuiCol_Separator), BAR_DIVIDER_THICKNESS);
        imgui::triangle_draw(*ImGui::GetWindowDrawList(), fullscreenCursorPos, halfButtonSize,
                             imgui::TriangleDirection::LEFT, ImGui::GetColorU32(ImGuiCol_Text));
      }
    }
    ImGui::End();
    ImGui::PopStyleVar(MENU_BAR_STYLE_VAR_COUNT);
    ImGui::PopStyleVar(MENU_STYLE_VAR_COUNT);
  }
}
