#ifndef __gxframework_mouse_h__
	#define __gxframework_mouse_h__

#include "window.h"

namespace Gx
{
	namespace MouseButtons
	{
		enum Enum
		{
			Left = 0,
			Right = 1,
			Middle = 2
		};
	}

	class GXFRAMEWORK_DECLSPEC Mouse
	{
	public:
		static Mouse& getInstance();

		bool isButtonDown(MouseButtons::Enum button) const {
			return m_currentButtonStates[button];
		}

		bool isButtonPressed(MouseButtons::Enum button) const {
			return m_currentButtonStates[button] && !m_previousButtonStates[button];
		}

		bool isButtonUp(MouseButtons::Enum button) const {
			return !m_currentButtonStates[button];
		}

		bool isCursorVisible() const {
			return m_isCursorVisible;
		}

		int getAbsolutePosX() const {
			return m_absolutePosX;
		}

		int getAbsolutePosY() const {
			return m_absolutePosY;
		}

		float getRelativePosX() const {
			return m_relativePosX;
		}

		float getRelativePosY() const {
			return m_relativePosY;
		}

		float getWheelPos() const {
			return m_wheelPos;
		}

		bool attach(Window::Handle windowHandle);
		void detach();

		void handleMessage(UINT msg, WPARAM wParam, LPARAM lParam);

		void hideCursor();
		void showCursor();

		void setPosition(int x, int y);

		void update();

	private:
		Mouse();
		Mouse(const Mouse&);
		Mouse& operator=(const Mouse&);

		Window::Handle m_windowHandle;
		int m_absolutePosX;
		int m_absolutePosY;
		int m_mouseIndex;
		int m_wheelDelta;
		int m_previousWheelDelta;
		float m_wheelPos;
		float m_relativePosX;
		float m_relativePosY;
		float m_mouseMovementX[2];
		float m_mouseMovementY[2];
		bool m_isCursorVisible;
		bool m_buttonStates[2][3];
		bool* m_currentButtonStates;
		bool* m_previousButtonStates;
	};
}

#endif // ~__gxframework_mouse_h__
