#pragma once
#include <queue>

class Mouse
{
public:
	class MouseEvent
	{
	public:
		enum class Type
		{
			LClick,
			LRelease,
			RClick,
			RRelease,
			//WheelUp,
			//WheelDown,
			Wheel,
			Move,
			Enter,
			Leave,
			Invalid
		};
	public:
		MouseEvent()
			:
			type(Type::Invalid),
			isLeftClicked(false),
			isRightClicked(false),
			x(0),
			y(0)
		{}

		MouseEvent(Type type, const Mouse& parent)
			:
			type(type),
			isLeftClicked(parent.isLeftClicked),
			isRightClicked(parent.isRightClicked),
			x(parent.x),
			y(parent.y)
		{}

		bool isValid()
		{
			return (type != Type::Invalid);
		}

		Type GetType()
		{
			return type;
		}

		int GetX()
		{
			return x;
		}

		int GetY()
		{
			return y;
		}

		bool IsLeftClicked()
		{
			return isLeftClicked;
		}

		bool IsRightClicked()
		{
			return isRightClicked;
		}
	private:
		Type type;
		int x;
		int y;
		bool isLeftClicked;
		bool isRightClicked;
	};

public:
	Mouse();

	int GetX();
	int GetY();
	bool IsLeftClicked();
	bool IsRightClicked();
	int GetLeftClickAtX();
	int GetLeftClickAtY();
	int GetRightClickAtX();
	int GetRightClickAtY();
	int GetRightDragDeltaX();
	int GetRightDragDeltaY();
	int GetWheelDelta();

	void OnMouseMove(int newX, int newY);
	void OnLeftClick(int newX, int newY);
	void OnleftRelease(int newX, int newY);
	void OnRightClick(int newX, int newY);
	void OnRightRelease(int newX, int newY);
	void OnWheelDelta(int x, int y, int delta);
	//void OnWheelUp(int x, int y);
	//void OnWheelDown(int x, int y);

	Mouse::MouseEvent ReadEvent();
	void TrimEvents();

	bool IsQueueEmpty();

private:
	int x;
	int y;
	bool isLeftClicked;
	bool isRightClicked;
	int leftClickAtX;
	int leftClickAtY;
	int rightClickAtX;
	int rightClickAtY;
	int rightDragDeltaX;
	int rightDragDeltaY;
	int wheelDelta;

	static constexpr unsigned int bufferSize = 16u;

	std::queue<MouseEvent> mouseEvents;
};