#pragma once

/**
 * \file ServerGame.h
 * \brief File containing the blitz::server::ServerGame class
 */

#include "blitz/game/Game.h"

namespace blitz {
namespace server {

/**
 * \struct ServerDuration
 * \brief Structure containing the server game durations
 * \var ServerDuration::m_GameDuration The game duration
 * \var ServerDuration::m_PrepDuration The preparation duration
 * \var ServerDuration::m_EndDuration The end duration
 */
struct ServerDuration {
	std::uint64_t m_GameDuration = 1000 * 3 * 60;
	std::uint64_t m_PrepDuration = 1000 * 10;
	std::uint64_t m_EndDuration = 1000 * 30;
};

class Server;

/**
 * \class ServerGame
 * \brief Class used to manage the server game
 */
class ServerGame : public game::Game {
  private:
	Server* m_Server;
	utils::Timer m_PositionTimer;
	ServerDuration m_ServerDuration;

  public:
	/**
	 * \brief Constructor
	 * \param server The server
	 */
	ServerGame(Server* server);
	virtual ~ServerGame();

	/**
	 * \brief Process a player shoot
	 * \param player The player
	 * \param position The position of the player
	 * \param yaw The yaw
	 * \param pitch The pitch
	 */
	void ProcessShoot(game::PlayerID player, Vec3f position, float yaw, float pitch);

	/**
	 * \brief Process a player login
	 * \param player The player
	 * \param name The name of the player
	 */
	void AddPlayer(game::PlayerID player, const std::string& name) override;
	/**
	 * \brief Remove a player from the game if he disconnected
	 */
	void RemovePlayer(game::PlayerID player) override;

	/**
	 * \brief Update the game
	 * \param delta The delta time in milliseconds
	 */
	void Tick(std::uint64_t delta) override;

	/**
	 * \brief Set the game state
	 * \param gameState The game state
	 * \param duration The duration in milliseconds
	 */
	void SetGameState(game::GameState gameState, std::uint64_t duration);

	/**
	 * \brief Get the server duration
	 * \return The server duration in milliseconds
	 */
	ServerDuration& GetServerDuration() {
		return m_ServerDuration;
	}

	/**
	 * \brief Send the player positions
	 */
	void SendServerConfig();

  private:
	void SendPlayerPositions();
	void DamagePlayer(game::Player& player, game::Player& shooter);
	void UpdateHP(game::Player& player, float newHP);
	void UpdatePlayerStats();
	void StartGame();	// when at least 2 players joined
	void CancelGame();	// when not enough players are left
	void ResetPlayerStats();
};

}  // namespace server
}  // namespace blitz
