/// Represents a physical key on a keyboard.
///
/// This enum covers standard US-layout keys and is used by the [`InputManager`]
/// to track key states.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u16)]
pub enum Key {
    A = 0,
    B = 1,
    C = 2,
    D = 3,
    E = 4,
    F = 5,
    G = 6,
    H = 7,
    I = 8,
    J = 9,
    K = 10,
    L = 11,
    M = 12,
    N = 13,
    O = 14,
    P = 15,
    Q = 16,
    R = 17,
    S = 18,
    T = 19,
    U = 20,
    V = 21,
    W = 22,
    X = 23,
    Y = 24,
    Z = 25,

    Num0 = 26,
    Num1 = 27,
    Num2 = 28,
    Num3 = 29,
    Num4 = 30,
    Num5 = 31,
    Num6 = 32,
    Num7 = 33,
    Num8 = 34,
    Num9 = 35,

    Escape = 36,
    Enter = 37,
    Space = 38,
    Tab = 39,
    Backspace = 40,

    Left = 41,
    Right = 42,
    Up = 43,
    Down = 44,

    LShift = 45,
    RShift = 46,
    LCtrl = 47,
    RCtrl = 48,
    LAlt = 49,
    RAlt = 50,

    CapsLock = 51,

    Insert = 52,
    Delete = 53,
    Home = 54,
    End = 55,
    PageUp = 56,
    PageDown = 57,

    PrintScreen = 58,
    ScrollLock = 59,
    Pause = 60,

    F1 = 61,
    F2 = 62,
    F3 = 63,
    F4 = 64,
    F5 = 65,
    F6 = 66,
    F7 = 67,
    F8 = 68,
    F9 = 69,
    F10 = 70,
    F11 = 71,
    F12 = 72,

    Minus = 73,
    Equal = 74,
    BracketLeft = 75,
    BracketRight = 76,
    Backslash = 77,
    Semicolon = 78,
    Quote = 79,
    Backquote = 80,
    Comma = 81,
    Period = 82,
    Slash = 83,

    NumLock = 84,
    Numpad0 = 85,
    Numpad1 = 86,
    Numpad2 = 87,
    Numpad3 = 88,
    Numpad4 = 89,
    Numpad5 = 90,
    Numpad6 = 91,
    Numpad7 = 92,
    Numpad8 = 93,
    Numpad9 = 94,
    NumpadAdd = 95,
    NumpadSubtract = 96,
    NumpadMultiply = 97,
    NumpadDivide = 98,
    NumpadEnter = 99,
    NumpadDecimal = 100,
}

impl Key {
    pub const COUNT: usize = (Key::NumpadDecimal as usize) + 1;
    pub const WORDS: usize = Self::COUNT.div_ceil(64);

    pub const fn as_index(self) -> usize {
        self as usize
    }

    #[cfg(not(target_os = "android"))]
    pub(crate) fn from_winit_key_code(code: winit::keyboard::KeyCode) -> Option<Self> {
        use winit::keyboard::KeyCode;
        Some(match code {
            KeyCode::KeyA => Key::A,
            KeyCode::KeyB => Key::B,
            KeyCode::KeyC => Key::C,
            KeyCode::KeyD => Key::D,
            KeyCode::KeyE => Key::E,
            KeyCode::KeyF => Key::F,
            KeyCode::KeyG => Key::G,
            KeyCode::KeyH => Key::H,
            KeyCode::KeyI => Key::I,
            KeyCode::KeyJ => Key::J,
            KeyCode::KeyK => Key::K,
            KeyCode::KeyL => Key::L,
            KeyCode::KeyM => Key::M,
            KeyCode::KeyN => Key::N,
            KeyCode::KeyO => Key::O,
            KeyCode::KeyP => Key::P,
            KeyCode::KeyQ => Key::Q,
            KeyCode::KeyR => Key::R,
            KeyCode::KeyS => Key::S,
            KeyCode::KeyT => Key::T,
            KeyCode::KeyU => Key::U,
            KeyCode::KeyV => Key::V,
            KeyCode::KeyW => Key::W,
            KeyCode::KeyX => Key::X,
            KeyCode::KeyY => Key::Y,
            KeyCode::KeyZ => Key::Z,

            KeyCode::Digit0 => Key::Num0,
            KeyCode::Digit1 => Key::Num1,
            KeyCode::Digit2 => Key::Num2,
            KeyCode::Digit3 => Key::Num3,
            KeyCode::Digit4 => Key::Num4,
            KeyCode::Digit5 => Key::Num5,
            KeyCode::Digit6 => Key::Num6,
            KeyCode::Digit7 => Key::Num7,
            KeyCode::Digit8 => Key::Num8,
            KeyCode::Digit9 => Key::Num9,

            KeyCode::Escape => Key::Escape,
            KeyCode::Enter => Key::Enter,
            KeyCode::Space => Key::Space,
            KeyCode::Tab => Key::Tab,
            KeyCode::Backspace => Key::Backspace,

            KeyCode::ArrowLeft => Key::Left,
            KeyCode::ArrowRight => Key::Right,
            KeyCode::ArrowUp => Key::Up,
            KeyCode::ArrowDown => Key::Down,

            KeyCode::ShiftLeft => Key::LShift,
            KeyCode::ShiftRight => Key::RShift,
            KeyCode::ControlLeft => Key::LCtrl,
            KeyCode::ControlRight => Key::RCtrl,
            KeyCode::AltLeft => Key::LAlt,
            KeyCode::AltRight => Key::RAlt,

            KeyCode::CapsLock => Key::CapsLock,

            KeyCode::Insert => Key::Insert,
            KeyCode::Delete => Key::Delete,
            KeyCode::Home => Key::Home,
            KeyCode::End => Key::End,
            KeyCode::PageUp => Key::PageUp,
            KeyCode::PageDown => Key::PageDown,

            KeyCode::PrintScreen => Key::PrintScreen,
            KeyCode::ScrollLock => Key::ScrollLock,
            KeyCode::Pause => Key::Pause,

            KeyCode::F1 => Key::F1,
            KeyCode::F2 => Key::F2,
            KeyCode::F3 => Key::F3,
            KeyCode::F4 => Key::F4,
            KeyCode::F5 => Key::F5,
            KeyCode::F6 => Key::F6,
            KeyCode::F7 => Key::F7,
            KeyCode::F8 => Key::F8,
            KeyCode::F9 => Key::F9,
            KeyCode::F10 => Key::F10,
            KeyCode::F11 => Key::F11,
            KeyCode::F12 => Key::F12,

            KeyCode::Minus => Key::Minus,
            KeyCode::Equal => Key::Equal,
            KeyCode::BracketLeft => Key::BracketLeft,
            KeyCode::BracketRight => Key::BracketRight,
            KeyCode::Backslash => Key::Backslash,
            KeyCode::Semicolon => Key::Semicolon,
            KeyCode::Quote => Key::Quote,
            KeyCode::Backquote => Key::Backquote,
            KeyCode::Comma => Key::Comma,
            KeyCode::Period => Key::Period,
            KeyCode::Slash => Key::Slash,

            KeyCode::NumLock => Key::NumLock,
            KeyCode::Numpad0 => Key::Numpad0,
            KeyCode::Numpad1 => Key::Numpad1,
            KeyCode::Numpad2 => Key::Numpad2,
            KeyCode::Numpad3 => Key::Numpad3,
            KeyCode::Numpad4 => Key::Numpad4,
            KeyCode::Numpad5 => Key::Numpad5,
            KeyCode::Numpad6 => Key::Numpad6,
            KeyCode::Numpad7 => Key::Numpad7,
            KeyCode::Numpad8 => Key::Numpad8,
            KeyCode::Numpad9 => Key::Numpad9,
            KeyCode::NumpadAdd => Key::NumpadAdd,
            KeyCode::NumpadSubtract => Key::NumpadSubtract,
            KeyCode::NumpadMultiply => Key::NumpadMultiply,
            KeyCode::NumpadDivide => Key::NumpadDivide,
            KeyCode::NumpadEnter => Key::NumpadEnter,
            KeyCode::NumpadDecimal => Key::NumpadDecimal,

            _ => return None,
        })
    }
}
