use anyhow::Result;
use kanata_interception as ic;
use kanata_interception::{KeyState, ScanCode, Stroke};

pub fn start() -> Result<()> {
    let intrcptn = ic::Interception::new().expect(
        "interception driver should init: have you completed the interception driver installation?",
    );
    intrcptn.set_filter(ic::is_keyboard, ic::Filter::KeyFilter(ic::KeyFilter::all()));
    let mut strokes = [ic::Stroke::Keyboard {
        code: ic::ScanCode::Esc,
        state: ic::KeyState::empty(),
        information: 0,
    }; 32];

    log::info!("interception attached, you can type now");
    loop {
        let dev = intrcptn.wait_with_timeout(std::time::Duration::from_millis(1));
        if dev > 0 {
            let num_strokes = intrcptn.receive(dev, &mut strokes);
            let num_strokes = num_strokes as usize;

            for i in 0..num_strokes {
                log::info!(
                    "got stroke {:?}: num: {}",
                    strokes[i],
                    OsCode::try_from(strokes[i])
                        .map(|osc| osc.as_u16().to_string())
                        .unwrap_or_else(|_| {
                            "unknown mapping! please file a bug containing these logs".into()
                        })
                );
                intrcptn.send(dev, &strokes[i..i + 1]);
            }
        }
    }
}

impl TryFrom<Stroke> for OsCode {
    type Error = ();

    fn try_from(item: Stroke) -> Result<Self, Self::Error> {
        Ok(match item {
            Stroke::Keyboard { code, state, .. } => {
                match (state.contains(KeyState::E0), state.contains(KeyState::E1)) {
                    (false, false) => {
                        match code {
                            ScanCode::Esc => OsCode::KEY_ESC,
                            ScanCode::Num1 => OsCode::KEY_1,
                            ScanCode::Num2 => OsCode::KEY_2,
                            ScanCode::Num3 => OsCode::KEY_3,
                            ScanCode::Num4 => OsCode::KEY_4,
                            ScanCode::Num5 => OsCode::KEY_5,
                            ScanCode::Num6 => OsCode::KEY_6,
                            ScanCode::Num7 => OsCode::KEY_7,
                            ScanCode::Num8 => OsCode::KEY_8,
                            ScanCode::Num9 => OsCode::KEY_9,
                            ScanCode::Num0 => OsCode::KEY_0,
                            ScanCode::Minus => OsCode::KEY_MINUS,
                            ScanCode::Equals => OsCode::KEY_EQUAL,
                            ScanCode::Backspace => OsCode::KEY_BACKSPACE,
                            ScanCode::Tab => OsCode::KEY_TAB,
                            ScanCode::Q => OsCode::KEY_Q,
                            ScanCode::W => OsCode::KEY_W,
                            ScanCode::E => OsCode::KEY_E,
                            ScanCode::R => OsCode::KEY_R,
                            ScanCode::T => OsCode::KEY_T,
                            ScanCode::Y => OsCode::KEY_Y,
                            ScanCode::U => OsCode::KEY_U,
                            ScanCode::I => OsCode::KEY_I,
                            ScanCode::O => OsCode::KEY_O,
                            ScanCode::P => OsCode::KEY_P,
                            ScanCode::LeftBracket => OsCode::KEY_LEFTBRACE,
                            ScanCode::RightBracket => OsCode::KEY_RIGHTBRACE,
                            ScanCode::Enter => OsCode::KEY_ENTER,
                            ScanCode::LeftControl => OsCode::KEY_LEFTCTRL,
                            ScanCode::A => OsCode::KEY_A,
                            ScanCode::S => OsCode::KEY_S,
                            ScanCode::D => OsCode::KEY_D,
                            ScanCode::F => OsCode::KEY_F,
                            ScanCode::G => OsCode::KEY_G,
                            ScanCode::H => OsCode::KEY_H,
                            ScanCode::J => OsCode::KEY_J,
                            ScanCode::K => OsCode::KEY_K,
                            ScanCode::L => OsCode::KEY_L,
                            ScanCode::SemiColon => OsCode::KEY_SEMICOLON,
                            ScanCode::Apostrophe => OsCode::KEY_APOSTROPHE,
                            ScanCode::Grave => OsCode::KEY_GRAVE,
                            ScanCode::LeftShift => OsCode::KEY_LEFTSHIFT,
                            ScanCode::BackSlash => OsCode::KEY_BACKSLASH,
                            ScanCode::Z => OsCode::KEY_Z,
                            ScanCode::X => OsCode::KEY_X,
                            ScanCode::C => OsCode::KEY_C,
                            ScanCode::V => OsCode::KEY_V,
                            ScanCode::B => OsCode::KEY_B,
                            ScanCode::N => OsCode::KEY_N,
                            ScanCode::M => OsCode::KEY_M,
                            ScanCode::Comma => OsCode::KEY_COMMA,
                            ScanCode::Period => OsCode::KEY_DOT,
                            ScanCode::Slash => OsCode::KEY_SLASH,
                            ScanCode::RightShift => OsCode::KEY_RIGHTSHIFT,
                            ScanCode::NumpadMultiply => OsCode::KEY_KPASTERISK,
                            ScanCode::LeftAlt => OsCode::KEY_LEFTALT,
                            ScanCode::Space => OsCode::KEY_SPACE,
                            ScanCode::CapsLock => OsCode::KEY_CAPSLOCK,
                            ScanCode::F1 => OsCode::KEY_F1,
                            ScanCode::F2 => OsCode::KEY_F2,
                            ScanCode::F3 => OsCode::KEY_F3,
                            ScanCode::F4 => OsCode::KEY_F4,
                            ScanCode::F5 => OsCode::KEY_F5,
                            ScanCode::F6 => OsCode::KEY_F6,
                            ScanCode::F7 => OsCode::KEY_F7,
                            ScanCode::F8 => OsCode::KEY_F8,
                            ScanCode::F9 => OsCode::KEY_F9,
                            ScanCode::F10 => OsCode::KEY_F10,
                            ScanCode::NumLock => OsCode::KEY_NUMLOCK,
                            ScanCode::ScrollLock => OsCode::KEY_SCROLLLOCK,
                            ScanCode::Numpad7 => OsCode::KEY_KP7,
                            ScanCode::Numpad8 => OsCode::KEY_KP8,
                            ScanCode::Numpad9 => OsCode::KEY_KP9,
                            ScanCode::NumpadMinus => OsCode::KEY_KPMINUS,
                            ScanCode::Numpad4 => OsCode::KEY_KP4,
                            ScanCode::Numpad5 => OsCode::KEY_KP5,
                            ScanCode::Numpad6 => OsCode::KEY_KP6,
                            ScanCode::NumpadPlus => OsCode::KEY_KPPLUS,
                            ScanCode::Numpad1 => OsCode::KEY_KP1,
                            ScanCode::Numpad2 => OsCode::KEY_KP2,
                            ScanCode::Numpad3 => OsCode::KEY_KP3,
                            ScanCode::Numpad0 => OsCode::KEY_KP0,
                            ScanCode::NumpadPeriod => OsCode::KEY_KPDOT,
                            ScanCode::Int1 => OsCode::KEY_102ND, /* Key between the left shift and Z. */
                            ScanCode::F11 => OsCode::KEY_F11,
                            ScanCode::F12 => OsCode::KEY_F12,
                            ScanCode::F13 => OsCode::KEY_F13,
                            ScanCode::F14 => OsCode::KEY_F14,
                            ScanCode::F15 => OsCode::KEY_F15,
                            ScanCode::F16 => OsCode::KEY_F16,
                            ScanCode::F17 => OsCode::KEY_F17,
                            ScanCode::F18 => OsCode::KEY_F18,
                            ScanCode::F19 => OsCode::KEY_F19,
                            ScanCode::F20 => OsCode::KEY_F20,
                            ScanCode::F21 => OsCode::KEY_F21,
                            ScanCode::F22 => OsCode::KEY_F22,
                            ScanCode::F23 => OsCode::KEY_F23,
                            ScanCode::F24 => OsCode::KEY_F24,
                            ScanCode::Katakana => OsCode::KEY_KATAKANA,
                            // Note: the OEM keys below don't seem to correspond to the same VK OEM
                            // mappings as the LLHOOK codes.
                            // ScanCode::Oem1 = 0x5A, /* VK_OEM_WSCTRL */
                            // ScanCode::Oem2 = 0x5B, /* VK_OEM_FINISH */
                            // ScanCode::Oem3 = 0x5C, /* VK_OEM_JUMP */
                            // ScanCode::Oem4 = 0x5E, /* VK_OEM_BACKTAB */
                            // ScanCode::Oem5 = 0x5F, /* VK_OEM_AUTO */
                            // ScanCode::Oem6 = 0x6F, /* VK_OEM_PA3 */
                            // ScanCode::Oem7 = 0x71, /* VK_OEM_RESET */
                            // ScanCode::EraseEOF = 0x5D,
                            // ScanCode::Zoom => 0x62,
                            // ScanCode::Help => 0x63,
                            // ScanCode::AltPrintScreen = 0x55, /* Alt + print screen. */
                            // ScanCode::SBCSChar = 0x77,
                            // ScanCode::Convert = 0x79,
                            // ScanCode::NonConvert = 0x7B,
                            _ => return Err(()),
                        }
                    }

                    (true, _) => {
                        match code as u8 {
                            0x10 => OsCode::KEY_PREVIOUSSONG,
                            0x19 => OsCode::KEY_NEXTSONG,
                            0x1C => OsCode::KEY_KPENTER,
                            0x1D => OsCode::KEY_RIGHTCTRL,
                            0x20 => OsCode::KEY_MUTE,
                            0x22 => OsCode::KEY_PLAYPAUSE, // sc_media_play
                            // 0x24 => OsCode::KEY_TODO, // sc_media_stop
                            0x2E => OsCode::KEY_VOLUMEDOWN, // sc_volume_down
                            0x30 => OsCode::KEY_VOLUMEUP,   // sc_volume_up
                            // 0x32 => OsCode::KEY_TODO, // sc_browser_home
                            0x35 => OsCode::KEY_KPSLASH, // sc_numpad_divide
                            0x37 => OsCode::KEY_PRINT,   // sc_printScreen
                            0x38 => OsCode::KEY_RIGHTALT, // sc_altRight
                            // 0x46 => OsCode::KEY_TODO, // sc_cancel
                            0x47 => OsCode::KEY_HOME,      // sc_home
                            0x48 => OsCode::KEY_UP,        // sc_arrowUp
                            0x49 => OsCode::KEY_PAGEUP,    // sc_pageUp
                            0x4B => OsCode::KEY_LEFT,      // sc_arrowLeft
                            0x4D => OsCode::KEY_RIGHT,     // sc_arrowRight
                            0x4F => OsCode::KEY_END,       // sc_end
                            0x50 => OsCode::KEY_DOWN,      // sc_arrowDown
                            0x51 => OsCode::KEY_PAGEDOWN,  // sc_pageDown
                            0x52 => OsCode::KEY_INSERT,    // sc_insert
                            0x53 => OsCode::KEY_DELETE,    // sc_delete
                            0x5B => OsCode::KEY_LEFTMETA,  // sc_metaLeft
                            0x5C => OsCode::KEY_RIGHTMETA, // sc_metaRight
                            // 0x5D => OsCode::KEY_TODO, // sc_application
                            // 0x5E => OsCode::KEY_TODO, // sc_power
                            // 0x5F => OsCode::KEY_TODO, // sc_sleep
                            // 0x63 => OsCode::KEY_TODO, // sc_wake
                            // 0x65 => OsCode::KEY_TODO, // sc_browser_search
                            // 0x66 => OsCode::KEY_TODO, // sc_browser_favorites
                            // 0x67 => OsCode::KEY_TODO, // sc_browser_refresh
                            // 0x68 => OsCode::KEY_TODO, // sc_browser_stop
                            0x69 => OsCode::KEY_FORWARD, // sc_browser_forward
                            0x6A => OsCode::KEY_BACK,    // sc_browser_back
                            // 0x6B => OsCode::KEY_TODO, // sc_launch_app1
                            // 0x6C => OsCode::KEY_TODO, // sc_launch_email
                            // 0x6D => OsCode::KEY_TODO, // sc_launch_media
                            _ => return Err(()),
                        }
                    }

                    _ => return Err(()),
                }
            }
            _ => return Err(()),
        })
    }
}

#[allow(unused)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum OsCode {
    KEY_RESERVED = 0,
    KEY_ESC = 1,
    KEY_1 = 2,
    KEY_2 = 3,
    KEY_3 = 4,
    KEY_4 = 5,
    KEY_5 = 6,
    KEY_6 = 7,
    KEY_7 = 8,
    KEY_8 = 9,
    KEY_9 = 10,
    KEY_0 = 11,
    KEY_MINUS = 12,
    KEY_EQUAL = 13,
    KEY_BACKSPACE = 14,
    KEY_TAB = 15,
    KEY_Q = 16,
    KEY_W = 17,
    KEY_E = 18,
    KEY_R = 19,
    KEY_T = 20,
    KEY_Y = 21,
    KEY_U = 22,
    KEY_I = 23,
    KEY_O = 24,
    KEY_P = 25,
    KEY_LEFTBRACE = 26,
    KEY_RIGHTBRACE = 27,
    KEY_ENTER = 28,
    KEY_LEFTCTRL = 29,
    KEY_A = 30,
    KEY_S = 31,
    KEY_D = 32,
    KEY_F = 33,
    KEY_G = 34,
    KEY_H = 35,
    KEY_J = 36,
    KEY_K = 37,
    KEY_L = 38,
    KEY_SEMICOLON = 39,
    KEY_APOSTROPHE = 40,
    KEY_GRAVE = 41,
    KEY_LEFTSHIFT = 42,
    KEY_BACKSLASH = 43,
    KEY_Z = 44,
    KEY_X = 45,
    KEY_C = 46,
    KEY_V = 47,
    KEY_B = 48,
    KEY_N = 49,
    KEY_M = 50,
    KEY_COMMA = 51,
    KEY_DOT = 52,
    KEY_SLASH = 53,
    KEY_RIGHTSHIFT = 54,
    KEY_KPASTERISK = 55,
    KEY_LEFTALT = 56,
    KEY_SPACE = 57,
    KEY_CAPSLOCK = 58,
    KEY_F1 = 59,
    KEY_F2 = 60,
    KEY_F3 = 61,
    KEY_F4 = 62,
    KEY_F5 = 63,
    KEY_F6 = 64,
    KEY_F7 = 65,
    KEY_F8 = 66,
    KEY_F9 = 67,
    KEY_F10 = 68,
    KEY_NUMLOCK = 69,
    KEY_SCROLLLOCK = 70,
    KEY_KP7 = 71,
    KEY_KP8 = 72,
    KEY_KP9 = 73,
    KEY_KPMINUS = 74,
    KEY_KP4 = 75,
    KEY_KP5 = 76,
    KEY_KP6 = 77,
    KEY_KPPLUS = 78,
    KEY_KP1 = 79,
    KEY_KP2 = 80,
    KEY_KP3 = 81,
    KEY_KP0 = 82,
    KEY_KPDOT = 83,
    KEY_ZENKAKUHANKAKU = 85,
    KEY_102ND = 86,
    KEY_F11 = 87,
    KEY_F12 = 88,
    KEY_RO = 89,
    KEY_KATAKANA = 90,
    KEY_HIRAGANA = 91,
    KEY_HENKAN = 92,
    KEY_KATAKANAHIRAGANA = 93,
    KEY_MUHENKAN = 94,
    KEY_KPJPCOMMA = 95,
    KEY_KPENTER = 96,
    KEY_RIGHTCTRL = 97,
    KEY_KPSLASH = 98,
    KEY_SYSRQ = 99,
    KEY_RIGHTALT = 100,
    KEY_LINEFEED = 101,
    KEY_HOME = 102,
    KEY_UP = 103,
    KEY_PAGEUP = 104,
    KEY_LEFT = 105,
    KEY_RIGHT = 106,
    KEY_END = 107,
    KEY_DOWN = 108,
    KEY_PAGEDOWN = 109,
    KEY_INSERT = 110,
    KEY_DELETE = 111,
    KEY_MACRO = 112,
    KEY_MUTE = 113,
    KEY_VOLUMEDOWN = 114,
    KEY_VOLUMEUP = 115,
    KEY_POWER = 116,
    KEY_KPEQUAL = 117,
    KEY_KPPLUSMINUS = 118,
    KEY_PAUSE = 119,
    KEY_SCALE = 120,
    KEY_KPCOMMA = 121,
    KEY_HANGEUL = 122,
    KEY_HANJA = 123,
    KEY_YEN = 124,
    KEY_LEFTMETA = 125,
    KEY_RIGHTMETA = 126,
    KEY_COMPOSE = 127,
    KEY_STOP = 128,
    KEY_AGAIN = 129,
    KEY_PROPS = 130,
    KEY_UNDO = 131,
    KEY_FRONT = 132,
    KEY_COPY = 133,
    KEY_OPEN = 134,
    KEY_PASTE = 135,
    KEY_FIND = 136,
    KEY_CUT = 137,
    KEY_HELP = 138,
    KEY_MENU = 139,
    KEY_CALC = 140,
    KEY_SETUP = 141,
    KEY_SLEEP = 142,
    KEY_WAKEUP = 143,
    KEY_FILE = 144,
    KEY_SENDFILE = 145,
    KEY_DELETEFILE = 146,
    KEY_XFER = 147,
    KEY_PROG1 = 148,
    KEY_PROG2 = 149,
    KEY_WWW = 150,
    KEY_MSDOS = 151,
    KEY_COFFEE = 152,
    KEY_ROTATE_DISPLAY = 153,
    KEY_CYCLEWINDOWS = 154,
    KEY_MAIL = 155,
    KEY_BOOKMARKS = 156,
    KEY_COMPUTER = 157,
    KEY_BACK = 158,
    KEY_FORWARD = 159,
    KEY_CLOSECD = 160,
    KEY_EJECTCD = 161,
    KEY_EJECTCLOSECD = 162,
    KEY_NEXTSONG = 163,
    KEY_PLAYPAUSE = 164,
    KEY_PREVIOUSSONG = 165,
    KEY_STOPCD = 166,
    KEY_RECORD = 167,
    KEY_REWIND = 168,
    KEY_PHONE = 169,
    KEY_ISO = 170,
    KEY_CONFIG = 171,
    KEY_HOMEPAGE = 172,
    KEY_REFRESH = 173,
    KEY_EXIT = 174,
    KEY_MOVE = 175,
    KEY_EDIT = 176,
    KEY_SCROLLUP = 177,
    KEY_SCROLLDOWN = 178,
    KEY_KPLEFTPAREN = 179,
    KEY_KPRIGHTPAREN = 180,
    KEY_NEW = 181,
    KEY_REDO = 182,
    KEY_F13 = 183,
    KEY_F14 = 184,
    KEY_F15 = 185,
    KEY_F16 = 186,
    KEY_F17 = 187,
    KEY_F18 = 188,
    KEY_F19 = 189,
    KEY_F20 = 190,
    KEY_F21 = 191,
    KEY_F22 = 192,
    KEY_F23 = 193,
    KEY_F24 = 194,
    KEY_PLAYCD = 200,
    KEY_PAUSECD = 201,
    KEY_PROG3 = 202,
    KEY_PROG4 = 203,
    KEY_DASHBOARD = 204,
    KEY_SUSPEND = 205,
    KEY_CLOSE = 206,
    KEY_PLAY = 207,
    KEY_FASTFORWARD = 208,
    KEY_BASSBOOST = 209,
    KEY_PRINT = 210,
    KEY_HP = 211,
    KEY_CAMERA = 212,
    KEY_SOUND = 213,
    KEY_QUESTION = 214,
    KEY_EMAIL = 215,
    KEY_CHAT = 216,
    KEY_SEARCH = 217,
    KEY_CONNECT = 218,
    KEY_FINANCE = 219,
    KEY_SPORT = 220,
    KEY_SHOP = 221,
    KEY_ALTERASE = 222,
    KEY_CANCEL = 223,
    KEY_BRIGHTNESSDOWN = 224,
    KEY_BRIGHTNESSUP = 225,
    KEY_MEDIA = 226,
    KEY_SWITCHVIDEOMODE = 227,
    KEY_KBDILLUMTOGGLE = 228,
    KEY_KBDILLUMDOWN = 229,
    KEY_KBDILLUMUP = 230,
    KEY_SEND = 231,
    KEY_REPLY = 232,
    KEY_FORWARDMAIL = 233,
    KEY_SAVE = 234,
    KEY_DOCUMENTS = 235,
    KEY_BATTERY = 236,
    KEY_BLUETOOTH = 237,
    KEY_WLAN = 238,
    KEY_UWB = 239,
    KEY_UNKNOWN = 240,
    KEY_VIDEO_NEXT = 241,
    KEY_VIDEO_PREV = 242,
    KEY_BRIGHTNESS_CYCLE = 243,
    KEY_BRIGHTNESS_AUTO = 244,
    KEY_DISPLAY_OFF = 245,
    KEY_WWAN = 246,
    KEY_RFKILL = 247,
    KEY_MICMUTE = 248,
    KEY_OK = 352,
    KEY_SELECT = 353,
    KEY_GOTO = 354,
    KEY_CLEAR = 355,
    KEY_POWER2 = 356,
    KEY_OPTION = 357,
    KEY_INFO = 358,
    KEY_TIME = 359,
    KEY_VENDOR = 360,
    KEY_ARCHIVE = 361,
    KEY_PROGRAM = 362,
    KEY_CHANNEL = 363,
    KEY_FAVORITES = 364,
    KEY_EPG = 365,
    KEY_PVR = 366,
    KEY_MHP = 367,
    KEY_LANGUAGE = 368,
    KEY_TITLE = 369,
    KEY_SUBTITLE = 370,
    KEY_ANGLE = 371,
    KEY_FULL_SCREEN = 372,
    KEY_MODE = 373,
    KEY_KEYBOARD = 374,
    KEY_ASPECT_RATIO = 375,
    KEY_PC = 376,
    KEY_TV = 377,
    KEY_TV2 = 378,
    KEY_VCR = 379,
    KEY_VCR2 = 380,
    KEY_SAT = 381,
    KEY_SAT2 = 382,
    KEY_CD = 383,
    KEY_TAPE = 384,
    KEY_RADIO = 385,
    KEY_TUNER = 386,
    KEY_PLAYER = 387,
    KEY_TEXT = 388,
    KEY_DVD = 389,
    KEY_AUX = 390,
    KEY_MP3 = 391,
    KEY_AUDIO = 392,
    KEY_VIDEO = 393,
    KEY_DIRECTORY = 394,
    KEY_LIST = 395,
    KEY_MEMO = 396,
    KEY_CALENDAR = 397,
    KEY_RED = 398,
    KEY_GREEN = 399,
    KEY_YELLOW = 400,
    KEY_BLUE = 401,
    KEY_CHANNELUP = 402,
    KEY_CHANNELDOWN = 403,
    KEY_FIRST = 404,
    KEY_LAST = 405,
    KEY_AB = 406,
    KEY_NEXT = 407,
    KEY_RESTART = 408,
    KEY_SLOW = 409,
    KEY_SHUFFLE = 410,
    KEY_BREAK = 411,
    KEY_PREVIOUS = 412,
    KEY_DIGITS = 413,
    KEY_TEEN = 414,
    KEY_TWEN = 415,
    KEY_VIDEOPHONE = 416,
    KEY_GAMES = 417,
    KEY_ZOOMIN = 418,
    KEY_ZOOMOUT = 419,
    KEY_ZOOMRESET = 420,
    KEY_WORDPROCESSOR = 421,
    KEY_EDITOR = 422,
    KEY_SPREADSHEET = 423,
    KEY_GRAPHICSEDITOR = 424,
    KEY_PRESENTATION = 425,
    KEY_DATABASE = 426,
    KEY_NEWS = 427,
    KEY_VOICEMAIL = 428,
    KEY_ADDRESSBOOK = 429,
    KEY_MESSENGER = 430,
    KEY_DISPLAYTOGGLE = 431,
    KEY_SPELLCHECK = 432,
    KEY_LOGOFF = 433,
    KEY_DOLLAR = 434,
    KEY_EURO = 435,
    KEY_FRAMEBACK = 436,
    KEY_FRAMEFORWARD = 437,
    KEY_CONTEXT_MENU = 438,
    KEY_MEDIA_REPEAT = 439,
    KEY_10CHANNELSUP = 440,
    KEY_10CHANNELSDOWN = 441,
    KEY_IMAGES = 442,
    KEY_DEL_EOL = 448,
    KEY_DEL_EOS = 449,
    KEY_INS_LINE = 450,
    KEY_DEL_LINE = 451,
    KEY_FN = 464,
    KEY_FN_ESC = 465,
    KEY_FN_F1 = 466,
    KEY_FN_F2 = 467,
    KEY_FN_F3 = 468,
    KEY_FN_F4 = 469,
    KEY_FN_F5 = 470,
    KEY_FN_F6 = 471,
    KEY_FN_F7 = 472,
    KEY_FN_F8 = 473,
    KEY_FN_F9 = 474,
    KEY_FN_F10 = 475,
    KEY_FN_F11 = 476,
    KEY_FN_F12 = 477,
    KEY_FN_1 = 478,
    KEY_FN_2 = 479,
    KEY_FN_D = 480,
    KEY_FN_E = 481,
    KEY_FN_F = 482,
    KEY_FN_S = 483,
    KEY_FN_B = 484,
    KEY_BRL_DOT1 = 497,
    KEY_BRL_DOT2 = 498,
    KEY_BRL_DOT3 = 499,
    KEY_BRL_DOT4 = 500,
    KEY_BRL_DOT5 = 501,
    KEY_BRL_DOT6 = 502,
    KEY_BRL_DOT7 = 503,
    KEY_BRL_DOT8 = 504,
    KEY_BRL_DOT9 = 505,
    KEY_BRL_DOT10 = 506,
    KEY_NUMERIC_0 = 512,
    KEY_NUMERIC_1 = 513,
    KEY_NUMERIC_2 = 514,
    KEY_NUMERIC_3 = 515,
    KEY_NUMERIC_4 = 516,
    KEY_NUMERIC_5 = 517,
    KEY_NUMERIC_6 = 518,
    KEY_NUMERIC_7 = 519,
    KEY_NUMERIC_8 = 520,
    KEY_NUMERIC_9 = 521,
    KEY_NUMERIC_STAR = 522,
    KEY_NUMERIC_POUND = 523,
    KEY_NUMERIC_A = 524,
    KEY_NUMERIC_B = 525,
    KEY_NUMERIC_C = 526,
    KEY_NUMERIC_D = 527,
    KEY_CAMERA_FOCUS = 528,
    KEY_WPS_BUTTON = 529,
    KEY_TOUCHPAD_TOGGLE = 530,
    KEY_TOUCHPAD_ON = 531,
    KEY_TOUCHPAD_OFF = 532,
    KEY_CAMERA_ZOOMIN = 533,
    KEY_CAMERA_ZOOMOUT = 534,
    KEY_CAMERA_UP = 535,
    KEY_CAMERA_DOWN = 536,
    KEY_CAMERA_LEFT = 537,
    KEY_CAMERA_RIGHT = 538,
    KEY_ATTENDANT_ON = 539,
    KEY_ATTENDANT_OFF = 540,
    KEY_ATTENDANT_TOGGLE = 541,
    KEY_LIGHTS_TOGGLE = 542,
    KEY_ALS_TOGGLE = 560,
    KEY_ROTATE_LOCK_TOGGLE = 561,
    KEY_BUTTONCONFIG = 576,
    KEY_TASKMANAGER = 577,
    KEY_JOURNAL = 578,
    KEY_CONTROLPANEL = 579,
    KEY_APPSELECT = 580,
    KEY_SCREENSAVER = 581,
    KEY_VOICECOMMAND = 582,
    KEY_ASSISTANT = 583,
    KEY_KBD_LAYOUT_NEXT = 584,
    KEY_BRIGHTNESS_MIN = 592,
    KEY_BRIGHTNESS_MAX = 593,
    KEY_KBDINPUTASSIST_PREV = 608,
    KEY_KBDINPUTASSIST_NEXT = 609,
    KEY_KBDINPUTASSIST_PREVGROUP = 610,
    KEY_KBDINPUTASSIST_NEXTGROUP = 611,
    KEY_KBDINPUTASSIST_ACCEPT = 612,
    KEY_KBDINPUTASSIST_CANCEL = 613,
    KEY_RIGHT_UP = 614,
    KEY_RIGHT_DOWN = 615,
    KEY_LEFT_UP = 616,
    KEY_LEFT_DOWN = 617,
    KEY_ROOT_MENU = 618,
    KEY_MEDIA_TOP_MENU = 619,
    KEY_NUMERIC_11 = 620,
    KEY_NUMERIC_12 = 621,
    KEY_AUDIO_DESC = 622,
    KEY_3D_MODE = 623,
    KEY_NEXT_FAVORITE = 624,
    KEY_STOP_RECORD = 625,
    KEY_PAUSE_RECORD = 626,
    KEY_VOD = 627,
    KEY_UNMUTE = 628,
    KEY_FASTREVERSE = 629,
    KEY_SLOWREVERSE = 630,
    KEY_DATA = 631,
    KEY_ONSCREEN_KEYBOARD = 632,
    KEY_MAX = 767,
    BTN_0 = 256,
    BTN_1 = 257,
    BTN_2 = 258,
    BTN_3 = 259,
    BTN_4 = 260,
    BTN_5 = 261,
    BTN_6 = 262,
    BTN_7 = 263,
    BTN_8 = 264,
    BTN_9 = 265,
    BTN_LEFT = 272,
    BTN_RIGHT = 273,
    BTN_MIDDLE = 274,
    BTN_SIDE = 275,
    BTN_EXTRA = 276,
    BTN_FORWARD = 277,
    BTN_BACK = 278,
    BTN_TASK = 279,
    BTN_TRIGGER = 288,
    BTN_THUMB = 289,
    BTN_THUMB2 = 290,
    BTN_TOP = 291,
    BTN_TOP2 = 292,
    BTN_PINKIE = 293,
    BTN_BASE = 294,
    BTN_BASE2 = 295,
    BTN_BASE3 = 296,
    BTN_BASE4 = 297,
    BTN_BASE5 = 298,
    BTN_BASE6 = 299,
    BTN_DEAD = 303,
    BTN_SOUTH = 304,
    BTN_EAST = 305,
    BTN_C = 306,
    BTN_NORTH = 307,
    BTN_WEST = 308,
    BTN_Z = 309,
    BTN_TL = 310,
    BTN_TR = 311,
    BTN_TL2 = 312,
    BTN_TR2 = 313,
    BTN_SELECT = 314,
    BTN_START = 315,
    BTN_MODE = 316,
    BTN_THUMBL = 317,
    BTN_THUMBR = 318,
    BTN_TOOL_PEN = 320,
    BTN_TOOL_RUBBER = 321,
    BTN_TOOL_BRUSH = 322,
    BTN_TOOL_PENCIL = 323,
    BTN_TOOL_AIRBRUSH = 324,
    BTN_TOOL_FINGER = 325,
    BTN_TOOL_MOUSE = 326,
    BTN_TOOL_LENS = 327,
    BTN_TOOL_QUINTTAP = 328,
    BTN_STYLUS3 = 329,
    BTN_TOUCH = 330,
    BTN_STYLUS = 331,
    BTN_STYLUS2 = 332,
    BTN_TOOL_DOUBLETAP = 333,
    BTN_TOOL_TRIPLETAP = 334,
    BTN_TOOL_QUADTAP = 335,
    BTN_GEAR_DOWN = 336,
    BTN_GEAR_UP = 337,
    BTN_DPAD_UP = 544,
    BTN_DPAD_DOWN = 545,
    BTN_DPAD_LEFT = 546,
    BTN_DPAD_RIGHT = 547,
    BTN_TRIGGER_HAPPY1 = 704,
    BTN_TRIGGER_HAPPY2 = 705,
    BTN_TRIGGER_HAPPY3 = 706,
    BTN_TRIGGER_HAPPY4 = 707,
    BTN_TRIGGER_HAPPY5 = 708,
    BTN_TRIGGER_HAPPY6 = 709,
    BTN_TRIGGER_HAPPY7 = 710,
    BTN_TRIGGER_HAPPY8 = 711,
    BTN_TRIGGER_HAPPY9 = 712,
    BTN_TRIGGER_HAPPY10 = 713,
    BTN_TRIGGER_HAPPY11 = 714,
    BTN_TRIGGER_HAPPY12 = 715,
    BTN_TRIGGER_HAPPY13 = 716,
    BTN_TRIGGER_HAPPY14 = 717,
    BTN_TRIGGER_HAPPY15 = 718,
    BTN_TRIGGER_HAPPY16 = 719,
    BTN_TRIGGER_HAPPY17 = 720,
    BTN_TRIGGER_HAPPY18 = 721,
    BTN_TRIGGER_HAPPY19 = 722,
    BTN_TRIGGER_HAPPY20 = 723,
    BTN_TRIGGER_HAPPY21 = 724,
    BTN_TRIGGER_HAPPY22 = 725,
    BTN_TRIGGER_HAPPY23 = 726,
    BTN_TRIGGER_HAPPY24 = 727,
    BTN_TRIGGER_HAPPY25 = 728,
    BTN_TRIGGER_HAPPY26 = 729,
    BTN_TRIGGER_HAPPY27 = 730,
    BTN_TRIGGER_HAPPY28 = 731,
    BTN_TRIGGER_HAPPY29 = 732,
    BTN_TRIGGER_HAPPY30 = 733,
    BTN_TRIGGER_HAPPY31 = 734,
    BTN_TRIGGER_HAPPY32 = 735,
    BTN_TRIGGER_HAPPY33 = 736,
    BTN_TRIGGER_HAPPY34 = 737,
    BTN_TRIGGER_HAPPY35 = 738,
    BTN_TRIGGER_HAPPY36 = 739,
    BTN_TRIGGER_HAPPY37 = 740,
    BTN_TRIGGER_HAPPY38 = 741,
    BTN_TRIGGER_HAPPY39 = 742,
    BTN_TRIGGER_HAPPY40 = 743,
    BTN_MAX = 744,
}

#[allow(unused)]
mod keys {
    // Taken from:
    // https://github.com/retep998/winapi-rs/blob/0.3/src/um/winuser.rs#L253
    pub const VK_LBUTTON: u16 = 0x01;
    pub const VK_RBUTTON: u16 = 0x02;
    pub const VK_CANCEL: u16 = 0x03;
    pub const VK_MBUTTON: u16 = 0x04;
    pub const VK_XBUTTON1: u16 = 0x05;
    pub const VK_XBUTTON2: u16 = 0x06;
    pub const VK_BACK: u16 = 0x08;
    pub const VK_TAB: u16 = 0x09;
    pub const VK_CLEAR: u16 = 0x0C;
    pub const VK_RETURN: u16 = 0x0D;
    pub const VK_SHIFT: u16 = 0x10;
    pub const VK_CONTROL: u16 = 0x11;
    pub const VK_MENU: u16 = 0x12;
    pub const VK_PAUSE: u16 = 0x13;
    pub const VK_CAPITAL: u16 = 0x14;
    pub const VK_KANA: u16 = 0x15;
    pub const VK_HANGEUL: u16 = 0x15;
    pub const VK_HANGUL: u16 = 0x15;
    pub const VK_JUNJA: u16 = 0x17;
    pub const VK_FINAL: u16 = 0x18;
    pub const VK_HANJA: u16 = 0x19;
    pub const VK_KANJI: u16 = 0x19;
    pub const VK_ESCAPE: u16 = 0x1B;
    pub const VK_CONVERT: u16 = 0x1C;
    pub const VK_NONCONVERT: u16 = 0x1D;
    pub const VK_ACCEPT: u16 = 0x1E;
    pub const VK_MODECHANGE: u16 = 0x1F;
    pub const VK_SPACE: u16 = 0x20;
    pub const VK_PRIOR: u16 = 0x21;
    pub const VK_NEXT: u16 = 0x22;
    pub const VK_END: u16 = 0x23;
    pub const VK_HOME: u16 = 0x24;
    pub const VK_LEFT: u16 = 0x25;
    pub const VK_UP: u16 = 0x26;
    pub const VK_RIGHT: u16 = 0x27;
    pub const VK_DOWN: u16 = 0x28;
    pub const VK_SELECT: u16 = 0x29;
    pub const VK_PRINT: u16 = 0x2A;
    pub const VK_EXECUTE: u16 = 0x2B;
    pub const VK_SNAPSHOT: u16 = 0x2C;
    pub const VK_INSERT: u16 = 0x2D;
    pub const VK_DELETE: u16 = 0x2E;
    pub const VK_HELP: u16 = 0x2F;
    pub const VK_LWIN: u16 = 0x5B;
    pub const VK_RWIN: u16 = 0x5C;
    pub const VK_APPS: u16 = 0x5D;
    pub const VK_SLEEP: u16 = 0x5F;
    pub const VK_NUMPAD0: u16 = 0x60;
    pub const VK_NUMPAD1: u16 = 0x61;
    pub const VK_NUMPAD2: u16 = 0x62;
    pub const VK_NUMPAD3: u16 = 0x63;
    pub const VK_NUMPAD4: u16 = 0x64;
    pub const VK_NUMPAD5: u16 = 0x65;
    pub const VK_NUMPAD6: u16 = 0x66;
    pub const VK_NUMPAD7: u16 = 0x67;
    pub const VK_NUMPAD8: u16 = 0x68;
    pub const VK_NUMPAD9: u16 = 0x69;
    pub const VK_MULTIPLY: u16 = 0x6A;
    pub const VK_ADD: u16 = 0x6B;
    pub const VK_SEPARATOR: u16 = 0x6C;
    pub const VK_SUBTRACT: u16 = 0x6D;
    pub const VK_DECIMAL: u16 = 0x6E;
    pub const VK_DIVIDE: u16 = 0x6F;
    pub const VK_F1: u16 = 0x70;
    pub const VK_F2: u16 = 0x71;
    pub const VK_F3: u16 = 0x72;
    pub const VK_F4: u16 = 0x73;
    pub const VK_F5: u16 = 0x74;
    pub const VK_F6: u16 = 0x75;
    pub const VK_F7: u16 = 0x76;
    pub const VK_F8: u16 = 0x77;
    pub const VK_F9: u16 = 0x78;
    pub const VK_F10: u16 = 0x79;
    pub const VK_F11: u16 = 0x7A;
    pub const VK_F12: u16 = 0x7B;
    pub const VK_F13: u16 = 0x7C;
    pub const VK_F14: u16 = 0x7D;
    pub const VK_F15: u16 = 0x7E;
    pub const VK_F16: u16 = 0x7F;
    pub const VK_F17: u16 = 0x80;
    pub const VK_F18: u16 = 0x81;
    pub const VK_F19: u16 = 0x82;
    pub const VK_F20: u16 = 0x83;
    pub const VK_F21: u16 = 0x84;
    pub const VK_F22: u16 = 0x85;
    pub const VK_F23: u16 = 0x86;
    pub const VK_F24: u16 = 0x87;
    pub const VK_NAVIGATION_VIEW: u16 = 0x88;
    pub const VK_NAVIGATION_MENU: u16 = 0x89;
    pub const VK_NAVIGATION_UP: u16 = 0x8A;
    pub const VK_NAVIGATION_DOWN: u16 = 0x8B;
    pub const VK_NAVIGATION_LEFT: u16 = 0x8C;
    pub const VK_NAVIGATION_RIGHT: u16 = 0x8D;
    pub const VK_NAVIGATION_ACCEPT: u16 = 0x8E;
    pub const VK_NAVIGATION_CANCEL: u16 = 0x8F;
    pub const VK_NUMLOCK: u16 = 0x90;
    pub const VK_SCROLL: u16 = 0x91;
    pub const VK_OEM_NEC_EQUAL: u16 = 0x92;
    pub const VK_OEM_FJ_JISHO: u16 = 0x92;
    pub const VK_OEM_FJ_MASSHOU: u16 = 0x93;
    pub const VK_OEM_FJ_TOUROKU: u16 = 0x94;
    pub const VK_OEM_FJ_LOYA: u16 = 0x95;
    pub const VK_OEM_FJ_ROYA: u16 = 0x96;
    pub const VK_LSHIFT: u16 = 0xA0;
    pub const VK_RSHIFT: u16 = 0xA1;
    pub const VK_LCONTROL: u16 = 0xA2;
    pub const VK_RCONTROL: u16 = 0xA3;
    pub const VK_LMENU: u16 = 0xA4;
    pub const VK_RMENU: u16 = 0xA5;
    pub const VK_BROWSER_BACK: u16 = 0xA6;
    pub const VK_BROWSER_FORWARD: u16 = 0xA7;
    pub const VK_BROWSER_REFRESH: u16 = 0xA8;
    pub const VK_BROWSER_STOP: u16 = 0xA9;
    pub const VK_BROWSER_SEARCH: u16 = 0xAA;
    pub const VK_BROWSER_FAVORITES: u16 = 0xAB;
    pub const VK_BROWSER_HOME: u16 = 0xAC;
    pub const VK_VOLUME_MUTE: u16 = 0xAD;
    pub const VK_VOLUME_DOWN: u16 = 0xAE;
    pub const VK_VOLUME_UP: u16 = 0xAF;
    pub const VK_MEDIA_NEXT_TRACK: u16 = 0xB0;
    pub const VK_MEDIA_PREV_TRACK: u16 = 0xB1;
    pub const VK_MEDIA_STOP: u16 = 0xB2;
    pub const VK_MEDIA_PLAY_PAUSE: u16 = 0xB3;
    pub const VK_LAUNCH_MAIL: u16 = 0xB4;
    pub const VK_LAUNCH_MEDIA_SELECT: u16 = 0xB5;
    pub const VK_LAUNCH_APP1: u16 = 0xB6;
    pub const VK_LAUNCH_APP2: u16 = 0xB7;
    pub const VK_OEM_1: u16 = 0xBA;
    pub const VK_OEM_PLUS: u16 = 0xBB;
    pub const VK_OEM_COMMA: u16 = 0xBC;
    pub const VK_OEM_MINUS: u16 = 0xBD;
    pub const VK_OEM_PERIOD: u16 = 0xBE;
    pub const VK_OEM_2: u16 = 0xBF;
    pub const VK_OEM_3: u16 = 0xC0;
    pub const VK_GAMEPAD_A: u16 = 0xC3;
    pub const VK_GAMEPAD_B: u16 = 0xC4;
    pub const VK_GAMEPAD_X: u16 = 0xC5;
    pub const VK_GAMEPAD_Y: u16 = 0xC6;
    pub const VK_GAMEPAD_RIGHT_SHOULDER: u16 = 0xC7;
    pub const VK_GAMEPAD_LEFT_SHOULDER: u16 = 0xC8;
    pub const VK_GAMEPAD_LEFT_TRIGGER: u16 = 0xC9;
    pub const VK_GAMEPAD_RIGHT_TRIGGER: u16 = 0xCA;
    pub const VK_GAMEPAD_DPAD_UP: u16 = 0xCB;
    pub const VK_GAMEPAD_DPAD_DOWN: u16 = 0xCC;
    pub const VK_GAMEPAD_DPAD_LEFT: u16 = 0xCD;
    pub const VK_GAMEPAD_DPAD_RIGHT: u16 = 0xCE;
    pub const VK_GAMEPAD_MENU: u16 = 0xCF;
    pub const VK_GAMEPAD_VIEW: u16 = 0xD0;
    pub const VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON: u16 = 0xD1;
    pub const VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON: u16 = 0xD2;
    pub const VK_GAMEPAD_LEFT_THUMBSTICK_UP: u16 = 0xD3;
    pub const VK_GAMEPAD_LEFT_THUMBSTICK_DOWN: u16 = 0xD4;
    pub const VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT: u16 = 0xD5;
    pub const VK_GAMEPAD_LEFT_THUMBSTICK_LEFT: u16 = 0xD6;
    pub const VK_GAMEPAD_RIGHT_THUMBSTICK_UP: u16 = 0xD7;
    pub const VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN: u16 = 0xD8;
    pub const VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT: u16 = 0xD9;
    pub const VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT: u16 = 0xDA;
    pub const VK_OEM_4: u16 = 0xDB;
    pub const VK_OEM_5: u16 = 0xDC;
    pub const VK_OEM_6: u16 = 0xDD;
    pub const VK_OEM_7: u16 = 0xDE;
    pub const VK_OEM_8: u16 = 0xDF;
    pub const VK_OEM_AX: u16 = 0xE1;
    pub const VK_OEM_102: u16 = 0xE2;
    pub const VK_ICO_HELP: u16 = 0xE3;
    pub const VK_ICO_00: u16 = 0xE4;
    pub const VK_PROCESSKEY: u16 = 0xE5;
    pub const VK_ICO_CLEAR: u16 = 0xE6;
    pub const VK_PACKET: u16 = 0xE7;
    pub const VK_OEM_RESET: u16 = 0xE9;
    pub const VK_OEM_JUMP: u16 = 0xEA;
    pub const VK_OEM_PA1: u16 = 0xEB;
    pub const VK_OEM_PA2: u16 = 0xEC;
    pub const VK_OEM_PA3: u16 = 0xED;
    pub const VK_OEM_WSCTRL: u16 = 0xEE;
    pub const VK_OEM_CUSEL: u16 = 0xEF;
    pub const VK_OEM_ATTN: u16 = 0xF0;
    pub const VK_OEM_FINISH: u16 = 0xF1;
    pub const VK_OEM_COPY: u16 = 0xF2;
    pub const VK_OEM_AUTO: u16 = 0xF3;
    pub const VK_OEM_ENLW: u16 = 0xF4;
    pub const VK_OEM_BACKTAB: u16 = 0xF5;
    pub const VK_ATTN: u16 = 0xF6;
    pub const VK_CRSEL: u16 = 0xF7;
    pub const VK_EXSEL: u16 = 0xF8;
    pub const VK_EREOF: u16 = 0xF9;
    pub const VK_PLAY: u16 = 0xFA;
    pub const VK_ZOOM: u16 = 0xFB;
    pub const VK_NONAME: u16 = 0xFC;
    pub const VK_PA1: u16 = 0xFD;
    pub const VK_OEM_CLEAR: u16 = 0xFE;
}

use keys::*;

impl OsCode {
    pub fn as_u16(self) -> u16 {
        match self {
            OsCode::KEY_0 => 0x30,
            OsCode::KEY_1 => 0x31,
            OsCode::KEY_2 => 0x32,
            OsCode::KEY_3 => 0x33,
            OsCode::KEY_4 => 0x34,
            OsCode::KEY_5 => 0x35,
            OsCode::KEY_6 => 0x36,
            OsCode::KEY_7 => 0x37,
            OsCode::KEY_8 => 0x38,
            OsCode::KEY_9 => 0x39,
            OsCode::KEY_A => 0x41,
            OsCode::KEY_B => 0x42,
            OsCode::KEY_C => 0x43,
            OsCode::KEY_D => 0x44,
            OsCode::KEY_E => 0x45,
            OsCode::KEY_F => 0x46,
            OsCode::KEY_G => 0x47,
            OsCode::KEY_H => 0x48,
            OsCode::KEY_I => 0x49,
            OsCode::KEY_J => 0x4A,
            OsCode::KEY_K => 0x4B,
            OsCode::KEY_L => 0x4C,
            OsCode::KEY_M => 0x4D,
            OsCode::KEY_N => 0x4E,
            OsCode::KEY_O => 0x4F,
            OsCode::KEY_P => 0x50,
            OsCode::KEY_Q => 0x51,
            OsCode::KEY_R => 0x52,
            OsCode::KEY_S => 0x53,
            OsCode::KEY_T => 0x54,
            OsCode::KEY_U => 0x55,
            OsCode::KEY_V => 0x56,
            OsCode::KEY_W => 0x57,
            OsCode::KEY_X => 0x58,
            OsCode::KEY_Y => 0x59,
            OsCode::KEY_Z => 0x5A,
            OsCode::KEY_SEMICOLON => VK_OEM_1,
            OsCode::KEY_SLASH => VK_OEM_2,
            OsCode::KEY_GRAVE => VK_OEM_3,
            OsCode::KEY_LEFTBRACE => VK_OEM_4,
            OsCode::KEY_BACKSLASH => VK_OEM_5,
            OsCode::KEY_RIGHTBRACE => VK_OEM_6,
            OsCode::KEY_APOSTROPHE => VK_OEM_7,
            OsCode::KEY_MINUS => VK_OEM_MINUS,
            OsCode::KEY_DOT => VK_OEM_PERIOD,
            OsCode::KEY_EQUAL => VK_OEM_PLUS,
            OsCode::KEY_BACKSPACE => VK_BACK,
            OsCode::KEY_ESC => VK_ESCAPE,
            OsCode::KEY_TAB => VK_TAB,
            OsCode::KEY_ENTER => VK_RETURN,
            OsCode::KEY_LEFTCTRL => VK_LCONTROL,
            OsCode::KEY_LEFTSHIFT => VK_LSHIFT,
            OsCode::KEY_COMMA => VK_OEM_COMMA,
            OsCode::KEY_RIGHTSHIFT => VK_RSHIFT,
            OsCode::KEY_KPASTERISK => VK_MULTIPLY,
            OsCode::KEY_LEFTALT => VK_LMENU,
            OsCode::KEY_SPACE => VK_SPACE,
            OsCode::KEY_CAPSLOCK => VK_CAPITAL,
            OsCode::KEY_F1 => VK_F1,
            OsCode::KEY_F2 => VK_F2,
            OsCode::KEY_F3 => VK_F3,
            OsCode::KEY_F4 => VK_F4,
            OsCode::KEY_F5 => VK_F5,
            OsCode::KEY_F6 => VK_F6,
            OsCode::KEY_F7 => VK_F7,
            OsCode::KEY_F8 => VK_F8,
            OsCode::KEY_F9 => VK_F9,
            OsCode::KEY_F10 => VK_F10,
            OsCode::KEY_F11 => VK_F11,
            OsCode::KEY_F12 => VK_F12,
            OsCode::KEY_NUMLOCK => VK_NUMLOCK,
            OsCode::KEY_CLEAR => VK_CLEAR,
            OsCode::KEY_SCROLLLOCK => VK_SCROLL,
            OsCode::KEY_KP0 => VK_NUMPAD0,
            OsCode::KEY_KP1 => VK_NUMPAD1,
            OsCode::KEY_KP2 => VK_NUMPAD2,
            OsCode::KEY_KP3 => VK_NUMPAD3,
            OsCode::KEY_KP4 => VK_NUMPAD4,
            OsCode::KEY_KP5 => VK_NUMPAD5,
            OsCode::KEY_KP6 => VK_NUMPAD6,
            OsCode::KEY_KP7 => VK_NUMPAD7,
            OsCode::KEY_KP8 => VK_NUMPAD8,
            OsCode::KEY_KP9 => VK_NUMPAD9,
            OsCode::KEY_KPMINUS => VK_SUBTRACT,
            OsCode::KEY_KPPLUS => VK_ADD,
            OsCode::KEY_KPDOT => VK_DECIMAL,
            OsCode::KEY_RIGHTCTRL => VK_RCONTROL,
            OsCode::KEY_KPSLASH => VK_DIVIDE,
            OsCode::KEY_RIGHTALT => VK_RMENU,
            OsCode::KEY_HOME => VK_HOME,
            OsCode::KEY_UP => VK_UP,
            OsCode::KEY_PAGEUP => VK_PRIOR,
            OsCode::KEY_LEFT => VK_LEFT,
            OsCode::KEY_RIGHT => VK_RIGHT,
            OsCode::KEY_END => VK_END,
            OsCode::KEY_DOWN => VK_DOWN,
            OsCode::KEY_PAGEDOWN => VK_NEXT,
            OsCode::KEY_INSERT => VK_INSERT,
            OsCode::KEY_DELETE => VK_DELETE,
            OsCode::KEY_MUTE => VK_VOLUME_MUTE,
            OsCode::KEY_VOLUMEDOWN => VK_VOLUME_DOWN,
            OsCode::KEY_VOLUMEUP => VK_VOLUME_UP,
            OsCode::KEY_PAUSE => VK_PAUSE,
            OsCode::KEY_LEFTMETA => VK_LWIN,
            OsCode::KEY_RIGHTMETA => VK_RWIN,
            OsCode::KEY_COMPOSE => VK_APPS,
            OsCode::KEY_BACK => VK_BROWSER_BACK,
            OsCode::KEY_FORWARD => VK_BROWSER_FORWARD,
            OsCode::KEY_NEXTSONG => VK_MEDIA_NEXT_TRACK,
            OsCode::KEY_PLAYPAUSE => VK_MEDIA_PLAY_PAUSE,
            OsCode::KEY_PREVIOUSSONG => VK_MEDIA_PREV_TRACK,
            OsCode::KEY_STOP => VK_MEDIA_STOP,
            OsCode::KEY_HOMEPAGE => VK_BROWSER_HOME,
            OsCode::KEY_MAIL => VK_LAUNCH_MAIL,
            OsCode::KEY_MEDIA => VK_LAUNCH_MEDIA_SELECT,
            OsCode::KEY_REFRESH => VK_BROWSER_REFRESH,
            OsCode::KEY_F13 => VK_F13,
            OsCode::KEY_F14 => VK_F14,
            OsCode::KEY_F15 => VK_F15,
            OsCode::KEY_F16 => VK_F16,
            OsCode::KEY_F17 => VK_F17,
            OsCode::KEY_F18 => VK_F18,
            OsCode::KEY_F19 => VK_F19,
            OsCode::KEY_F20 => VK_F20,
            OsCode::KEY_F21 => VK_F21,
            OsCode::KEY_F22 => VK_F22,
            OsCode::KEY_F23 => VK_F23,
            OsCode::KEY_F24 => VK_F24,
            OsCode::KEY_HANGEUL => VK_HANGEUL,
            OsCode::KEY_HANJA => VK_HANJA,
            OsCode::KEY_102ND => VK_OEM_102,
            OsCode::KEY_PLAY => VK_PLAY,
            OsCode::KEY_PRINT => VK_SNAPSHOT,
            OsCode::KEY_SEARCH => VK_BROWSER_SEARCH,
            OsCode::KEY_FAVORITES => VK_BROWSER_FAVORITES,
            OsCode::KEY_RO => 0xC1,
            OsCode::KEY_HENKAN => VK_CONVERT,
            OsCode::KEY_MUHENKAN => VK_NONCONVERT,
            _ => 0,
        }
    }
}
