#include "client/render/gui/UpdateMenu.h"

#include "client/updater/Updater.h"

#include "client/render/gui/imgui/imgui.h"

#include <chrono>

namespace td {
namespace gui {

UpdateMenu::UpdateMenu(client::Client* client) : GuiWidget(client), m_Opened(true), m_Updater(std::make_unique<utils::Updater>()) {
	CheckUpdates();
}

UpdateMenu::~UpdateMenu() {}

void UpdateMenu::Render() {
	RenderErrorPopup();
	if (m_Opened) {
		ImGui::Begin("Updater", &m_Opened);
		if (IsUpdateChecked()) {

			bool updateAvailable = m_UpdateAvailable.get();
			if (updateAvailable) {

				if (m_Updater->IsFileWrited()) {
					ImGui::Text("The update is now installed");
					ImGui::Text("The game needs to be restarted");
				} else if (m_Updater->IsDownloadComplete()) {
					ImGui::Text("Download done!");
					if (ImGui::Button("Install")) {
						if (!m_Updater->WriteFile()) {
							m_Error = "Failed to write file !\n";
							ImGui::OpenPopup("UpdateError");
						}
					}
					if (ImGui::Button("Cancel")) {
						m_Updater->CancelDownload();
						m_Updater->ClearCache();
					}
				} else {
					if (m_Updater->GetDownloadProgress() > 0) {
						ImGui::Text("Downloading ...");
						ImGui::ProgressBar(m_Updater->GetDownloadProgress());
						if (ImGui::Button("Cancel")) {
							m_Updater->CancelDownload();
						}
					} else {
						ImGui::Text("An update is available!");
						ImGui::Separator();
						ImGui::Text("Current version : %s", m_Updater->GetCurrentVersion().c_str());
						ImGui::Text("Last version : %s", m_Updater->GetLastVersion().c_str());

						bool canDownloadFile = m_Updater->CanUpdate();

						if (!canDownloadFile) ImGui::BeginDisabled();

						if (ImGui::Button("Download")) {
							m_Updater->DownloadUpdate();
						}

						if (!canDownloadFile) ImGui::EndDisabled();

						ImGui::SameLine();
						if (ImGui::Button("Cancel")) {
							m_Opened = false;
						}
					}
				}
			} else {
				ImGui::Text("No update available!");
				ImGui::Separator();
				ImGui::Text("Current version : %s", m_Updater->GetCurrentVersion().c_str());
				ImGui::Text("Last version : %s", m_Updater->GetLastVersion().c_str());
			}
		} else {
			ImGui::Text("Checking updates ...");
		}
		ImGui::End();
	}
}

void UpdateMenu::RenderErrorPopup() {
	if (ImGui::BeginPopup("UpdateError")) {
		ImGui::Text("Error : %s", m_Error.c_str());
		ImGui::EndPopup();
	}
}

bool UpdateMenu::IsUpdateChecked() {
	return m_UpdateAvailable.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}

void UpdateMenu::CheckUpdates() {
	m_UpdateAvailable = std::async(std::launch::async, [&]() { return m_Updater->CheckUpdate();});
}

} // namespace gui
} // namespace td
