#include "AuthUtils.h"
#include "Client.h"

#include "Datas/UserDatas.h"
#include "Utils/ChatUtils.h"

auto Utils::Auth::start() -> bool {

	WSAData wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		return false;
	}

	clientsocket = socket(AF_INET, SOCK_STREAM, 0);
	if (clientsocket == INVALID_SOCKET) {
		WSACleanup();

		return false;
	}

	struct addrinfo hints, * res;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;

	if (getaddrinfo(_("www.valkyrieclient.xyz"), _("8080"), &hints, &res) != 0) {
		if (getaddrinfo(_("valkyrieclient.ddns.net"), _("8080"), &hints, &res) != 0) {
			return false;
		}
	}

	sockaddr_in hint;
	hint.sin_family = AF_INET;
	hint.sin_port = htons(8080);
	hint.sin_addr = ((sockaddr_in*)res->ai_addr)->sin_addr;

	if (connect(clientsocket, (sockaddr*)&hint, sizeof(hint)) == SOCKET_ERROR) {
		hint.sin_addr.s_addr = inet_addr(_("192.168.1.80"));
		if (connect(clientsocket, (sockaddr*)&hint, sizeof(hint)) == SOCKET_ERROR) {
			return false;
		}
		else {
			local = true;
			Client::notifications.push_back({ _("Information"), _("Running on local."), 5.f, 10.f });
			return true;
		}

		closesocket(clientsocket);
		WSACleanup();

		return false;
	}

	return true;
}

auto Utils::Auth::end() -> void {
	closesocket(clientsocket);
	WSACleanup();
}

auto Utils::Auth::login(std::string token, std::string key, std::string username) -> bool {
	nlohmann::json js = {
		{_("type"), _("login")},
		{_("token"), token},
		{_("key"), key},
		{_("username"), username}
	};

	std::string jsstr = js.dump();

	send(clientsocket, jsstr.c_str(), jsstr.length(), 0);

	char buffer[1024];
	int received = recv(clientsocket, buffer, sizeof(buffer), 0);
	if (received > 0) {
		std::string response(buffer, received);
		nlohmann::json received = nlohmann::json::parse(response);

		if (received.contains(_("status")) && received[_("status")] == _("success")) {
			Datas::User::name = received[_("username")];
			Datas::User::role = received[_("role")];
			Utils::Chat::display(_("You have been authenticated as ") + Datas::User::name);
			return true;
		}
	}

	return false;
}

auto Utils::Auth::create(std::string token, std::string key, std::string username) -> bool {
	end();
	start();

	nlohmann::json js = {
		{_("type"), _("register")},
		{_("token"), token},
		{_("username"), username},
		{_("key"), key}
	};

	std::string jsstr = js.dump();

	send(clientsocket, jsstr.c_str(), jsstr.length(), 0);

	char buffer[1024];
	int received = recv(clientsocket, buffer, sizeof(buffer), 0);
	if (received > 0) {
		std::string response(buffer, received);
		nlohmann::json received = nlohmann::json::parse(response);

		if (received.contains(_("status")) && received[_("status")] == _("success")) {
			return true;
		}
		else if (received[_("status")] == _("username")) {
			laststatus = 1;
		}
	}

	return false;
}

auto Utils::Auth::readfile(std::string path) -> bool {
	std::ifstream file(path);
	nlohmann::json j;

	if (file.is_open()) {
		file >> j;
	}

	if (j.contains(_("key"))) {
		Datas::User::FileInfo::u_key = j[_("key")].get<std::string>();
		Datas::User::FileInfo::u_name = j[_("username")].get<std::string>();
	}
	else {
		j[_("key")] = _("Your key");
		j[_("username")] = _("Your username");

		std::ofstream ofile(path);
		ofile << j.dump(4);

		return false;
	}

	return true;
}
