#pragma once

#ifndef __gx_keyboard_h__
	#define __gx_keyboard_h__

#include "foundation.h"

namespace Gx
{
	namespace Keys
	{
		enum Enum
		{
			D0               = 48,
			D1               = 49,
			D2               = 50,
			D3               = 51,
			D4               = 52,
			D5               = 53,
			D6               = 54,
			D7               = 55,
			D8               = 56,
			D9               = 57,

			A               = 65,
			B               = 66,
			C               = 67,
			D               = 68,
			E               = 69,
			F               = 70,
			G               = 71,
			H               = 72,
			I               = 73,
			J               = 74,
			K               = 75,
			L               = 76,
			M               = 77,
			N               = 78,
			O               = 79,
			P               = 80,
			Q               = 81,
			R               = 82,
			S               = 83,
			T               = 84,
			U               = 85,
			V               = 86,
			W               = 87,
			X               = 88,
			Y               = 89,
			Z               = 90,

			F1              = VK_F1,
			F2              = VK_F2,
			F3              = VK_F3,
			F4              = VK_F4,
			F5              = VK_F5,
			F6              = VK_F6,
			F7              = VK_F7,
			F8              = VK_F8,
			F9              = VK_F9,
			F10             = VK_F10,
			F11             = VK_F11,
			F12             = VK_F12,

			BackSpace       = VK_BACK,
			Tab             = VK_TAB,
			Enter           = VK_RETURN,
			CapsLock        = VK_CAPITAL,
			Escape          = VK_ESCAPE,
			Space           = VK_SPACE,
			Apps            = VK_APPS,
			Semicolon       = VK_OEM_1, // ';:'
			Add             = VK_OEM_PLUS,
			Comma           = VK_OEM_COMMA,
			Subtract        = VK_OEM_MINUS,
			Period          = VK_OEM_PERIOD, // '.'
			FwdSlash        = VK_OEM_2, // '/?'
			Tilde           = VK_OEM_3,
			LBracket        = VK_OEM_4,
			BackSlash       = VK_OEM_5,
			RBracket        = VK_OEM_6,
			Apostrophe      = VK_OEM_7,

			Shift           = VK_SHIFT,
			LShift			= VK_LSHIFT,
			RShift			= VK_RSHIFT,

			Ctrl            = VK_CONTROL,
			LCtrl			= VK_LCONTROL,
			RCtrl			= VK_RCONTROL,

			LWin            = VK_LWIN,
			RWin            = VK_RWIN,

			Alt				= VK_MENU,
			LAlt            = VK_LMENU,
			RAlt            = VK_RMENU,

			Insert          = VK_INSERT,
			Delete          = VK_DELETE,
			Home            = VK_HOME,
			End             = VK_END,
			PageUp          = VK_PRIOR,
			PageDown        = VK_NEXT,

			Up              = VK_UP,
			Down            = VK_DOWN,
			Right           = VK_RIGHT,
			Left            = VK_LEFT,

			NumLock         = VK_NUMLOCK,
			NumpadDivide   = VK_DIVIDE,
			NumpadMultiply = VK_MULTIPLY,
			NumpadSubtract = VK_SUBTRACT,
			NumpadAdd      = VK_ADD,
			NumpadDecimal  = VK_DECIMAL,
			Numpad0        = VK_NUMPAD0,
			Numpad1        = VK_NUMPAD1,
			Numpad2        = VK_NUMPAD2,
			Numpad3        = VK_NUMPAD3,
			Numpad4        = VK_NUMPAD4,
			Numpad5        = VK_NUMPAD5,
			Numpad6        = VK_NUMPAD6,
			Numpad7        = VK_NUMPAD7,
			Numpad8        = VK_NUMPAD8,
			Numpad9        = VK_NUMPAD9
		};
	}

	class Window;
	struct KeyEventArgs;

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

		bool isKeyDown(Keys::Enum key) const {
			return (m_currentKeyStates[key] & 0x80) ? true : false;
		}

		bool isKeyUp(Keys::Enum key) const {
			return (m_currentKeyStates[key] & 0x80) ? false : true;
		}

		bool isKeyPressed(Keys::Enum key) const { 
			return ((m_currentKeyStates[key] & 0x80) && !(m_previousKeyStates[key] & 0x80)) ? true : false;
		}

		void update();

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

		GxU8* m_currentKeyStates;
		GxU8* m_previousKeyStates;
	};
}

#endif /* __gx_keyboard_h__ */