#ifndef CINPUT_HPP
#define CINPUT_HPP

#include "../../Model/Input/CMouse.hpp"
#include "../../Model/Input/CKeyboard.hpp"
#include "../../Model/Input/CController.hpp"
#include "../Exception/CException.hpp"
#include "../../Model/Observer/CKeyObserver.hpp"
#include "../Exception/CExceptionManager.hpp"
#include "../CKernel.fwd.hpp"

#include <SDL.h>
#include <utility>
#include <map>

/**
 * @file CInput.hpp
 * @brief file of the CInput class, class to handle all input event.
 */

/**
 * @brief Class to handle all input event.
 */
class CInput : public CKeyObserver {
private:
	// A pointer to the game.
	CKernel* m_kernel;

	// The event handler.
	SDL_Event m_event;

	// The mouse model.
	CMouse m_mouse;

	// The keyboard model.
	CKeyboard m_keyboard;

	// The controllers model, sorted by id.
	std::map<unsigned int, CController*> m_controllers;

public:
	CInput(void) = delete;
	CInput(const CInput& param) = delete;
	CInput& operator=(const CInput& param) = delete;

	/**
	 * @brief The usage constructor.
	 * @param[in] game A pointer to the game object, to handle specific event, like quit.
	 */
	CInput(CKernel* game);

	/**
	 * @brief The destructor.
	 */
	~CInput(void);

	/**
	 * @brief Function to handle all event of the game, SDL and CGame must be initialized. This function is call once per game frame.
	 */
	void updateEvent(void);

	/**
	 * @brief The keyboard getter.
	 * @return CKeyboard*, The keyboard.
	 */
	CKeyboard* getKeyboard(void);

	/**
	 * @brief The mouse getter.
	 * @return CMouse*, The mouse.
	 */
	CMouse* getMouse(void);

	/**
	 * @brief The controller getter.
	 * @param[in] id The id of the wanted controller.
	 * @return CController*, The controller.
	 */
	CController* getController(unsigned int id);

	/**
	 * @brief The controllers getter.
	 * @return std::map<unsigned int, CController*>, All the controllers, ordered by id.
	 */
	std::map<unsigned int, CController*> getControllers(void);

	/**
	 * @brief Handle key down event.
	 * @param[in] which The code of the key.
	 */
	virtual void onKKeyDown(unsigned int which);

	/**
	 * @brief Handle key down event.
	 * @param[in] which The code of the key.
	 */
	virtual void onKKeyUp(unsigned int which);
};

#endif