
-----------------------
-- General Functions --
-----------------------

-- @bubb_doc { EEex_Key_GetFromName }
--
-- @summary: Returns a ``SDL_Keycode`` value that represents the given ``keyName``.
--
-- @param { keyName / type=string }: The name of the key whose ``SDL_Keycode`` value is being fetched.
--
-- @return { usertype=SDL_Keycode }: See summary.
--
-- @extra_comment:
--
-- ============================================================================================================
--
-- Recognized ``keyName`` values
-- """""""""""""""""""""""""""""
--
-- UTF-8 character encodings are recognized. For example, all of the following lines would be considered valid:
--
-- .. code-block:: Lua
--
--    EEex_Key_GetFromName("a")
--    EEex_Key_GetFromName("$")
--    EEex_Key_GetFromName("£")
--    EEex_Key_GetFromName("€")
--    EEex_Key_GetFromName("𐍈")
--
-- Additionally, the following table provides a list of all the specially-recognized key names:
--
-- +---------------------+
-- | Recognized Key Name |
-- +=====================+
-- | Return              |
-- +---------------------+
-- | Escape              |
-- +---------------------+
-- | Backspace           |
-- +---------------------+
-- | Tab                 |
-- +---------------------+
-- | Space               |
-- +---------------------+
-- | CapsLock            |
-- +---------------------+
-- | F1                  |
-- +---------------------+
-- | F2                  |
-- +---------------------+
-- | F3                  |
-- +---------------------+
-- | F4                  |
-- +---------------------+
-- | F5                  |
-- +---------------------+
-- | F6                  |
-- +---------------------+
-- | F7                  |
-- +---------------------+
-- | F8                  |
-- +---------------------+
-- | F9                  |
-- +---------------------+
-- | F10                 |
-- +---------------------+
-- | F11                 |
-- +---------------------+
-- | F12                 |
-- +---------------------+
-- | PrintScreen         |
-- +---------------------+
-- | ScrollLock          |
-- +---------------------+
-- | Pause               |
-- +---------------------+
-- | Insert              |
-- +---------------------+
-- | Home                |
-- +---------------------+
-- | PageUp              |
-- +---------------------+
-- | Delete              |
-- +---------------------+
-- | End                 |
-- +---------------------+
-- | PageDown            |
-- +---------------------+
-- | Right               |
-- +---------------------+
-- | Left                |
-- +---------------------+
-- | Down                |
-- +---------------------+
-- | Up                  |
-- +---------------------+
-- | Numlock             |
-- +---------------------+
-- | Keypad /            |
-- +---------------------+
-- | Keypad *            |
-- +---------------------+
-- | Keypad -            |
-- +---------------------+
-- | Keypad +            |
-- +---------------------+
-- | Keypad Enter        |
-- +---------------------+
-- | Keypad 1            |
-- +---------------------+
-- | Keypad 2            |
-- +---------------------+
-- | Keypad 3            |
-- +---------------------+
-- | Keypad 4            |
-- +---------------------+
-- | Keypad 5            |
-- +---------------------+
-- | Keypad 6            |
-- +---------------------+
-- | Keypad 7            |
-- +---------------------+
-- | Keypad 8            |
-- +---------------------+
-- | Keypad 9            |
-- +---------------------+
-- | Keypad 0            |
-- +---------------------+
-- | Keypad .            |
-- +---------------------+
-- | Menu                |
-- +---------------------+
-- | Power               |
-- +---------------------+
-- | Keypad =            |
-- +---------------------+
-- | F13                 |
-- +---------------------+
-- | F14                 |
-- +---------------------+
-- | F15                 |
-- +---------------------+
-- | F16                 |
-- +---------------------+
-- | F17                 |
-- +---------------------+
-- | F18                 |
-- +---------------------+
-- | F19                 |
-- +---------------------+
-- | F20                 |
-- +---------------------+
-- | F21                 |
-- +---------------------+
-- | F22                 |
-- +---------------------+
-- | F23                 |
-- +---------------------+
-- | F24                 |
-- +---------------------+
-- | Execute             |
-- +---------------------+
-- | Help                |
-- +---------------------+
-- | Menu                |
-- +---------------------+
-- | Select              |
-- +---------------------+
-- | Stop                |
-- +---------------------+
-- | Again               |
-- +---------------------+
-- | Undo                |
-- +---------------------+
-- | Cut                 |
-- +---------------------+
-- | Copy                |
-- +---------------------+
-- | Paste               |
-- +---------------------+
-- | Find                |
-- +---------------------+
-- | Mute                |
-- +---------------------+
-- | VolumeUp            |
-- +---------------------+
-- | VolumeDown          |
-- +---------------------+
-- | Keypad ,            |
-- +---------------------+
-- | Keypad = (AS400)    |
-- +---------------------+
-- | AltErase            |
-- +---------------------+
-- | SysReq              |
-- +---------------------+
-- | Cancel              |
-- +---------------------+
-- | Clear               |
-- +---------------------+
-- | Prior               |
-- +---------------------+
-- | Return              |
-- +---------------------+
-- | Separator           |
-- +---------------------+
-- | Out                 |
-- +---------------------+
-- | Oper                |
-- +---------------------+
-- | Clear / Again       |
-- +---------------------+
-- | CrSel               |
-- +---------------------+
-- | ExSel               |
-- +---------------------+
-- | Keypad 00           |
-- +---------------------+
-- | Keypad 000          |
-- +---------------------+
-- | ThousandsSeparator  |
-- +---------------------+
-- | DecimalSeparator    |
-- +---------------------+
-- | CurrencyUnit        |
-- +---------------------+
-- | CurrencySubUnit     |
-- +---------------------+
-- | Keypad (            |
-- +---------------------+
-- | Keypad )            |
-- +---------------------+
-- | Keypad {            |
-- +---------------------+
-- | Keypad }            |
-- +---------------------+
-- | Keypad Tab          |
-- +---------------------+
-- | Keypad Backspace    |
-- +---------------------+
-- | Keypad A            |
-- +---------------------+
-- | Keypad B            |
-- +---------------------+
-- | Keypad C            |
-- +---------------------+
-- | Keypad D            |
-- +---------------------+
-- | Keypad E            |
-- +---------------------+
-- | Keypad F            |
-- +---------------------+
-- | Keypad XOR          |
-- +---------------------+
-- | Keypad ^            |
-- +---------------------+
-- | Keypad %            |
-- +---------------------+
-- | Keypad <            |
-- +---------------------+
-- | Keypad >            |
-- +---------------------+
-- | Keypad &            |
-- +---------------------+
-- | Keypad &&           |
-- +---------------------+
-- | Keypad |            |
-- +---------------------+
-- | Keypad ||           |
-- +---------------------+
-- | Keypad :            |
-- +---------------------+
-- | Keypad #            |
-- +---------------------+
-- | Keypad Space        |
-- +---------------------+
-- | Keypad @            |
-- +---------------------+
-- | Keypad !            |
-- +---------------------+
-- | Keypad MemStore     |
-- +---------------------+
-- | Keypad MemRecall    |
-- +---------------------+
-- | Keypad MemClear     |
-- +---------------------+
-- | Keypad MemAdd       |
-- +---------------------+
-- | Keypad MemSubtract  |
-- +---------------------+
-- | Keypad MemMultiply  |
-- +---------------------+
-- | Keypad MemDivide    |
-- +---------------------+
-- | Keypad +/-          |
-- +---------------------+
-- | Keypad Clear        |
-- +---------------------+
-- | Keypad ClearEntry   |
-- +---------------------+
-- | Keypad Binary       |
-- +---------------------+
-- | Keypad Octal        |
-- +---------------------+
-- | Keypad Decimal      |
-- +---------------------+
-- | Keypad Hexadecimal  |
-- +---------------------+
-- | Left Ctrl           |
-- +---------------------+
-- | Left Shift          |
-- +---------------------+
-- | Left Alt            |
-- +---------------------+
-- | Left Windows        |
-- +---------------------+
-- | Right Ctrl          |
-- +---------------------+
-- | Right Shift         |
-- +---------------------+
-- | Right Alt           |
-- +---------------------+
-- | Right Windows       |
-- +---------------------+
-- | ModeSwitch          |
-- +---------------------+
-- | AudioNext           |
-- +---------------------+
-- | AudioPrev           |
-- +---------------------+
-- | AudioStop           |
-- +---------------------+
-- | AudioPlay           |
-- +---------------------+
-- | AudioMute           |
-- +---------------------+
-- | MediaSelect         |
-- +---------------------+
-- | WWW                 |
-- +---------------------+
-- | Mail                |
-- +---------------------+
-- | Calculator          |
-- +---------------------+
-- | Computer            |
-- +---------------------+
-- | AC Search           |
-- +---------------------+
-- | AC Home             |
-- +---------------------+
-- | AC Back             |
-- +---------------------+
-- | AC Forward          |
-- +---------------------+
-- | AC Stop             |
-- +---------------------+
-- | AC Refresh          |
-- +---------------------+
-- | AC Bookmarks        |
-- +---------------------+
-- | BrightnessDown      |
-- +---------------------+
-- | BrightnessUp        |
-- +---------------------+
-- | DisplaySwitch       |
-- +---------------------+
-- | KBDIllumToggle      |
-- +---------------------+
-- | KBDIllumDown        |
-- +---------------------+
-- | KBDIllumUp          |
-- +---------------------+
-- | Eject               |
-- +---------------------+
-- | Sleep               |
-- +---------------------+

function EEex_Key_GetFromName(name)
	return EngineGlobals.SDL_GetKeyFromName(name)
end

function EEex_Key_GetName(key)
	return EngineGlobals.SDL_GetKeyName(key)
end

EEex_Key_IsDownMap = EEex_Key_IsDownMap or {}

-- @bubb_doc { EEex_Key_IsDown }
--
-- @summary: Returns ``true`` if the given ``key`` is currently pressed. See `SDL_Keycode`_ for valid ``key`` values.
--
--           It is recommended to use `EEex_Key_GetFromName`_ if you are unsure which ``SDL_Keycode`` matches the desired character.
--
-- @param { key / usertype=SDL_Keycode }: The key whose pressed status is being checked.
--
-- @return { type=boolean }: See summary.
--
-- @extra_comment:
--
-- =================================================================================================================================
--
-- **SDL_Keycode**
-- """""""""""""""
--
-- +-------------------------+------------+
-- | Ordinal Name            | Value      |
-- +=========================+============+
-- | SDLK_UNKNOWN            | 0          |
-- +-------------------------+------------+
-- | SDLK_BACKSPACE          | 8          |
-- +-------------------------+------------+
-- | SDLK_TAB                | 9          |
-- +-------------------------+------------+
-- | SDLK_RETURN             | 13         |
-- +-------------------------+------------+
-- | SDLK_ESCAPE             | 27         |
-- +-------------------------+------------+
-- | SDLK_SPACE              | 32         |
-- +-------------------------+------------+
-- | SDLK_EXCLAIM            | 33         |
-- +-------------------------+------------+
-- | SDLK_QUOTEDBL           | 34         |
-- +-------------------------+------------+
-- | SDLK_HASH               | 35         |
-- +-------------------------+------------+
-- | SDLK_DOLLAR             | 36         |
-- +-------------------------+------------+
-- | SDLK_PERCENT            | 37         |
-- +-------------------------+------------+
-- | SDLK_AMPERSAND          | 38         |
-- +-------------------------+------------+
-- | SDLK_QUOTE              | 39         |
-- +-------------------------+------------+
-- | SDLK_LEFTPAREN          | 40         |
-- +-------------------------+------------+
-- | SDLK_RIGHTPAREN         | 41         |
-- +-------------------------+------------+
-- | SDLK_ASTERISK           | 42         |
-- +-------------------------+------------+
-- | SDLK_PLUS               | 43         |
-- +-------------------------+------------+
-- | SDLK_COMMA              | 44         |
-- +-------------------------+------------+
-- | SDLK_MINUS              | 45         |
-- +-------------------------+------------+
-- | SDLK_PERIOD             | 46         |
-- +-------------------------+------------+
-- | SDLK_SLASH              | 47         |
-- +-------------------------+------------+
-- | SDLK_0                  | 48         |
-- +-------------------------+------------+
-- | SDLK_1                  | 49         |
-- +-------------------------+------------+
-- | SDLK_2                  | 50         |
-- +-------------------------+------------+
-- | SDLK_3                  | 51         |
-- +-------------------------+------------+
-- | SDLK_4                  | 52         |
-- +-------------------------+------------+
-- | SDLK_5                  | 53         |
-- +-------------------------+------------+
-- | SDLK_6                  | 54         |
-- +-------------------------+------------+
-- | SDLK_7                  | 55         |
-- +-------------------------+------------+
-- | SDLK_8                  | 56         |
-- +-------------------------+------------+
-- | SDLK_9                  | 57         |
-- +-------------------------+------------+
-- | SDLK_COLON              | 58         |
-- +-------------------------+------------+
-- | SDLK_SEMICOLON          | 59         |
-- +-------------------------+------------+
-- | SDLK_LESS               | 60         |
-- +-------------------------+------------+
-- | SDLK_EQUALS             | 61         |
-- +-------------------------+------------+
-- | SDLK_GREATER            | 62         |
-- +-------------------------+------------+
-- | SDLK_QUESTION           | 63         |
-- +-------------------------+------------+
-- | SDLK_AT                 | 64         |
-- +-------------------------+------------+
-- | SDLK_LEFTBRACKET        | 91         |
-- +-------------------------+------------+
-- | SDLK_BACKSLASH          | 92         |
-- +-------------------------+------------+
-- | SDLK_RIGHTBRACKET       | 93         |
-- +-------------------------+------------+
-- | SDLK_CARET              | 94         |
-- +-------------------------+------------+
-- | SDLK_UNDERSCORE         | 95         |
-- +-------------------------+------------+
-- | SDLK_BACKQUOTE          | 96         |
-- +-------------------------+------------+
-- | SDLK_a                  | 97         |
-- +-------------------------+------------+
-- | SDLK_b                  | 98         |
-- +-------------------------+------------+
-- | SDLK_c                  | 99         |
-- +-------------------------+------------+
-- | SDLK_d                  | 100        |
-- +-------------------------+------------+
-- | SDLK_e                  | 101        |
-- +-------------------------+------------+
-- | SDLK_f                  | 102        |
-- +-------------------------+------------+
-- | SDLK_g                  | 103        |
-- +-------------------------+------------+
-- | SDLK_h                  | 104        |
-- +-------------------------+------------+
-- | SDLK_i                  | 105        |
-- +-------------------------+------------+
-- | SDLK_j                  | 106        |
-- +-------------------------+------------+
-- | SDLK_k                  | 107        |
-- +-------------------------+------------+
-- | SDLK_l                  | 108        |
-- +-------------------------+------------+
-- | SDLK_m                  | 109        |
-- +-------------------------+------------+
-- | SDLK_n                  | 110        |
-- +-------------------------+------------+
-- | SDLK_o                  | 111        |
-- +-------------------------+------------+
-- | SDLK_p                  | 112        |
-- +-------------------------+------------+
-- | SDLK_q                  | 113        |
-- +-------------------------+------------+
-- | SDLK_r                  | 114        |
-- +-------------------------+------------+
-- | SDLK_s                  | 115        |
-- +-------------------------+------------+
-- | SDLK_t                  | 116        |
-- +-------------------------+------------+
-- | SDLK_u                  | 117        |
-- +-------------------------+------------+
-- | SDLK_v                  | 118        |
-- +-------------------------+------------+
-- | SDLK_w                  | 119        |
-- +-------------------------+------------+
-- | SDLK_x                  | 120        |
-- +-------------------------+------------+
-- | SDLK_y                  | 121        |
-- +-------------------------+------------+
-- | SDLK_z                  | 122        |
-- +-------------------------+------------+
-- | SDLK_DELETE             | 127        |
-- +-------------------------+------------+
-- | SDLK_CAPSLOCK           | 0x40000039 |
-- +-------------------------+------------+
-- | SDLK_F1                 | 0x4000003A |
-- +-------------------------+------------+
-- | SDLK_F2                 | 0x4000003B |
-- +-------------------------+------------+
-- | SDLK_F3                 | 0x4000003C |
-- +-------------------------+------------+
-- | SDLK_F4                 | 0x4000003D |
-- +-------------------------+------------+
-- | SDLK_F5                 | 0x4000003E |
-- +-------------------------+------------+
-- | SDLK_F6                 | 0x4000003F |
-- +-------------------------+------------+
-- | SDLK_F7                 | 0x40000040 |
-- +-------------------------+------------+
-- | SDLK_F8                 | 0x40000041 |
-- +-------------------------+------------+
-- | SDLK_F9                 | 0x40000042 |
-- +-------------------------+------------+
-- | SDLK_F10                | 0x40000043 |
-- +-------------------------+------------+
-- | SDLK_F11                | 0x40000044 |
-- +-------------------------+------------+
-- | SDLK_F12                | 0x40000045 |
-- +-------------------------+------------+
-- | SDLK_PRINTSCREEN        | 0x40000046 |
-- +-------------------------+------------+
-- | SDLK_SCROLLLOCK         | 0x40000047 |
-- +-------------------------+------------+
-- | SDLK_PAUSE              | 0x40000048 |
-- +-------------------------+------------+
-- | SDLK_INSERT             | 0x40000049 |
-- +-------------------------+------------+
-- | SDLK_HOME               | 0x4000004A |
-- +-------------------------+------------+
-- | SDLK_PAGEUP             | 0x4000004B |
-- +-------------------------+------------+
-- | SDLK_END                | 0x4000004D |
-- +-------------------------+------------+
-- | SDLK_PAGEDOWN           | 0x4000004E |
-- +-------------------------+------------+
-- | SDLK_RIGHT              | 0x4000004F |
-- +-------------------------+------------+
-- | SDLK_LEFT               | 0x40000050 |
-- +-------------------------+------------+
-- | SDLK_DOWN               | 0x40000051 |
-- +-------------------------+------------+
-- | SDLK_UP                 | 0x40000052 |
-- +-------------------------+------------+
-- | SDLK_NUMLOCKCLEAR       | 0x40000053 |
-- +-------------------------+------------+
-- | SDLK_KP_DIVIDE          | 0x40000054 |
-- +-------------------------+------------+
-- | SDLK_KP_MULTIPLY        | 0x40000055 |
-- +-------------------------+------------+
-- | SDLK_KP_MINUS           | 0x40000056 |
-- +-------------------------+------------+
-- | SDLK_KP_PLUS            | 0x40000057 |
-- +-------------------------+------------+
-- | SDLK_KP_ENTER           | 0x40000058 |
-- +-------------------------+------------+
-- | SDLK_KP_1               | 0x40000059 |
-- +-------------------------+------------+
-- | SDLK_KP_2               | 0x4000005A |
-- +-------------------------+------------+
-- | SDLK_KP_3               | 0x4000005B |
-- +-------------------------+------------+
-- | SDLK_KP_4               | 0x4000005C |
-- +-------------------------+------------+
-- | SDLK_KP_5               | 0x4000005D |
-- +-------------------------+------------+
-- | SDLK_KP_6               | 0x4000005E |
-- +-------------------------+------------+
-- | SDLK_KP_7               | 0x4000005F |
-- +-------------------------+------------+
-- | SDLK_KP_8               | 0x40000060 |
-- +-------------------------+------------+
-- | SDLK_KP_9               | 0x40000061 |
-- +-------------------------+------------+
-- | SDLK_KP_0               | 0x40000062 |
-- +-------------------------+------------+
-- | SDLK_KP_PERIOD          | 0x40000063 |
-- +-------------------------+------------+
-- | SDLK_APPLICATION        | 0x40000065 |
-- +-------------------------+------------+
-- | SDLK_POWER              | 0x40000066 |
-- +-------------------------+------------+
-- | SDLK_KP_EQUALS          | 0x40000067 |
-- +-------------------------+------------+
-- | SDLK_F13                | 0x40000068 |
-- +-------------------------+------------+
-- | SDLK_F14                | 0x40000069 |
-- +-------------------------+------------+
-- | SDLK_F15                | 0x4000006A |
-- +-------------------------+------------+
-- | SDLK_F16                | 0x4000006B |
-- +-------------------------+------------+
-- | SDLK_F17                | 0x4000006C |
-- +-------------------------+------------+
-- | SDLK_F18                | 0x4000006D |
-- +-------------------------+------------+
-- | SDLK_F19                | 0x4000006E |
-- +-------------------------+------------+
-- | SDLK_F20                | 0x4000006F |
-- +-------------------------+------------+
-- | SDLK_F21                | 0x40000070 |
-- +-------------------------+------------+
-- | SDLK_F22                | 0x40000071 |
-- +-------------------------+------------+
-- | SDLK_F23                | 0x40000072 |
-- +-------------------------+------------+
-- | SDLK_F24                | 0x40000073 |
-- +-------------------------+------------+
-- | SDLK_EXECUTE            | 0x40000074 |
-- +-------------------------+------------+
-- | SDLK_HELP               | 0x40000075 |
-- +-------------------------+------------+
-- | SDLK_MENU               | 0x40000076 |
-- +-------------------------+------------+
-- | SDLK_SELECT             | 0x40000077 |
-- +-------------------------+------------+
-- | SDLK_STOP               | 0x40000078 |
-- +-------------------------+------------+
-- | SDLK_AGAIN              | 0x40000079 |
-- +-------------------------+------------+
-- | SDLK_UNDO               | 0x4000007A |
-- +-------------------------+------------+
-- | SDLK_CUT                | 0x4000007B |
-- +-------------------------+------------+
-- | SDLK_COPY               | 0x4000007C |
-- +-------------------------+------------+
-- | SDLK_PASTE              | 0x4000007D |
-- +-------------------------+------------+
-- | SDLK_FIND               | 0x4000007E |
-- +-------------------------+------------+
-- | SDLK_MUTE               | 0x4000007F |
-- +-------------------------+------------+
-- | SDLK_VOLUMEUP           | 0x40000080 |
-- +-------------------------+------------+
-- | SDLK_VOLUMEDOWN         | 0x40000081 |
-- +-------------------------+------------+
-- | SDLK_KP_COMMA           | 0x40000085 |
-- +-------------------------+------------+
-- | SDLK_KP_EQUALSAS400     | 0x40000086 |
-- +-------------------------+------------+
-- | SDLK_ALTERASE           | 0x40000099 |
-- +-------------------------+------------+
-- | SDLK_SYSREQ             | 0x4000009A |
-- +-------------------------+------------+
-- | SDLK_CANCEL             | 0x4000009B |
-- +-------------------------+------------+
-- | SDLK_CLEAR              | 0x4000009C |
-- +-------------------------+------------+
-- | SDLK_PRIOR              | 0x4000009D |
-- +-------------------------+------------+
-- | SDLK_RETURN2            | 0x4000009E |
-- +-------------------------+------------+
-- | SDLK_SEPARATOR          | 0x4000009F |
-- +-------------------------+------------+
-- | SDLK_OUT                | 0x400000A0 |
-- +-------------------------+------------+
-- | SDLK_OPER               | 0x400000A1 |
-- +-------------------------+------------+
-- | SDLK_CLEARAGAIN         | 0x400000A2 |
-- +-------------------------+------------+
-- | SDLK_CRSEL              | 0x400000A3 |
-- +-------------------------+------------+
-- | SDLK_EXSEL              | 0x400000A4 |
-- +-------------------------+------------+
-- | SDLK_KP_00              | 0x400000B0 |
-- +-------------------------+------------+
-- | SDLK_KP_000             | 0x400000B1 |
-- +-------------------------+------------+
-- | SDLK_THOUSANDSSEPARATOR | 0x400000B2 |
-- +-------------------------+------------+
-- | SDLK_DECIMALSEPARATOR   | 0x400000B3 |
-- +-------------------------+------------+
-- | SDLK_CURRENCYUNIT       | 0x400000B4 |
-- +-------------------------+------------+
-- | SDLK_CURRENCYSUBUNIT    | 0x400000B5 |
-- +-------------------------+------------+
-- | SDLK_KP_LEFTPAREN       | 0x400000B6 |
-- +-------------------------+------------+
-- | SDLK_KP_RIGHTPAREN      | 0x400000B7 |
-- +-------------------------+------------+
-- | SDLK_KP_LEFTBRACE       | 0x400000B8 |
-- +-------------------------+------------+
-- | SDLK_KP_RIGHTBRACE      | 0x400000B9 |
-- +-------------------------+------------+
-- | SDLK_KP_TAB             | 0x400000BA |
-- +-------------------------+------------+
-- | SDLK_KP_BACKSPACE       | 0x400000BB |
-- +-------------------------+------------+
-- | SDLK_KP_A               | 0x400000BC |
-- +-------------------------+------------+
-- | SDLK_KP_B               | 0x400000BD |
-- +-------------------------+------------+
-- | SDLK_KP_C               | 0x400000BE |
-- +-------------------------+------------+
-- | SDLK_KP_D               | 0x400000BF |
-- +-------------------------+------------+
-- | SDLK_KP_E               | 0x400000C0 |
-- +-------------------------+------------+
-- | SDLK_KP_F               | 0x400000C1 |
-- +-------------------------+------------+
-- | SDLK_KP_XOR             | 0x400000C2 |
-- +-------------------------+------------+
-- | SDLK_KP_POWER           | 0x400000C3 |
-- +-------------------------+------------+
-- | SDLK_KP_PERCENT         | 0x400000C4 |
-- +-------------------------+------------+
-- | SDLK_KP_LESS            | 0x400000C5 |
-- +-------------------------+------------+
-- | SDLK_KP_GREATER         | 0x400000C6 |
-- +-------------------------+------------+
-- | SDLK_KP_AMPERSAND       | 0x400000C7 |
-- +-------------------------+------------+
-- | SDLK_KP_DBLAMPERSAND    | 0x400000C8 |
-- +-------------------------+------------+
-- | SDLK_KP_VERTICALBAR     | 0x400000C9 |
-- +-------------------------+------------+
-- | SDLK_KP_DBLVERTICALBAR  | 0x400000CA |
-- +-------------------------+------------+
-- | SDLK_KP_COLON           | 0x400000CB |
-- +-------------------------+------------+
-- | SDLK_KP_HASH            | 0x400000CC |
-- +-------------------------+------------+
-- | SDLK_KP_SPACE           | 0x400000CD |
-- +-------------------------+------------+
-- | SDLK_KP_AT              | 0x400000CE |
-- +-------------------------+------------+
-- | SDLK_KP_EXCLAM          | 0x400000CF |
-- +-------------------------+------------+
-- | SDLK_KP_MEMSTORE        | 0x400000D0 |
-- +-------------------------+------------+
-- | SDLK_KP_MEMRECALL       | 0x400000D1 |
-- +-------------------------+------------+
-- | SDLK_KP_MEMCLEAR        | 0x400000D2 |
-- +-------------------------+------------+
-- | SDLK_KP_MEMADD          | 0x400000D3 |
-- +-------------------------+------------+
-- | SDLK_KP_MEMSUBTRACT     | 0x400000D4 |
-- +-------------------------+------------+
-- | SDLK_KP_MEMMULTIPLY     | 0x400000D5 |
-- +-------------------------+------------+
-- | SDLK_KP_MEMDIVIDE       | 0x400000D6 |
-- +-------------------------+------------+
-- | SDLK_KP_PLUSMINUS       | 0x400000D7 |
-- +-------------------------+------------+
-- | SDLK_KP_CLEAR           | 0x400000D8 |
-- +-------------------------+------------+
-- | SDLK_KP_CLEARENTRY      | 0x400000D9 |
-- +-------------------------+------------+
-- | SDLK_KP_BINARY          | 0x400000DA |
-- +-------------------------+------------+
-- | SDLK_KP_OCTAL           | 0x400000DB |
-- +-------------------------+------------+
-- | SDLK_KP_DECIMAL         | 0x400000DC |
-- +-------------------------+------------+
-- | SDLK_KP_HEXADECIMAL     | 0x400000DD |
-- +-------------------------+------------+
-- | SDLK_LCTRL              | 0x400000E0 |
-- +-------------------------+------------+
-- | SDLK_LSHIFT             | 0x400000E1 |
-- +-------------------------+------------+
-- | SDLK_LALT               | 0x400000E2 |
-- +-------------------------+------------+
-- | SDLK_LGUI               | 0x400000E3 |
-- +-------------------------+------------+
-- | SDLK_RCTRL              | 0x400000E4 |
-- +-------------------------+------------+
-- | SDLK_RSHIFT             | 0x400000E5 |
-- +-------------------------+------------+
-- | SDLK_RALT               | 0x400000E6 |
-- +-------------------------+------------+
-- | SDLK_RGUI               | 0x400000E7 |
-- +-------------------------+------------+
-- | SDLK_MODE               | 0x40000101 |
-- +-------------------------+------------+
-- | SDLK_AUDIONEXT          | 0x40000102 |
-- +-------------------------+------------+
-- | SDLK_AUDIOPREV          | 0x40000103 |
-- +-------------------------+------------+
-- | SDLK_AUDIOSTOP          | 0x40000104 |
-- +-------------------------+------------+
-- | SDLK_AUDIOPLAY          | 0x40000105 |
-- +-------------------------+------------+
-- | SDLK_AUDIOMUTE          | 0x40000106 |
-- +-------------------------+------------+
-- | SDLK_MEDIASELECT        | 0x40000107 |
-- +-------------------------+------------+
-- | SDLK_WWW                | 0x40000108 |
-- +-------------------------+------------+
-- | SDLK_MAIL               | 0x40000109 |
-- +-------------------------+------------+
-- | SDLK_CALCULATOR         | 0x4000010A |
-- +-------------------------+------------+
-- | SDLK_COMPUTER           | 0x4000010B |
-- +-------------------------+------------+
-- | SDLK_AC_SEARCH          | 0x4000010C |
-- +-------------------------+------------+
-- | SDLK_AC_HOME            | 0x4000010D |
-- +-------------------------+------------+
-- | SDLK_AC_BACK            | 0x4000010E |
-- +-------------------------+------------+
-- | SDLK_AC_FORWARD         | 0x4000010F |
-- +-------------------------+------------+
-- | SDLK_AC_STOP            | 0x40000110 |
-- +-------------------------+------------+
-- | SDLK_AC_REFRESH         | 0x40000111 |
-- +-------------------------+------------+
-- | SDLK_AC_BOOKMARKS       | 0x40000112 |
-- +-------------------------+------------+
-- | SDLK_BRIGHTNESSDOWN     | 0x40000113 |
-- +-------------------------+------------+
-- | SDLK_BRIGHTNESSUP       | 0x40000114 |
-- +-------------------------+------------+
-- | SDLK_DISPLAYSWITCH      | 0x40000115 |
-- +-------------------------+------------+
-- | SDLK_KBDILLUMTOGGLE     | 0x40000116 |
-- +-------------------------+------------+
-- | SDLK_KBDILLUMDOWN       | 0x40000117 |
-- +-------------------------+------------+
-- | SDLK_KBDILLUMUP         | 0x40000118 |
-- +-------------------------+------------+
-- | SDLK_EJECT              | 0x40000119 |
-- +-------------------------+------------+
-- | SDLK_SLEEP              | 0x4000011A |
-- +-------------------------+------------+

function EEex_Key_IsDown(key)
	return EEex_Key_IsDownMap[key]
end

---------------
-- Listeners --
---------------

EEex_Key_PressedListeners = {}

-- @bubb_doc { EEex_Key_AddPressedListener }
--
-- @summary: Registers a listener function that is called whenever a key is pressed. See `SDL_Keycode`_ for valid ``key`` values.
--
-- @param { func / type=function }: The listener to register.
--
-- @extra_comment:
--
-- ==============================================================================================================================
--
-- The listener function
-- """""""""""""""""""""
--
-- **Parameters:**
--
-- +------+-------------+---------------------------+
-- | Name | Type        | Description               |
-- +======+=============+===========================+
-- | key  | SDL_Keycode | The key that was pressed. |
-- +------+-------------+---------------------------+

function EEex_Key_AddPressedListener(func)
	table.insert(EEex_Key_PressedListeners, func)
end

EEex_Key_ReleasedListeners = {}

-- @bubb_doc { EEex_Key_AddReleasedListener }
--
-- @summary: Registers a listener function that is called whenever a key is released. See `SDL_Keycode`_ for valid ``key`` values.
--
-- @param { func / type=function }: The listener to register.
--
-- @extra_comment:
--
-- ===============================================================================================================================
--
-- The listener function
-- """""""""""""""""""""
--
-- **Parameters:**
--
-- +------+-------------+----------------------------+
-- | Name | Type        | Description                |
-- +======+=============+============================+
-- | key  | SDL_Keycode | The key that was released. |
-- +------+-------------+----------------------------+

function EEex_Key_AddReleasedListener(func)
	table.insert(EEex_Key_ReleasedListeners, func)
end

EEex_Key_Private_CaptureFunc = nil

function EEex_Key_EnterCaptureMode(func)
	EEex_Key_Private_CaptureFunc = func
end

function EEex_Key_ExitCaptureMode()
	EEex_Key_Private_CaptureFunc = nil
end

EEex_Key_Private_PressedStack = {}
EEex_Key_Private_PressedStackSize = 0

function EEex_Key_GetPressedStack()
	return EEex.DeepCopy(EEex_Key_Private_PressedStack)
end

function EEex_Key_GetPressedCount()
	return EEex_Key_Private_PressedStackSize
end

-----------
-- Hooks --
-----------

function EEex_Key_Private_RemoveFromPressedStack(key)
	local foundI = EEex_Utility_Find(EEex_Key_Private_PressedStack, key)
	if foundI == nil then return end
	table.remove(EEex_Key_Private_PressedStack, foundI)
	EEex_Key_Private_PressedStackSize = EEex_Key_Private_PressedStackSize - 1
end

function EEex_Key_Private_OnPressed(key, bRepeat)

	if EEex_Key_Private_CaptureFunc ~= nil then
		if not bRepeat then
			EEex_Key_Private_CaptureFunc(key)
		end
		return true -- Consume event
	end

	EEex_Key_IsDownMap[key] = true

	if not bRepeat then

		EEex_Key_Private_PressedStackSize = EEex_Key_Private_PressedStackSize + 1
		EEex_Key_Private_PressedStack[EEex_Key_Private_PressedStackSize] = key

		for i, func in ipairs(EEex_Key_PressedListeners) do
			if func(key) then
				return true -- Consume event
			end
		end
	end
end

function EEex_Key_Private_OnReleased(key)

	-- Always remove, even if in capture mode, so keys pressed before a capture mode
	-- and released during the capture mode don't become "permanently" stuck down.
	EEex_Key_IsDownMap[key] = false
	EEex_Key_Private_RemoveFromPressedStack(key)

	if EEex_Key_Private_CaptureFunc ~= nil then
		return true -- Consume event
	end

	for i, func in ipairs(EEex_Key_ReleasedListeners) do
		if func(key) then
			return true -- Consume event
		end
	end
end

function EEex_Key_Hook_AfterEventsPoll(event)
	if event.type == SDL_EventType.SDL_KEYDOWN then
		return EEex_Key_Private_OnPressed(event.key.keysym.sym, event.key["repeat"] ~= 0)
	elseif event.type == SDL_EventType.SDL_KEYUP then
		return EEex_Key_Private_OnReleased(event.key.keysym.sym)
	end
end
