#include "application/gui_application.h"
#include "localization.h"
#include "rd_log.h"

namespace crossdesk {

void GuiApplication::DrawConnectionStatusText(
    std::shared_ptr<RemoteSession> &props) {
  std::string text;
  switch (props->connection_status_.load()) {
  case ConnectionStatus::Disconnected:
    text = localization::p2p_disconnected[localization_language_index_];
    break;
  case ConnectionStatus::Failed:
    text = localization::p2p_failed[localization_language_index_];
    break;
  case ConnectionStatus::Closed:
    text = localization::p2p_closed[localization_language_index_];
    break;
  default:
    break;
  }

  if (!text.empty()) {
    ImVec2 size = ImGui::GetWindowSize();
    ImVec2 text_size = ImGui::CalcTextSize(text.c_str());
    ImGui::SetCursorPos(
        ImVec2((size.x - text_size.x) * 0.5f,
               (size.y - text_size.y - title_bar_height_) * 0.5f));
    ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.0f), "%s", text.c_str());
  }
}

void GuiApplication::DrawReceivingScreenText(
    std::shared_ptr<RemoteSession> &props) {
  if (!props->connection_established_ ||
      props->connection_status_.load() != ConnectionStatus::Connected) {
    return;
  }

  bool has_valid_frame = false;
  {
    std::lock_guard<std::mutex> lock(props->video_frame_mutex_);
    has_valid_frame = props->stream_texture_ != nullptr &&
                      props->video_width_ > 0 && props->video_height_ > 0 &&
                      props->front_frame_ && !props->front_frame_->empty();
  }

  if (has_valid_frame) {
    return;
  }

  const std::string &text =
      localization::receiving_screen[localization_language_index_];
  ImVec2 size = ImGui::GetWindowSize();
  ImVec2 text_size = ImGui::CalcTextSize(text.c_str());
  ImGui::SetCursorPos(
      ImVec2((size.x - text_size.x) * 0.5f, (size.y - text_size.y) * 0.5f));
  ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 0.92f), "%s", text.c_str());
}

void GuiApplication::CloseTab(decltype(remote_sessions_)::iterator &it) {
  // std::unique_lock lock(remote_sessions_mutex_);
  if (it != remote_sessions_.end()) {
    CloseRemoteSession(it->second);
    it = remote_sessions_.erase(it);
    if (remote_sessions_.empty()) {
      SDL_Event event;
      event.type = SDL_EVENT_QUIT;
      SDL_PushEvent(&event);
    }
  }
}

int GuiApplication::StreamWindow() {
  ImGui::SetNextWindowPos(
      ImVec2(0, fullscreen_button_pressed_ ? 0 : title_bar_height_),
      ImGuiCond_Always);
  ImGui::SetNextWindowSize(ImVec2(stream_window_width_, stream_window_height_),
                           ImGuiCond_Always);
  ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
  ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
  ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
  bool video_bg_opened = ImGui::Begin(
      "VideoBg", nullptr,
      ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
          ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoDocking);
  ImGui::PopStyleColor(2);
  ImGui::PopStyleVar();

  if (!video_bg_opened) {
    return 0;
  }

  ImGuiWindowFlags stream_window_flag =
      ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoDecoration |
      ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoMove;

  if (!fullscreen_button_pressed_) {
    ImGui::SetNextWindowPos(
        ImVec2(title_bar_button_width_ * 0.8f, title_bar_button_width_ * 0.1f),
        ImGuiCond_Always);
    ImGui::SetNextWindowSize(ImVec2(0, title_bar_button_width_ * 0.8f),
                             ImGuiCond_Always);
    ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
    ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
    ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0.0f));
    ImGui::Begin("TabBar", nullptr,
                 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration |
                     ImGuiWindowFlags_NoBringToFrontOnFocus |
                     ImGuiWindowFlags_NoDocking);
    ImGui::PopStyleColor();
    ImGui::PopStyleVar(2);

    if (ImGui::BeginTabBar("StreamTabBar",
                           ImGuiTabBarFlags_Reorderable |
                               ImGuiTabBarFlags_AutoSelectNewTabs)) {
      is_tab_bar_hovered_ = ImGui::IsWindowHovered();

      // std::shared_lock lock(remote_sessions_mutex_);
      for (auto it = remote_sessions_.begin();
           it != remote_sessions_.end();) {
        auto &props = it->second;
        if (!props->tab_opened_) {
          std::string remote_id_to_close = props->remote_id_;
          // lock.unlock();
          {
            // std::unique_lock unique_lock(remote_sessions_mutex_);
            auto close_it = remote_sessions_.find(remote_id_to_close);
            if (close_it != remote_sessions_.end()) {
              CloseTab(close_it);
            }
          }
          // lock.lock();
          it = remote_sessions_.begin();
          continue;
        }

        std::string tab_label =
            enable_srtp_
                ? std::string(ICON_FA_SHIELD_HALVED) + " " + props->remote_id_
                : props->remote_id_;
        if (ImGui::BeginTabItem(tab_label.c_str(), &props->tab_opened_)) {
          props->tab_selected_ = true;
          ImGui::SetWindowFontScale(0.6f);

          ImGui::SetNextWindowSize(
              ImVec2(stream_window_width_,
                     stream_window_height_ -
                         (fullscreen_button_pressed_ ? 0 : title_bar_height_)),
              ImGuiCond_Always);
          ImGui::SetNextWindowPos(
              ImVec2(0, fullscreen_button_pressed_ ? 0 : title_bar_height_),
              ImGuiCond_Always);
          ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
          ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
          ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0.0f));
          ImGui::Begin(props->remote_id_.c_str(), nullptr, stream_window_flag);
          ImGui::PopStyleColor();
          ImGui::PopStyleVar(2);

          ImVec2 pos = ImGui::GetWindowPos();
          ImVec2 size = ImGui::GetWindowSize();
          props->render_window_x_ = pos.x;
          props->render_window_y_ = pos.y;
          props->render_window_width_ = size.x;
          props->render_window_height_ = size.y;
          UpdateRenderRect();

          ControlWindow(props);

          // Show file transfer window if needed
          FileTransferWindow(props);

          DrawReceivingScreenText(props);

          focused_remote_id_ = props->remote_id_;

          if (!props->peer_) {
            std::string remote_id_to_erase = props->remote_id_;
            // lock.unlock();
            {
              // std::unique_lock unique_lock(remote_sessions_mutex_);
              auto erase_it = remote_sessions_.find(remote_id_to_erase);
              if (erase_it != remote_sessions_.end()) {
                // Ensure we flush pending STREAM_REFRESH_EVENT events and
                // clean up peer resources before erasing the entry, otherwise
                // SDL events may still hold raw pointers to freed
                // RemoteSession (including video_frame_mutex_),
                // leading to std::system_error when locking.
                CloseTab(erase_it);
              }
            }
            // lock.lock();
            ImGui::End();
            ImGui::EndTabItem();
            it = remote_sessions_.begin();
            continue;
          } else {
            DrawConnectionStatusText(props);
            ++it;
          }

          ImGui::End();
          ImGui::EndTabItem();
        } else {
          props->tab_selected_ = false;
          if (!props->tab_opened_) {
            std::string remote_id_to_close = props->remote_id_;
            // lock.unlock();
            {
              // std::unique_lock unique_lock(remote_sessions_mutex_);
              auto close_it = remote_sessions_.find(remote_id_to_close);
              if (close_it != remote_sessions_.end()) {
                CloseTab(close_it);
              }
            }
            // lock.lock();
            it = remote_sessions_.begin();
            continue;
          }
          ++it;
        }
      }

      ImGui::EndTabBar();
    }

    ImGui::End(); // End TabBar
  } else {
    // std::shared_lock lock(remote_sessions_mutex_);
    for (auto it = remote_sessions_.begin();
         it != remote_sessions_.end();) {
      auto &props = it->second;
      if (!props->tab_opened_) {
        std::string remote_id_to_close = props->remote_id_;
        // lock.unlock();
        {
          // std::unique_lock unique_lock(remote_sessions_mutex_);
          auto close_it = remote_sessions_.find(remote_id_to_close);
          if (close_it != remote_sessions_.end()) {
            CloseTab(close_it);
          }
        }
        // lock.lock();
        it = remote_sessions_.begin();
        continue;
      }

      if (props->tab_selected_) {
        ImGui::SetNextWindowSize(
            ImVec2(stream_window_width_,
                   stream_window_height_ -
                       (fullscreen_button_pressed_ ? 0 : title_bar_height_)),
            ImGuiCond_Always);
        ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
        ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
        ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0.0f));
        ImGui::Begin(props->remote_id_.c_str(), nullptr, stream_window_flag);
        ImGui::PopStyleColor();
        ImGui::PopStyleVar(2);

        ImVec2 pos = ImGui::GetWindowPos();
        ImVec2 size = ImGui::GetWindowSize();
        props->render_window_x_ = pos.x;
        props->render_window_y_ = pos.y;
        props->render_window_width_ = size.x;
        props->render_window_height_ = size.y;
        UpdateRenderRect();

        ControlWindow(props);

        // Show file transfer window if needed
        FileTransferWindow(props);

        DrawReceivingScreenText(props);

        ImGui::End();

        if (!props->peer_) {
          fullscreen_button_pressed_ = false;
          SDL_SetWindowFullscreen(stream_window_, false);
          std::string remote_id_to_erase = props->remote_id_;
          // lock.unlock();
          {
            // std::unique_lock unique_lock(remote_sessions_mutex_);
            auto erase_it = remote_sessions_.find(remote_id_to_erase);
            if (erase_it != remote_sessions_.end()) {
              CloseTab(erase_it);
            }
          }
          // lock.lock();
          it = remote_sessions_.begin();
          continue;
        } else {
          DrawConnectionStatusText(props);
          ++it;
        }
      } else {
        ++it;
      }
    }
  }

  // UpdateRenderRect();
  ImGui::End(); // End VideoBg

  return 0;
}
} // namespace crossdesk