#pragma once

/**
 * \file PlayerController.h
 * \brief File containing the blitz::input::PlayerController class.
 */

#include "blitz/common/Smoothing.h"
#include "blitz/game/Listeners.h"
#include "blitz/misc/ObjectNotifier.h"
#include "blitz/misc/Time.h"

namespace blitz {

class Client;

namespace game {

class Player;

}  // namespace game

namespace input {

/**
 * \brief Class that handles player input and sends it to the client.
 * \details This class is responsible for handling player input and sending it to the server.
 * It also handles the player's velocity and position.
 */
class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener>, game::ClientListener {
  private:
	game::Player* m_Player;
	Client* m_Client;
	utils::CooldownTimer<float> m_ShootTimer{1.0f};
	EMASmoother m_DxSmoother;
	EMASmoother m_DySmoother;
	// current (target) velocity
	Vec3f m_Velocity;
	/// maximum x-axis velocity
	Vec3f m_MaxVelocity;
	/// this is reset when the player touches the ground
	bool m_OnGround;

  public:
	/**
	 * \brief Default constructor
	 */
	PlayerController(Client* client);

	/**
	 * \brief Update things like player position and velocity.
	 */
	void Update(float delta);

	virtual void OnGameConfigUpdate() override;

	/**
	 * \brief Set the player that this controller is attached to.
	 * \param a_Player The player to attach to.
	 */
	void SetAttachedPlayer(game::Player* a_Player) {
		m_Player = a_Player;
	}

	/**
	 * \brief Get the player that this controller is attached to.
	 * \return The player that this controller is attached to.
	 */
	game::Player* GetAttachedPlayer() {
		return m_Player;
	}

  private:
	void UpdateShootTimer(int bpm);
	void MouseMotionEvent(int, int);
	void UpdatePosition(float delta);
};

}  // namespace input
}  // namespace blitz
