#pragma once

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

namespace td {
namespace game {

enum class GameState : std::uint8_t {
	Lobby,
	Game,
	EndGame,
	Disconnected,
	Closed
};

typedef std::map<std::uint8_t, Player> PlayerList;

class GameListener {
public:
	virtual void OnPlayerJoin(PlayerID player) {}
	virtual void OnPlayerLeave(PlayerID player) {}

	virtual void OnGameStateUpdate(GameState newState) {}
	virtual void OnGameBegin() {}
	virtual void OnGameEnd() {}
	virtual void OnGameClose() {}
};

typedef utils::ObjectNotifier<GameListener> GameNotifier;

class Game : public GameNotifier {
protected:
	World* m_World;
	TeamList m_Teams = { Team{TeamColor::Red}, Team{TeamColor::Blue} };
	GameState m_GameState = GameState::Lobby;
	PlayerList m_Players;
public:
	Game(World* world);
	virtual ~Game();

	virtual void Tick(std::uint64_t delta);

	virtual void Reset();

	Team& GetRedTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }
	const Team& GetRedTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }

	Team& GetBlueTeam() { return m_Teams[static_cast<std::uint8_t>(TeamColor::Blue)]; }
	const Team& GetBlueTeam() const { return m_Teams[static_cast<std::uint8_t>(TeamColor::Red)]; }

	Team& GetTeam(TeamColor team) { return m_Teams[static_cast<std::uint8_t>(team)]; }
	const Team& GetTeam(TeamColor team) const { return m_Teams[static_cast<std::uint8_t>(team)]; }

	GameState GetGameState() const { return m_GameState; }
	void SetGameState(GameState gameState) { m_GameState = gameState; };

	const World* GetWorld() const { return m_World; }
	World* GetWorld() { return m_World; }

	const PlayerList& GetPlayers() const { return m_Players; }
	PlayerList& GetPlayers() { return m_Players; }

	const Player* GetPlayerById(PlayerID id) const;
	Player* GetPlayerById(PlayerID id);

	const TeamList& GetTeams() const { return m_Teams; }

	void RemovePlayer(PlayerID pId);

};

} // namespace game 
} // namespace td
