#include "client/updater/Updater.h"

#include "td/misc/Platform.h"
#include "td/misc/DataBuffer.h"
#include "td/misc/Log.h"
#include "td/misc/Format.h"

#include "td/network/HttpLib.h"

#ifdef _WIN32
#include <windows.h>
#include <cstdio>
#endif

namespace td {
namespace utils {

bool Updater::CheckUpdate() {
	httplib::Client client("thesims.freeboxos.fr", 30000);

	if (auto res = client.Get("/Tower%20Defense/version")) {

		std::string currentVersion = GetCurrentVersion();
		m_LastVersion = res.value().body;

		// we only look at the first line
		m_LastVersion = m_LastVersion.substr(0, m_LastVersion.find('\n'));

		utils::LOG(utils::format("Current version : [%s]", GetCurrentVersion().c_str()));
		utils::LOG(utils::format("Last version : [%s]", m_LastVersion.c_str()));

		if (currentVersion != m_LastVersion) {
			return true;
		}
		return false;
	} else {
		utils::LOGE(utils::format("Error code : %u", res.error()));
		return false;
	}

	return false;
}

bool Updater::CanUpdate() {
	return !GetDownloadFileURL().empty();
}

std::string Updater::GetDownloadFileURL() {
	Os systemOs = GetSystemOs();
	Architecture systemArch = GetSystemArchitecture();

	switch (systemOs) {

	case Os::Windows: {

			switch (systemArch) {
			case Architecture::x86_64:
				return "/Tower%20Defense/Tower%20Defense%20Windows%20(x86_64).exe";
			case Architecture::x86:
				return "/Tower%20Defense/Tower%20Defense%20Windows%20(x86).exe";
			default:
				return "";
			}

		}

	default: // not supported on Android and Linux (package managers are better)
		return "";
	}
}

std::string Updater::GetLocalFilePath() {
#ifdef _WIN32
	char filePathBuffer[1024];
	GetModuleFileName(nullptr, filePathBuffer, sizeof(filePathBuffer));

	std::string filePath = filePathBuffer;
	return filePath;
#endif
	return "";
}

void Updater::DownloadUpdate() {
	if (m_DownloadComplete) return;

	m_CancelDownload = false;

	std::string newFileUrl = GetDownloadFileURL();

	httplib::Client client("thesims.freeboxos.fr", 30000);

	httplib::ContentReceiver reciever = [&](const char* data, size_t data_length) {
		std::string fileData(data, data_length);
		m_FileBuffer << fileData;
		return true;
	};

	httplib::Progress progress = [&](uint64_t len, uint64_t total) {
		m_Progress = (float)len * 100.0f / total;
		return !m_CancelDownload;
	};

	auto res = client.Get(newFileUrl.c_str(), reciever, progress);

	if (!m_CancelDownload) {
		m_DownloadComplete = true;
	}
}

void Updater::RemoveOldFile() {
	std::remove(std::string(GetLocalFilePath() + "_old").c_str());
}

bool Updater::WriteFile() {
	if (m_FileWrited || !m_DownloadComplete) return false;

	if (!m_FileBuffer.WriteFile(GetLocalFilePath() + "_recent"))
		return false;

#ifdef _WIN32
	std::rename(GetLocalFilePath().c_str(), std::string(GetLocalFilePath() + "_old").c_str());
	std::rename(std::string(GetLocalFilePath() + "_recent").c_str(), GetLocalFilePath().c_str());
#endif

	m_FileWrited = true;
	m_DownloadComplete = false;

	ClearCache();

	return true;
}

} // namespace utils
} // namespace td
