#pragma once

#ifndef __gx_mouse_h__
	#define __gx_mouse_h__

#include "foundation.h"

namespace Gx
{
	class Window;
	struct MouseEventArgs;

	struct MouseButtons
	{
		enum Enum
		{
			Left = 0,
			Right = 1,
			Middle = 2,
			XButton1 = 3,
			XButton2 = 4
		};
	};

	struct MousePoint
	{
		MousePoint(GxF32 x = 0.0f, GxF32 y = 0.0f) : x(x), y(y) { }

		GxF32 x, y;
	};

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

		/* sprawdzanie stanu przyciskow myszy */
		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];
		}

		void setPosition(const MousePoint& point);
		void setCursorVisible(bool isCursorVisible); // rename to: setCursorHiding()
		void setCursorClipping(bool enabledCursorClipping);
		void setCursorCentring(bool enabledCursorCentring);
		void setCursorSmoothing(bool enabledCursorSmoothing);

		MousePoint getPosition() const {
			return m_currentPosition;
		}

		GxF32 getPositionX() const {
			return m_currentPosition.x;
		}

		GxF32 getPositionY() const {
			return m_currentPosition.y;
		}

		MousePoint getRelativePosition() const {
			return m_relativePosition;
		}

		GxF32 getRelativePositionX() const {
			return m_relativePosition.x;
		}

		GxF32 getRelativePositionY() const {
			return m_relativePosition.y;
		}

		MousePoint getCenterPosition() const {
			return m_centerPosition;
		}

		GxF32 getCenterPositionX() const {
			return m_centerPosition.x;
		}

		GxF32 getCenterPositionY() const {
			return m_centerPosition.y;
		}

		void update();
		void attach(HWND windowHandle);
		void detach();

	protected:
		void performSmoothing(MousePoint& point);

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

		static const GxI32 historyBufferSize = 10;

		MousePoint	m_currentPosition;
		MousePoint	m_previousPosition;
		MousePoint	m_relativePosition;
		MousePoint	m_centerPosition;

		MousePoint	m_historyPositions[historyBufferSize];
		GxF32		m_weightModifier;

		bool	m_isCursorVisible;
		bool	m_enabledCursorClipping;
		bool	m_enabledCursorCentring;
		bool	m_enabledCursorSmoothing;

		bool*	m_currentButtonStates;
		bool*	m_previousButtonStates;

		HWND	m_windowHandle;
	};
}

#endif /* __gx_mouse_h__ */