#include "client/ClientConnexion.h"

#include "blitz/misc/Format.h"
#include "blitz/misc/Log.h"
#include "blitz/misc/PrettyLog.h"
#include "blitz/protocol/packets/ChatPacket.h"
#include "blitz/protocol/packets/ConnexionInfoPacket.h"
#include "blitz/protocol/packets/DisconnectPacket.h"
#include "blitz/protocol/packets/KeepAlivePacket.h"
#include "blitz/protocol/packets/PlayerLoginPacket.h"
#include "client/Client.h"

namespace blitz {
namespace client {

static std::string PrintColoredText(const protocol::ColoredText& coloredText) {
	std::string text;
	for (const auto& part : coloredText) {
		text += utils::GetTextColor({static_cast<std::uint8_t>(part.color.r * 255), static_cast<std::uint8_t>(part.color.g * 255),
					static_cast<std::uint8_t>(part.color.b * 255)}) +
				part.text;
	}
	text += utils::GetTextColorReset();
	return text;
}

ClientConnexion::ClientConnexion(Client* client) : network::Connexion(&m_Dispatcher), m_Client(client) {
	RegisterHandlers();
}

ClientConnexion::~ClientConnexion() {
	GetDispatcher()->UnregisterHandler(this);
}

void ClientConnexion::RegisterHandlers() {
	GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this);
	GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
	GetDispatcher()->RegisterHandler(protocol::PacketType::Chat, this);
	GetDispatcher()->RegisterHandler(protocol::PacketType::ConnexionInfo, this);
}

bool ClientConnexion::Connect(const std::string& pseudo, const std::string& address, std::uint16_t port) {
	if (!Connexion::Connect(address, port))
		return false;

	m_PlayerName = pseudo;
	return true;
}

void ClientConnexion::HandlePacket(const protocol::ChatPacket* packet) {
	utils::LOG("[Chat] " + PrintColoredText(packet->GetMessage()));
	m_Client->ChatTextReceived(packet->GetMessage());
}

void ClientConnexion::HandlePacket(const protocol::DisconnectPacket* packet) {
	utils::LOG("[ClientConnexion] Disconnected ! Reason : " + packet->GetReason());
	m_Client->NotifyListeners(&game::ClientListener::OnGameLeave);
}

void ClientConnexion::HandlePacket(const protocol::KeepAlivePacket* packet) {
	protocol::KeepAlivePacket response(packet->GetAliveID());
	SendPacket(&response);
}

void ClientConnexion::HandlePacket(const protocol::ConnexionInfoPacket* packet) {
	m_PlayerID = packet->GetConnectionID();
	utils::LOGD("[ClientConnexion] Logging in with pseudo " + m_PlayerName + " ...");
	Login(m_PlayerName);
}

void ClientConnexion::Login(const std::string& pseudo) {
	protocol::PlayerLoginPacket packet(pseudo);
	SendPacket(&packet);
}

}  // namespace client
}  // namespace blitz
