#pragma once

#include "client/ClientConnexion.h"
#include "client/game/ClientGame.h"

#include "td/game/Team.h"
#include "td/game/Player.h"

#include "td/protocol/Protocol.h"
#include "td/protocol/packets/SendMobsPacket.h"

#include "client/render/Renderer.h"

#include "td/network/Network.h"

namespace td {
namespace client {

class Client {
private:
	render::Renderer* m_Renderer;
	ClientConnexion m_Connexion;
	std::unique_ptr<ClientGame> m_Game;
	bool m_Connected;
public:
	Client(render::Renderer* renderer) : m_Renderer(renderer), m_Game(std::make_unique<ClientGame>(this)), m_Connected(false) {}

	const ClientGame& GetGame() const { return *m_Game; }
	const ClientConnexion& GetConnexion() const { return m_Connexion; }
	render::Renderer* GetRenderer() const { return m_Renderer; }

	ClientGame& GetGame() { return *m_Game; }
	ClientConnexion& GetConnexion() { return m_Connexion; }

	const game::Player* GetPlayer() { return m_Game->GetPlayer(); }

	void Tick(std::uint64_t delta);

	void Render();

	bool Connect(const network::IPAddresses& addresses, std::uint16_t port);
	void CloseConnection();

	bool IsConnected() const { return m_Connexion.GetSocketStatus() == network::Socket::Connected; }

	void SelectTeam(game::TeamColor team);
	void SendMobs(const std::vector<protocol::MobSend>& mobSends);
	void PlaceTower(game::TowerType type, const Vec2f& position);
	void UpgradeTower(game::TowerID tower, game::TowerLevel level);
	void RemoveTower(game::TowerID tower);
private:
	void Reset();
};

} // namespace client
} // namespace td
