#ifndef CGAMEWINDOW_HPP
#define CGAMEWINDOW_HPP

#include "CWindow.hpp"
#include "../../Controller/Exception/CLibException.hpp"
#include "../../Controller/Exception/CLogicException.hpp"

#include <cstdlib>
#include <string>
#include <utility>
#include <exception>
#include <stdexcept>
#include <SDL.h>
#ifdef WIN32
    #include <SDL_Image.h>
#else
    #include <SDL_image.h>
#endif

/**
 * @file CGameWindow.hpp
 * @brief File of CGameWindow, a class reprensenting a OpenGL Window, using SDL2 lib.
 */

/**
 * @brief Class reprensenting a OpenGL Window, using SDL2 lib.
 */
class CGameWindow : public CWindow {
private:
	// Say if the mouse is grabbed.
	bool m_grabCursor;

	// Say if the mouse is in relative mode.
	bool m_relativeCursor;

	// The anti-aliasing.
	unsigned char m_msaa;

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

	/**
	 * @brief The default constructor, build a non visible window with size of widthxheight.
	 * @param[in] title The title of the window.
	 * @param[in] iconPath The iconPath of the window.
	 * @param[in] width The width of the window.
	 * @param[in] height The height of the window.
	 * @param[in] resizable The define the resizable property of the window.
	 * @param[in] fullscreen The define the fullscreen property of the window.
	 * @param[in] sdlFlags Allow to add SDL flags.
	 * @param[in] imageFlags Allow to add SDL_Image flags.
	 */
	CGameWindow(std::string title, std::string iconPath, unsigned int width, unsigned int height, bool resizable, bool fullscreen);

	CGameWindow(std::string title, SDL_Window* window);

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

	/**
	 * @brief Say if the mouse is grabbed.
	 * @return bool, a boolean which say the mouse grab status.
	 */
	bool isCursorGrabbed(void) const;

	/**
	 * @brief Set the mouse grab status.
	 * @param[in] newMouseGrab New value of mouse grab status.
	 */
	void setCursorGrabbed(bool newMouseGrab);

	/**
	 * @brief Say if the mouse is relative.
	 * @return bool, a boolean which say the mouse relative status.
	 */
	bool isCursorRelative(void) const;

	/**
	 * @brief Set the mouse relative status, if true, the cursor grabb is also forced to true if not.
	 * @param[in] newMouseRelative New value of mouse relative status.
	 */
	void setCursorRelative(bool newMouseRelative);

	/**
	 * @brief Get the MSAA value.
	 * @return unsigned char, the MSAA value.
	 */
	unsigned char getAntiAliasing(void) const;

	/**
	 * @brief Set the MSAA of the window.
	 * @param[in] newMsaa New value of MSAA, must be 2, 4, 8, 16.
	 * @post if newMsaa not equal 2, 4, 8, 16, the value is set to 0.
	 */
	void setAntiAliasing(unsigned char newMsaa);

	/**
	 * @brief Launched before the creation of the window, usefull for setting OpenGL attribute.
	 */
	virtual void preinitialization();

	/**
	 * @brief Launched after the creation of the window, usefull for setting others attribute.
	 */
	virtual void postinitialization();

	/**
	 * @brief Get the OpenGLContext of the window.
	 * @return SDL_GLContext the OpenGL context of the window, in SDL2 format, we need to destroy it after using, with SDL_GL_DeleteContext(SDL_GLContext);.
	 * @post Give a error if the window is not initialized.
	 */
	SDL_GLContext getOpenGLContext(void);
};

#endif