#include "td/protocol/PacketFactory.h"
#include "td/protocol/Packets.h"
#include <map>
#include <functional>

namespace td {
namespace protocol {
namespace PacketFactory {

using PacketCreator = std::function<PacketPtr()>;

static std::map<PacketType, PacketCreator> packets = {
	{PacketType::PlayerLogin,           []() -> PacketPtr {return std::make_unique<PlayerLoginPacket>();} },
	{PacketType::WorldBeginData,        []() -> PacketPtr {return std::make_unique<WorldBeginDataPacket>();} },
	{PacketType::WorldData,             []() -> PacketPtr {return std::make_unique<WorldDataPacket>();} },
	{PacketType::KeepAlive,             []() -> PacketPtr {return std::make_unique<KeepAlivePacket>();} },
	{PacketType::UpdateMoney,           []() -> PacketPtr {return std::make_unique<UpdateMoneyPacket>();} },
	{PacketType::UpdateEXP,             []() -> PacketPtr {return std::make_unique<UpdateExpPacket>();} },
	{PacketType::UpdateLobbyTime,       []() -> PacketPtr {return std::make_unique<UpdateLobbyTimePacket>(); } },
	{PacketType::UpdateGameState,       []() -> PacketPtr {return std::make_unique<UpdateGameStatePacket>(); } },
	{PacketType::PlayerList,            []() -> PacketPtr {return std::make_unique<PlayerListPacket>(); } },
	{PacketType::PlayerJoin,            []() -> PacketPtr {return std::make_unique<PlayerJoinPacket>(); } },
	{PacketType::PlayerLeave,           []() -> PacketPtr {return std::make_unique<PlayerLeavePacket>(); } },
	{PacketType::ConnectionInfo,        []() -> PacketPtr {return std::make_unique<ConnexionInfoPacket>(); } },
	{PacketType::SelectTeam,            []() -> PacketPtr {return std::make_unique<SelectTeamPacket>(); } },
	{PacketType::UpdatePlayerTeam,      []() -> PacketPtr {return std::make_unique<UpdatePlayerTeamPacket>(); } },
	{PacketType::Disconnect,            []() -> PacketPtr {return std::make_unique<DisconnectPacket>(); } },
	{PacketType::ServerTps,             []() -> PacketPtr {return std::make_unique<ServerTpsPacket>(); } },
	{PacketType::SpawnMob,              []() -> PacketPtr {return std::make_unique<SpawnMobPacket>(); } },
	{PacketType::PlaceTower,            []() -> PacketPtr {return std::make_unique<PlaceTowerPacket>(); } },
	{PacketType::WorldAddTower,         []() -> PacketPtr {return std::make_unique<WorldAddTowerPacket>(); } },
	{PacketType::RemoveTower,           []() -> PacketPtr {return std::make_unique<RemoveTowerPacket>(); } },
	{PacketType::SendMobs,              []() -> PacketPtr {return std::make_unique<SendMobsPacket>(); } },
	{PacketType::UpgradeTower,          []() -> PacketPtr {return std::make_unique<UpgradeTowerPacket>(); } },
	{PacketType::UpdateCastleLife,      []() -> PacketPtr {return std::make_unique<UpdateCastleLifePacket>(); } },
	{PacketType::UpdateMobStates,       []() -> PacketPtr {return std::make_unique<UpdateMobStatesPacket>(); } },
	{PacketType::PlayerBuyItem,         []() -> PacketPtr {return std::make_unique<PlayerBuyItemPacket>(); } },
	{PacketType::PlayerBuyMobUpgrade,   []() -> PacketPtr {return std::make_unique<PlayerBuyMobUpgradePacket>(); } },
	{PacketType::RemoveMob,           	[]() -> PacketPtr {return std::make_unique<RemoveMobPacket>(); } },
};

PacketPtr CreatePacket(PacketType type, DataBuffer& buffer) {
	PacketPtr packet = packets[type]();
	packet->Deserialize(buffer);
	return packet;
}

}
} // namespace protocol
} // namespace td
