// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: CC-BY-NC-ND-4.0

#pragma once

#include "common/types.h"

#include <array>
#include <cstring>
#include <map>
#include <optional>
#include <string_view>

#include "SDL3/SDL.h"

namespace SDLKeyNames {

static const std::map<int, const char*> s_sdl_key_names = {
  {SDLK_RETURN, "Return"},
  {SDLK_ESCAPE, "Escape"},
  {SDLK_BACKSPACE, "Backspace"},
  {SDLK_TAB, "Tab"},
  {SDLK_SPACE, "Space"},
  {SDLK_EXCLAIM, "Exclam"},
  {SDLK_DBLAPOSTROPHE, "QuoteDbl"},
  {SDLK_HASH, "Hash"},
  {SDLK_PERCENT, "Percent"},
  {SDLK_DOLLAR, "Dollar"},
  {SDLK_AMPERSAND, "Ampersand"},
  {SDLK_APOSTROPHE, "Apostrophe"},
  {SDLK_LEFTPAREN, "ParenLeft"},
  {SDLK_RIGHTPAREN, "ParenRight"},
  {SDLK_ASTERISK, "Asterisk"},
  {SDLK_PLUS, "PLus"},
  {SDLK_COMMA, "Comma"},
  {SDLK_MINUS, "Minus"},
  {SDLK_PERIOD, "Period"},
  {SDLK_SLASH, "Slash"},
  {SDLK_0, "0"},
  {SDLK_1, "1"},
  {SDLK_2, "2"},
  {SDLK_3, "3"},
  {SDLK_4, "4"},
  {SDLK_5, "5"},
  {SDLK_6, "6"},
  {SDLK_7, "7"},
  {SDLK_8, "8"},
  {SDLK_9, "9"},
  {SDLK_COLON, "Colon"},
  {SDLK_SEMICOLON, "Semcolon"},
  {SDLK_LESS, "Less"},
  {SDLK_EQUALS, "Equal"},
  {SDLK_GREATER, "Greater"},
  {SDLK_QUESTION, "Question"},
  {SDLK_AT, "AT"},
  {SDLK_LEFTBRACKET, "BracketLeft"},
  {SDLK_BACKSLASH, "Backslash"},
  {SDLK_RIGHTBRACKET, "BracketRight"},
  {SDLK_CARET, "Caret"},
  {SDLK_UNDERSCORE, "Underscore"},
  {SDLK_GRAVE, "Backquote"},
  {SDLK_A, "A"},
  {SDLK_B, "B"},
  {SDLK_C, "C"},
  {SDLK_D, "D"},
  {SDLK_E, "E"},
  {SDLK_F, "F"},
  {SDLK_G, "G"},
  {SDLK_H, "H"},
  {SDLK_I, "I"},
  {SDLK_J, "J"},
  {SDLK_K, "K"},
  {SDLK_L, "L"},
  {SDLK_M, "M"},
  {SDLK_N, "N"},
  {SDLK_O, "O"},
  {SDLK_P, "P"},
  {SDLK_Q, "Q"},
  {SDLK_R, "R"},
  {SDLK_S, "S"},
  {SDLK_T, "T"},
  {SDLK_U, "U"},
  {SDLK_V, "V"},
  {SDLK_W, "W"},
  {SDLK_X, "X"},
  {SDLK_Y, "Y"},
  {SDLK_Z, "Z"},
  {SDLK_CAPSLOCK, "CapsLock"},
  {SDLK_F1, "F1"},
  {SDLK_F2, "F2"},
  {SDLK_F3, "F3"},
  {SDLK_F4, "F4"},
  {SDLK_F5, "F5"},
  {SDLK_F6, "F6"},
  {SDLK_F7, "F7"},
  {SDLK_F8, "F8"},
  {SDLK_F9, "F9"},
  {SDLK_F10, "F10"},
  {SDLK_F11, "F11"},
  {SDLK_F12, "F12"},
  {SDLK_PRINTSCREEN, "Print"},
  {SDLK_SCROLLLOCK, "ScrollLock"},
  {SDLK_PAUSE, "Pause"},
  {SDLK_INSERT, "Insert"},
  {SDLK_HOME, "Home"},
  {SDLK_PAGEUP, "PageUp"},
  {SDLK_DELETE, "Delete"},
  {SDLK_END, "End"},
  {SDLK_PAGEDOWN, "PageDown"},
  {SDLK_RIGHT, "Right"},
  {SDLK_LEFT, "Left"},
  {SDLK_DOWN, "Down"},
  {SDLK_UP, "Up"},
  {SDLK_NUMLOCKCLEAR, "NumLock"},
  {SDLK_KP_DIVIDE, "Keypad+Divide"},
  {SDLK_KP_MULTIPLY, "Keypad+Multiply"},
  {SDLK_KP_MINUS, "Keypad+Minus"},
  {SDLK_KP_PLUS, "Keypad+Plus"},
  {SDLK_KP_ENTER, "Keypad+Return"},
  {SDLK_KP_1, "Keypad+1"},
  {SDLK_KP_2, "Keypad+2"},
  {SDLK_KP_3, "Keypad+3"},
  {SDLK_KP_4, "Keypad+4"},
  {SDLK_KP_5, "Keypad+5"},
  {SDLK_KP_6, "Keypad+6"},
  {SDLK_KP_7, "Keypad+7"},
  {SDLK_KP_8, "Keypad+8"},
  {SDLK_KP_9, "Keypad+9"},
  {SDLK_KP_0, "Keypad+0"},
  {SDLK_KP_PERIOD, "Keypad+Period"},
  {SDLK_APPLICATION, "Application"},
  {SDLK_POWER, "Power"},
  {SDLK_KP_EQUALS, "Keypad+Equal"},
  {SDLK_F13, "F13"},
  {SDLK_F14, "F14"},
  {SDLK_F15, "F15"},
  {SDLK_F16, "F16"},
  {SDLK_F17, "F17"},
  {SDLK_F18, "F18"},
  {SDLK_F19, "F19"},
  {SDLK_F20, "F20"},
  {SDLK_F21, "F21"},
  {SDLK_F22, "F22"},
  {SDLK_F23, "F23"},
  {SDLK_F24, "F24"},
  {SDLK_EXECUTE, "Execute"},
  {SDLK_HELP, "Help"},
  {SDLK_MENU, "Menu"},
  {SDLK_SELECT, "Select"},
  {SDLK_STOP, "Stop"},
  {SDLK_AGAIN, "Again"},
  {SDLK_UNDO, "Undo"},
  {SDLK_CUT, "Cut"},
  {SDLK_COPY, "Copy"},
  {SDLK_PASTE, "Paste"},
  {SDLK_FIND, "Find"},
  {SDLK_MUTE, "Mute"},
  {SDLK_VOLUMEUP, "VolumeUp"},
  {SDLK_VOLUMEDOWN, "VolumeDown"},
  {SDLK_KP_COMMA, "Keypad+Comma"},
  {SDLK_KP_EQUALSAS400, "Keypad+EqualAS400"},
  {SDLK_ALTERASE, "AltErase"},
  {SDLK_SYSREQ, "SysReq"},
  {SDLK_CANCEL, "Cancel"},
  {SDLK_CLEAR, "Clear"},
  {SDLK_PRIOR, "Prior"},
  {SDLK_RETURN2, "Return2"},
  {SDLK_SEPARATOR, "Separator"},
  {SDLK_OUT, "Out"},
  {SDLK_OPER, "Oper"},
  {SDLK_CLEARAGAIN, "ClearAgain"},
  {SDLK_CRSEL, "CrSel"},
  {SDLK_EXSEL, "ExSel"},
  {SDLK_KP_00, "Keypad+00"},
  {SDLK_KP_000, "Keypad+000"},
  {SDLK_THOUSANDSSEPARATOR, "ThousandsSeparator"},
  {SDLK_DECIMALSEPARATOR, "DecimalSeparator"},
  {SDLK_CURRENCYUNIT, "CurrencyUnit"},
  {SDLK_CURRENCYSUBUNIT, "CurrencySubunit"},
  {SDLK_KP_LEFTPAREN, "Keypad+ParenLeft"},
  {SDLK_KP_RIGHTPAREN, "Keypad+ParenRight"},
  {SDLK_KP_LEFTBRACE, "Keypad+LeftBrace"},
  {SDLK_KP_RIGHTBRACE, "Keypad+RightBrace"},
  {SDLK_KP_TAB, "Keypad+Tab"},
  {SDLK_KP_BACKSPACE, "Keypad+Backspace"},
  {SDLK_KP_A, "Keypad+A"},
  {SDLK_KP_B, "Keypad+B"},
  {SDLK_KP_C, "Keypad+C"},
  {SDLK_KP_D, "Keypad+D"},
  {SDLK_KP_E, "Keypad+E"},
  {SDLK_KP_F, "Keypad+F"},
  {SDLK_KP_XOR, "Keypad+XOR"},
  {SDLK_KP_POWER, "Keypad+Power"},
  {SDLK_KP_PERCENT, "Keypad+Percent"},
  {SDLK_KP_LESS, "Keypad+Less"},
  {SDLK_KP_GREATER, "Keypad+Greater"},
  {SDLK_KP_AMPERSAND, "Keypad+Ampersand"},
  {SDLK_KP_DBLAMPERSAND, "Keypad+AmpersandDbl"},
  {SDLK_KP_VERTICALBAR, "Keypad+Bar"},
  {SDLK_KP_DBLVERTICALBAR, "Keypad+BarDbl"},
  {SDLK_KP_COLON, "Keypad+Colon"},
  {SDLK_KP_HASH, "Keypad+Hash"},
  {SDLK_KP_SPACE, "Keypad+Space"},
  {SDLK_KP_AT, "Keypad+At"},
  {SDLK_KP_EXCLAM, "Keypad+Exclam"},
  {SDLK_KP_MEMSTORE, "Keypad+MemStore"},
  {SDLK_KP_MEMRECALL, "Keypad+MemRecall"},
  {SDLK_KP_MEMCLEAR, "Keypad+MemClear"},
  {SDLK_KP_MEMADD, "Keypad+MemAdd"},
  {SDLK_KP_MEMSUBTRACT, "Keypad+MemSubtract"},
  {SDLK_KP_MEMMULTIPLY, "Keypad+MemMultiply"},
  {SDLK_KP_MEMDIVIDE, "Keypad+MemDivide"},
  {SDLK_KP_PLUSMINUS, "Keypad+PlusMinus"},
  {SDLK_KP_CLEAR, "Keypad+Clear"},
  {SDLK_KP_CLEARENTRY, "Keypad+ClearEntry"},
  {SDLK_KP_BINARY, "Keypad+Binary"},
  {SDLK_KP_OCTAL, "Keypad+Octal"},
  {SDLK_KP_DECIMAL, "Keypad+Decimal"},
  {SDLK_KP_HEXADECIMAL, "Keypad+Hexadecimal"},
  {SDLK_LCTRL, "LeftControl"},
  {SDLK_LSHIFT, "LeftShift"},
  {SDLK_LALT, "LeftAlt"},
  {SDLK_LGUI, "Super_L"},
  {SDLK_RCTRL, "RightCtrl"},
  {SDLK_RSHIFT, "RightShift"},
  {SDLK_RALT, "RightAlt"},
  {SDLK_RGUI, "RightSuper"},
  {SDLK_MODE, "Mode"},
  {SDLK_MEDIA_NEXT_TRACK, "MediaNext"},
  {SDLK_MEDIA_PREVIOUS_TRACK, "MediaPrevious"},
  {SDLK_MEDIA_STOP, "MediaStop"},
  {SDLK_MEDIA_PLAY, "MediaPlay"},
  {SDLK_MEDIA_PLAY_PAUSE, "MediaPlayPause"},
  {SDLK_MEDIA_SELECT, "MediaSelect"},
  {SDLK_MEDIA_REWIND, "MediaRewind"},
  {SDLK_MEDIA_FAST_FORWARD, "MediaFastForward"},
  {SDLK_MUTE, "VolumeMute"},
  {SDLK_AC_SEARCH, "Search"},
  {SDLK_AC_HOME, "Home"},
  {SDLK_AC_BACK, "Back"},
  {SDLK_AC_FORWARD, "Forward"},
  {SDLK_AC_STOP, "Stop"},
  {SDLK_AC_REFRESH, "Refresh"},
  {SDLK_AC_BOOKMARKS, "Bookmarks"},
  {SDLK_MEDIA_EJECT, "Eject"},
  {SDLK_SLEEP, "Sleep"},
};

static const char* GetKeyName(u32 key)
{
  const auto it = s_sdl_key_names.find(key);
  return it == s_sdl_key_names.end() ? nullptr : it->second;
}

static std::optional<u32> GetKeyCodeForName(const std::string_view& key_name)
{
  for (const auto& it : s_sdl_key_names)
  {
    if (key_name == it.second)
      return it.first;
  }

  return std::nullopt;
}

} // namespace SDLKeyNames
