#include "dialogs.hpp"

#include "misc/cpp/imgui_stdlib.h"
#include "imgui.h"
#include "utils/types.hpp"

namespace rrr::layers::gui
{
  void dialogs::on_attach() 
  {
    BASE_WINDOW_FLAGS();
  }

  void dialogs::on_detach()
  {

  }

  void dialogs::gui_render()
  {
    if (!show) return;

    ImVec2 center = ImGui::GetMainViewport()->GetCenter();
    ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.8f));
    ImGui::SetNextWindowSize(ImVec2(width, height));

    ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);

    BEGIN_IMGUI_WIN();

    if (delete_dialog)
      draw_delete_dialog();

    if (create_dialog)
      draw_create_dialog();

    if (rename_dialog)
      draw_rename_dialog();

    if (help_dialog)
      draw_help_dialog();

    END_IMGUI_WIN();

    ImGui::PopStyleVar();
  }

  void dialogs::on_event(system_event& e)
  {
    if (e.get_name() == try_engine::system_event::classificator::WINDOW_RESIZE())
      resize();

    if (e.get_name() == try_engine::system_event::classificator::KEY_PRESSED())
      pressed(e);

    if (e.get_name() == try_engine::system_event::classificator::KEY_RELEASED())
      released(e);
  }

  void dialogs::resize()
  {
    height = try_engine::application::get()->get_window()->height() / 5.f;
    width = try_engine::application::get()->get_window()->width() / 3.2f;
  }

  void dialogs::on_event(std::any event_type, std::any value)
  {
    auto et = std::any_cast<types::event_type>(event_type);

    switch (et)
    {
      case types::event_type::SHOW_DELETE_ONE_FILE_DIALOG:
        {
          current_file = std::any_cast<file>(value);
          show = true;
          delete_dialog = true;
        }
        break;
      case types::event_type::SHOW_CREATE_FILE_DIALOG:
        {
          show = true;
          create_dialog = true;
        }
        break;
      case types::event_type::SHOW_RENAME_FILE_DIALOG:
        {
          current_file = std::any_cast<file>(value);
          show = true;
          rename_dialog = true;
        }
        break;
      case types::event_type::SHOW_HELP_DIALOG:
        {
          show = true;
          help_dialog = true;
        }
        break;
      default:
        break;
    }
  }

  void dialogs::on_update(time t)
  {

  }

  void dialogs::pressed(system_event& e)
  {
    auto key = static_cast<try_engine::system_event::key_pressed_event&>(e);

    if (key.get_keycode() == try_engine::key::LEFTSHIFT || key.get_keycode() == try_engine::key::RIGHTSHIFT)
      shift = true;

    if (key.get_keycode() == try_engine::key::N)
    {
      if (delete_dialog)
      {
        delete_dialog = false;
        show = false;
        em->execute(types::event_type::UNFREEZE_BROWSER_ACTION, nullptr);
      }
    }

    if (key.get_keycode() == try_engine::key::ESCAPE)
      cancel();
    
    if (shift && key.get_keycode() == try_engine::key::Y)
    {
      if (delete_dialog)
      {
        show = false;
        delete_dialog = false;
        em->execute(types::event_type::DELETE_CURRENT_FILE, nullptr);
      }
    }

    if (key.get_keycode() == try_engine::key::ENTER)
    {
      if (create_dialog)
        create_file();
      if (rename_dialog)
        rename();
    }

    if (help_dialog && key.get_keycode() == try_engine::key::F1)
      cancel();
  }

  void dialogs::released(system_event& e)
  {
    auto key = static_cast<try_engine::system_event::key_pressed_event&>(e);

    if (key.get_keycode() == try_engine::key::LEFTSHIFT || key.get_keycode() == try_engine::key::RIGHTSHIFT)
      shift = false;
  }

  void dialogs::draw_delete_dialog()
  {
    TR_PUSH_FONT(MEDIUM, 18);
    std::string label = current_file.type == file_type::DIR ? "Даннaя директория будет удалена!" : "Данный файл будет удален!";

    // манипуляции с тем чтобы название стояло посередлине
    // см. и ниже тоже
    auto pos = ImGui::GetCursorPos();
    pos.x = width / (current_file.type == file_type::DIR ? 5.4f : 4.8f);
    pos.y += 12.f; 
    ImGui::SetCursorPos(pos);
    ImGui::TextUnformatted(label.data());
    ImGui::Separator();

    // манипуляции с тем чтобы название стояло посередлине
    // тут и зависимость от длинны строки и размера шрифта, но не того
    // что выше при определении шрифта, а того который нужен для отрисовки 
    // на самом экране
    pos = ImGui::GetCursorPos();
    auto p = current_file.path.filename().string().size() * 5.f; 
    pos.x += width / 2.f - p;
    pos.y += 12.f; 
    ImGui::SetCursorPos(pos);

    ImGui::TextUnformatted(current_file.path.filename().string().data());

    pos = ImGui::GetCursorPos();
    pos.y = height - height / 4.f;
    pos.x = width / 9.f;
    ImGui::SetCursorPos(pos);
    auto button_size = ImVec2(width / 3.f, height / 5.f);
    if (ImGui::Button("Удалить (Y)", button_size)) 
    { 
      show = false;
      delete_dialog = false;
      em->execute(types::event_type::DELETE_CURRENT_FILE, nullptr);
    }

    ImGui::SameLine(width / 1.8f);

    if (ImGui::Button("Отмена (n / Esc)", button_size))
      cancel();

    TR_POP_FONT();
  }

  void dialogs::draw_create_dialog()
  {
    TR_PUSH_FONT(MEDIUM, 18);
    std::string label = "Создание файла/директории!";

    // манипуляции с тем чтобы название стояло посередлине
    // см. и ниже тоже
    auto pos = ImGui::GetCursorPos();
    pos.x = width / (current_file.type == file_type::DIR ? 5.4f : 4.8f);
    pos.y += 12.f; 
    ImGui::SetCursorPos(pos);
    ImGui::TextUnformatted(label.data());
    ImGui::Separator();

    ImGui::PushItemWidth(-FLT_MIN - 10.f);
    pos = ImGui::GetCursorPos();
    pos.x = 10.f;
    ImGui::SetCursorPos(pos);
    // для фокусировки
    if (!ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)) ImGui::SetKeyboardFocusHere(0);
    if (ImGui::InputText("##new_file_title", &title)) {}

    ImGui::PopItemWidth();

    pos = ImGui::GetCursorPos();
    pos.y = height - height / 4.f;
    pos.x = width / 9.f;
    ImGui::SetCursorPos(pos);
    auto button_size = ImVec2(width / 3.f, height / 5.f);
    if (ImGui::Button("Создать (Enter)", button_size)) 
      create_file();

    ImGui::SameLine(width / 1.8f);

    if (ImGui::Button("Отмена (Esc)", button_size)) 
      cancel();

    TR_POP_FONT();
  }

  void dialogs::draw_rename_dialog()
  {
    TR_PUSH_FONT(MEDIUM, 18);
    std::string label = "Переименование файла/директории!";
    title = current_file.path.filename();

    // манипуляции с тем чтобы название стояло посередлине
    // см. и ниже тоже
    auto pos = ImGui::GetCursorPos();
    pos.x = width / (current_file.type == file_type::DIR ? 5.4f : 4.8f);
    pos.y += 12.f; 
    ImGui::SetCursorPos(pos);
    ImGui::TextUnformatted(label.data());
    ImGui::Separator();

    ImGui::PushItemWidth(-FLT_MIN - 10.f);
    pos = ImGui::GetCursorPos();
    pos.x = 10.f;
    ImGui::SetCursorPos(pos);
    // для фокусировки
    if (!ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)) ImGui::SetKeyboardFocusHere(0);
    if (ImGui::InputText("##new_file_title", &title)) {}

    ImGui::PopItemWidth();

    pos = ImGui::GetCursorPos();
    pos.y = height - height / 4.f;
    pos.x = width / 9.f;
    ImGui::SetCursorPos(pos);
    auto button_size = ImVec2(width / 3.f, height / 5.f);
    if (ImGui::Button("Переименовать (Enter)", button_size)) 
      rename();

    ImGui::SameLine(width / 1.8f);

    if (ImGui::Button("Отмена (Esc)", button_size)) 
      cancel();

    TR_POP_FONT();
  }

  void dialogs::draw_help_dialog()
  {
    height = try_engine::application::get()->get_window()->height() / 2.7f;

    TR_PUSH_FONT(MEDIUM, 16);

    std::string label = "Помощь";
    title = current_file.path.filename();

    // манипуляции с тем чтобы название стояло посередлине
    // см. и ниже тоже
    auto pos = ImGui::GetCursorPos();
    pos.x = width / 2.6f;
    pos.y += 12.f; 
    ImGui::SetCursorPos(pos);
    ImGui::TextUnformatted(label.data());

    ImGui::Separator();
    ImGui::TextUnformatted("Копирование: С / backspace");
    ImGui::TextUnformatted("Вставка: P");
    ImGui::TextUnformatted("Удаление: D");
    ImGui::TextUnformatted("Переименование: R");
    ImGui::TextUnformatted("Создание: A");

    ImGui::Separator();
    ImGui::TextUnformatted("Перемещение в начало: gg");
    ImGui::TextUnformatted("Перемещение в конец: G");

    ImGui::Separator();
    ImGui::TextUnformatted("Выход из помощи: F1");

    TR_POP_FONT();
  }
  void dialogs::create_file()
  {
    if (title.empty()) return;
    show = false;
    create_dialog = false;
    em->execute(types::event_type::CREATE_FILE, title);
    title.clear();
  }

  void dialogs::rename()
  {
    if (title.empty()) return;
    show = false;
    rename_dialog = false;
    em->execute(types::event_type::RENAME_FILE, current_file.path.parent_path() / title);
    title.clear();
  }

  void dialogs::cancel()
  {
    delete_dialog = false;
    create_dialog = false;
    rename_dialog = false;
    help_dialog = false;
    title.clear();
    show = false;
    height = try_engine::application::get()->get_window()->height() / 5.f;
    width = try_engine::application::get()->get_window()->width() / 3.2f;
    em->execute(types::event_type::UNFREEZE_BROWSER_ACTION, nullptr);
  }
}
