#pragma once

#include "td/misc/DataBuffer.h"

#include <memory>

namespace td {
namespace protocol {

class PacketHandler;

enum class PacketType : std::uint8_t {
	// client --> server
	PlayerLogin = 0,
	SelectTeam,
	SendMobs,
	PlaceTower,

	// client <-- server
	PlayerJoin,
	PlayerLeave,
	WorldBeginData,
	WorldData,
	UpdateMoney,
	UpdateEXP,
	UpdateLobbyTime,
	UpdateGameState,
	PlayerList,
	ConnectionInfo,
	UpdatePlayerTeam,
	ServerTps,
	WorldAddTower,
	UpdateMobStates,
	UpdateCastleLife,
	SpawnMob,
	RemoveMob,

	// client <--> server
	KeepAlive,
	Disconnect,
	UpgradeTower,
	RemoveTower,
	PlayerBuyItem,
	PlayerBuyMobUpgrade,

	PACKET_COUNT
};

class Packet {
public:
	Packet() {}
	virtual ~Packet() {}

	virtual DataBuffer Serialize(bool packetID = true) const = 0;
	virtual void Deserialize(DataBuffer& data) = 0;
	virtual void Dispatch(PacketHandler* handler) const = 0;

	void WritePacketID(DataBuffer& data, bool packetID) const;

	virtual PacketType GetType() const = 0;
	std::uint8_t GetID() const { return static_cast<std::uint8_t>(GetType()); }
};

typedef std::unique_ptr<Packet> PacketPtr;

}  // namespace protocol
}  // namespace td