#pragma once

/**
 * \file Player.h
 * \brief File containing the blitz::game::Player class
 */

#include "blitz/common/Defines.h"
#include "blitz/maths/Vector.h"
#include <cstdint>
#include <string>

namespace blitz {
namespace game {

/**
 * \struct PlayerStats
 * \brief The statistics of a player
 */
struct PlayerStats {
	/**
	 * \brief The number of deaths
	 */
	std::uint16_t m_Deaths;
	/**
	 * \brief The number of kills
	 */
	std::uint16_t m_Kills;
	/**
	 * \brief The number of shots
	 */
	std::uint32_t m_ShootCount;
	/**
	 * \brief The number of successful shots
	 */
	std::uint32_t m_ShootSuccessCount;
};

/**
 * \class Player
 * \brief The player of the game
 */
class Player {
  private:
	PlayerID m_ID;
	std::string m_Name;
	Vec3f m_Position;
	Vec3f m_Velocity;
	float m_Yaw;
	float m_Pitch;
	float m_HP;
	bool m_IsBot;
	PlayerStats m_Stats{};

  public:
	/**
	 * \brief Default constructor
	 * \param id The ID of the player
	 */
	Player(PlayerID id) : m_ID(id), m_Yaw(0), m_Pitch(0), m_HP(100), m_IsBot(false) {}

	/**
	 * \brief Get the ID of the player
	 * \return The ID of the player
	 */
	PlayerID GetID() const {
		return m_ID;
	}

	/**
	 * \brief Get the name of the player
	 * \return The name of the player
	 */
	const std::string& GetName() const {
		return m_Name;
	}

	/**
	 * \brief Set the name of the player
	 * \param name The name of the player
	 */
	void SetName(const std::string& name) {
		m_Name = name;
	}

	/**
	 * \brief Get the position of the player
	 * \return The position of the player
	 */
	const Vec3f& GetPosition() const {
		return m_Position;
	}

	/**
	 * \brief Set the position of the player
	 * \param newPos The new position of the player
	 */
	void SetPosition(const Vec3f& newPos) {
		m_Position = newPos;
	}

	/**
	 * \brief Add a position to the player
	 * \param dPos The position to add
	 */
	void AddPosition(const Vec3f& dPos) {
		m_Position += dPos;
	}

	/**
	 * \brief Get the velocity of the player
	 * \return The velocity of the player
	 */
	const Vec3f& GetVelocity() const {
		return m_Velocity;
	}

	/**
	 * \brief Set the velocity of the player
	 * \param newVelocity The new velocity of the player
	 */
	void SetVelocity(const Vec3f& newVelocity) {
		m_Velocity = newVelocity;
	}

	/**
	 * \brief Get the yaw of the player
	 * \return The yaw of the player in radians
	 */
	float GetYaw() const {
		return m_Yaw;
	}

	/**
	 * \brief Set the yaw of the player
	 * \param yaw The yaw of the player in radians
	 */
	void SetYaw(float yaw) {
		m_Yaw = yaw;
	}

	/**
	 * \brief Add a yaw to the player
	 * \param dYaw The yaw to add in radians
	 */
	void AddYaw(float dYaw) {
		m_Yaw += dYaw;
	}

	/**
	 * \brief Get the pitch of the player
	 * \return The pitch of the player in radians
	 */
	float GetPitch() const {
		return m_Pitch;
	}

	/**
	 * \brief Set the pitch of the player
	 * \param pitch The pitch of the player in radians
	 */
	void SetPitch(float pitch) {
		m_Pitch = pitch;
	}

	/**
	 * \brief Add a pitch to the player
	 * \param dPitch The pitch to add in radians
	 */
	void AddPitch(float dPitch) {
		m_Pitch += dPitch;
	}

	/**
	 * \brief Get the HP of the player
	 * \return The HP of the player
	 */
	float GetHP() const {
		return m_HP;
	}

	/**
	 * \brief Set the HP of the player
	 * \param hp The HP of the player
	 */
	void SetHP(float hp) {
		m_HP = hp;
	}

	/**
	 * \brief When the player is a bot
	 * \return True if the player is a bot
	 */
	bool IsBot() const {
		return m_IsBot;
	}

	/**
	 * \brief Set the player as a bot
	 */
	void SetBot() {
		m_IsBot = true;
	}

	/**
	 * \brief Get the statistics of the player (const version)
	 * \return The statistics of the player
	 */
	const PlayerStats& GetStats() const {
		return m_Stats;
	}

	/**
	 * \brief Get the statistics of the player
	 * \return The statistics of the player
	 */
	PlayerStats& GetStats() {
		return m_Stats;
	}
};


}  // namespace game
}  // namespace blitz
