#ifndef KEYCODES_HPP
#define KEYCODES_HPP

#include <cstdint>
#include <ostream>

namespace OpenEngine
{
	typedef enum class KeyCode : uint16_t
	{
		// From glfw3.h
		Space               = 32,
		Apostrophe          = 39, /* ' */
		Comma               = 44, /* , */
		Minus               = 45, /* - */
		Period              = 46, /* . */
		Slash               = 47, /* / */

		D0                  = 48, /* 0 */
		D1                  = 49, /* 1 */
		D2                  = 50, /* 2 */
		D3                  = 51, /* 3 */
		D4                  = 52, /* 4 */
		D5                  = 53, /* 5 */
		D6                  = 54, /* 6 */
		D7                  = 55, /* 7 */
		D8                  = 56, /* 8 */
		D9                  = 57, /* 9 */

		Semicolon           = 59, /* ; */
		Equal               = 61, /* = */

		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,

		LeftBracket         = 91,  /* [ */
		Backslash           = 92,  /* \ */
		RightBracket        = 93,  /* ] */
		GraveAccent         = 96,  /* ` */

		World1              = 161, /* non-US #1 */
		World2              = 162, /* non-US #2 */

		/* Function keys */
		Escape              = 256,
		Enter               = 257,
		Tab                 = 258,
		Backspace           = 259,
		Insert              = 260,
		Delete              = 261,
		Right               = 262,
		Left                = 263,
		Down                = 264,
		Up                  = 265,
		PageUp              = 266,
		PageDown            = 267,
		Home                = 268,
		End                 = 269,
		CapsLock            = 280,
		ScrollLock          = 281,
		NumLock             = 282,
		PrintScreen         = 283,
		Pause               = 284,
		F1                  = 290,
		F2                  = 291,
		F3                  = 292,
		F4                  = 293,
		F5                  = 294,
		F6                  = 295,
		F7                  = 296,
		F8                  = 297,
		F9                  = 298,
		F10                 = 299,
		F11                 = 300,
		F12                 = 301,
		F13                 = 302,
		F14                 = 303,
		F15                 = 304,
		F16                 = 305,
		F17                 = 306,
		F18                 = 307,
		F19                 = 308,
		F20                 = 309,
		F21                 = 310,
		F22                 = 311,
		F23                 = 312,
		F24                 = 313,
		F25                 = 314,

		/* Keypad */
		KP0                 = 320,
		KP1                 = 321,
		KP2                 = 322,
		KP3                 = 323,
		KP4                 = 324,
		KP5                 = 325,
		KP6                 = 326,
		KP7                 = 327,
		KP8                 = 328,
		KP9                 = 329,
		KPDecimal           = 330,
		KPDivide            = 331,
		KPMultiply          = 332,
		KPSubtract          = 333,
		KPAdd               = 334,
		KPEnter             = 335,
		KPEqual             = 336,

		LeftShift           = 340,
		LeftControl         = 341,
		LeftAlt             = 342,
		LeftSuper           = 343,
		RightShift          = 344,
		RightControl        = 345,
		RightAlt            = 346,
		RightSuper          = 347,
		Menu                = 348
	} Key;

	inline std::ostream& operator<<(std::ostream& os, KeyCode keyCode)
	{
		os << static_cast<int32_t>(keyCode);
		return os;
	}
}

// From glfw3.h
#define OE_KEY_SPACE           ::OpenEngine::Key::Space
#define OE_KEY_APOSTROPHE      ::OpenEngine::Key::Apostrophe    /* ' */
#define OE_KEY_COMMA           ::OpenEngine::Key::Comma         /* , */
#define OE_KEY_MINUS           ::OpenEngine::Key::Minus         /* - */
#define OE_KEY_PERIOD          ::OpenEngine::Key::Period        /* . */
#define OE_KEY_SLASH           ::OpenEngine::Key::Slash         /* / */
#define OE_KEY_0               ::OpenEngine::Key::D0
#define OE_KEY_1               ::OpenEngine::Key::D1
#define OE_KEY_2               ::OpenEngine::Key::D2
#define OE_KEY_3               ::OpenEngine::Key::D3
#define OE_KEY_4               ::OpenEngine::Key::D4
#define OE_KEY_5               ::OpenEngine::Key::D5
#define OE_KEY_6               ::OpenEngine::Key::D6
#define OE_KEY_7               ::OpenEngine::Key::D7
#define OE_KEY_8               ::OpenEngine::Key::D8
#define OE_KEY_9               ::OpenEngine::Key::D9
#define OE_KEY_SEMICOLON       ::OpenEngine::Key::Semicolon     /* ; */
#define OE_KEY_EQUAL           ::OpenEngine::Key::Equal         /* = */
#define OE_KEY_A               ::OpenEngine::Key::A
#define OE_KEY_B               ::OpenEngine::Key::B
#define OE_KEY_C               ::OpenEngine::Key::C
#define OE_KEY_D               ::OpenEngine::Key::D
#define OE_KEY_E               ::OpenEngine::Key::E
#define OE_KEY_F               ::OpenEngine::Key::F
#define OE_KEY_G               ::OpenEngine::Key::G
#define OE_KEY_H               ::OpenEngine::Key::H
#define OE_KEY_I               ::OpenEngine::Key::I
#define OE_KEY_J               ::OpenEngine::Key::J
#define OE_KEY_K               ::OpenEngine::Key::K
#define OE_KEY_L               ::OpenEngine::Key::L
#define OE_KEY_M               ::OpenEngine::Key::M
#define OE_KEY_N               ::OpenEngine::Key::N
#define OE_KEY_O               ::OpenEngine::Key::O
#define OE_KEY_P               ::OpenEngine::Key::P
#define OE_KEY_Q               ::OpenEngine::Key::Q
#define OE_KEY_R               ::OpenEngine::Key::R
#define OE_KEY_S               ::OpenEngine::Key::S
#define OE_KEY_T               ::OpenEngine::Key::T
#define OE_KEY_U               ::OpenEngine::Key::U
#define OE_KEY_V               ::OpenEngine::Key::V
#define OE_KEY_W               ::OpenEngine::Key::W
#define OE_KEY_X               ::OpenEngine::Key::X
#define OE_KEY_Y               ::OpenEngine::Key::Y
#define OE_KEY_Z               ::OpenEngine::Key::Z
#define OE_KEY_LEFT_BRACKET    ::OpenEngine::Key::LeftBracket   /* [ */
#define OE_KEY_BACKSLASH       ::OpenEngine::Key::Backslash     /* \ */
#define OE_KEY_RIGHT_BRACKET   ::OpenEngine::Key::RightBracket  /* ] */
#define OE_KEY_GRAVE_ACCENT    ::OpenEngine::Key::GraveAccent   /* ` */
#define OE_KEY_WORLD_1         ::OpenEngine::Key::World1        /* non-US #1 */
#define OE_KEY_WORLD_2         ::OpenEngine::Key::World2        /* non-US #2 */

/* Function keys */
#define OE_KEY_ESCAPE          ::OpenEngine::Key::Escape
#define OE_KEY_ENTER           ::OpenEngine::Key::Enter
#define OE_KEY_TAB             ::OpenEngine::Key::Tab
#define OE_KEY_BACKSPACE       ::OpenEngine::Key::Backspace
#define OE_KEY_INSERT          ::OpenEngine::Key::Insert
#define OE_KEY_DELETE          ::OpenEngine::Key::Delete
#define OE_KEY_RIGHT           ::OpenEngine::Key::Right
#define OE_KEY_LEFT            ::OpenEngine::Key::Left
#define OE_KEY_DOWN            ::OpenEngine::Key::Down
#define OE_KEY_UP              ::OpenEngine::Key::Up
#define OE_KEY_PAGE_UP         ::OpenEngine::Key::PageUp
#define OE_KEY_PAGE_DOWN       ::OpenEngine::Key::PageDown
#define OE_KEY_HOME            ::OpenEngine::Key::Home
#define OE_KEY_END             ::OpenEngine::Key::End
#define OE_KEY_CAPS_LOCK       ::OpenEngine::Key::CapsLock
#define OE_KEY_SCROLL_LOCK     ::OpenEngine::Key::ScrollLock
#define OE_KEY_NUM_LOCK        ::OpenEngine::Key::NumLock
#define OE_KEY_PRINT_SCREEN    ::OpenEngine::Key::PrintScreen
#define OE_KEY_PAUSE           ::OpenEngine::Key::Pause
#define OE_KEY_F1              ::OpenEngine::Key::F1
#define OE_KEY_F2              ::OpenEngine::Key::F2
#define OE_KEY_F3              ::OpenEngine::Key::F3
#define OE_KEY_F4              ::OpenEngine::Key::F4
#define OE_KEY_F5              ::OpenEngine::Key::F5
#define OE_KEY_F6              ::OpenEngine::Key::F6
#define OE_KEY_F7              ::OpenEngine::Key::F7
#define OE_KEY_F8              ::OpenEngine::Key::F8
#define OE_KEY_F9              ::OpenEngine::Key::F9
#define OE_KEY_F10             ::OpenEngine::Key::F10
#define OE_KEY_F11             ::OpenEngine::Key::F11
#define OE_KEY_F12             ::OpenEngine::Key::F12
#define OE_KEY_F13             ::OpenEngine::Key::F13
#define OE_KEY_F14             ::OpenEngine::Key::F14
#define OE_KEY_F15             ::OpenEngine::Key::F15
#define OE_KEY_F16             ::OpenEngine::Key::F16
#define OE_KEY_F17             ::OpenEngine::Key::F17
#define OE_KEY_F18             ::OpenEngine::Key::F18
#define OE_KEY_F19             ::OpenEngine::Key::F19
#define OE_KEY_F20             ::OpenEngine::Key::F20
#define OE_KEY_F21             ::OpenEngine::Key::F21
#define OE_KEY_F22             ::OpenEngine::Key::F22
#define OE_KEY_F23             ::OpenEngine::Key::F23
#define OE_KEY_F24             ::OpenEngine::Key::F24
#define OE_KEY_F25             ::OpenEngine::Key::F25

/* Keypad */
#define OE_KEY_KP_0            ::OpenEngine::Key::KP0
#define OE_KEY_KP_1            ::OpenEngine::Key::KP1
#define OE_KEY_KP_2            ::OpenEngine::Key::KP2
#define OE_KEY_KP_3            ::OpenEngine::Key::KP3
#define OE_KEY_KP_4            ::OpenEngine::Key::KP4
#define OE_KEY_KP_5            ::OpenEngine::Key::KP5
#define OE_KEY_KP_6            ::OpenEngine::Key::KP6
#define OE_KEY_KP_7            ::OpenEngine::Key::KP7
#define OE_KEY_KP_8            ::OpenEngine::Key::KP8
#define OE_KEY_KP_9            ::OpenEngine::Key::KP9
#define OE_KEY_KP_DECIMAL      ::OpenEngine::Key::KPDecimal
#define OE_KEY_KP_DIVIDE       ::OpenEngine::Key::KPDivide
#define OE_KEY_KP_MULTIPLY     ::OpenEngine::Key::KPMultiply
#define OE_KEY_KP_SUBTRACT     ::OpenEngine::Key::KPSubtract
#define OE_KEY_KP_ADD          ::OpenEngine::Key::KPAdd
#define OE_KEY_KP_ENTER        ::OpenEngine::Key::KPEnter
#define OE_KEY_KP_EQUAL        ::OpenEngine::Key::KPEqual

#define OE_KEY_LEFT_SHIFT      ::OpenEngine::Key::LeftShift
#define OE_KEY_LEFT_CONTROL    ::OpenEngine::Key::LeftControl
#define OE_KEY_LEFT_ALT        ::OpenEngine::Key::LeftAlt
#define OE_KEY_LEFT_SUPER      ::OpenEngine::Key::LeftSuper
#define OE_KEY_RIGHT_SHIFT     ::OpenEngine::Key::RightShift
#define OE_KEY_RIGHT_CONTROL   ::OpenEngine::Key::RightControl
#define OE_KEY_RIGHT_ALT       ::OpenEngine::Key::RightAlt
#define OE_KEY_RIGHT_SUPER     ::OpenEngine::Key::RightSuper
#define OE_KEY_MENU            ::OpenEngine::Key::Menu

#endif // KEYCODES_HPP
