use winit::{
    dpi::{PhysicalPosition, PhysicalSize},
    event::{ElementState, KeyEvent, Modifiers, MouseButton, MouseScrollDelta, WindowEvent},
    keyboard::{Key, PhysicalKey, SmolStr},
};

pub enum AppEvent {
    Input(InputEvent),
    Redraw,
    Close,
    Ignored,
}

pub enum InputEvent {
    Resize(PhysicalSize<u32>),
    Focus(bool),
    Modifier(Modifiers),
    CursorMove(PhysicalPosition<f64>),
    CursorLeft,
    CursorEntered,
    Pointer {
        button: MouseButton,
        state: ElementState,
    },
    Wheel(MouseScrollDelta),
    KeyDown {
        physical_key: PhysicalKey,
        logical_key: Key,
        text: Option<SmolStr>,
        repeat: bool,
    },
}

impl AppEvent {
    pub fn from_winit(event: WindowEvent) -> Self {
        match event {
            WindowEvent::CloseRequested => Self::Close,
            WindowEvent::RedrawRequested => Self::Redraw,
            WindowEvent::Resized(size) => Self::Input(InputEvent::Resize(size)),
            WindowEvent::Focused(focused) => Self::Input(InputEvent::Focus(focused)),
            WindowEvent::ModifiersChanged(mods) => Self::Input(InputEvent::Modifier(mods)),
            WindowEvent::CursorMoved { position, .. } => {
                Self::Input(InputEvent::CursorMove(position))
            }
            WindowEvent::CursorLeft { .. } => Self::Input(InputEvent::CursorLeft),
            WindowEvent::CursorEntered { .. } => Self::Input(InputEvent::CursorEntered),
            WindowEvent::MouseInput { state, button, .. } => {
                Self::Input(InputEvent::Pointer { button, state })
            }
            WindowEvent::MouseWheel { delta, .. } => Self::Input(InputEvent::Wheel(delta)),
            WindowEvent::KeyboardInput {
                event:
                    KeyEvent {
                        state: ElementState::Pressed,
                        physical_key,
                        logical_key,
                        text,
                        repeat,
                        ..
                    },
                ..
            } => Self::Input(InputEvent::KeyDown {
                physical_key,
                logical_key,
                text,
                repeat,
            }),
            WindowEvent::KeyboardInput { .. }
            | WindowEvent::ActivationTokenDone { .. }
            | WindowEvent::Moved(_)
            | WindowEvent::Destroyed
            | WindowEvent::DroppedFile(_)
            | WindowEvent::HoveredFile(_)
            | WindowEvent::HoveredFileCancelled
            | WindowEvent::Ime(_)
            | WindowEvent::PinchGesture { .. }
            | WindowEvent::PanGesture { .. }
            | WindowEvent::DoubleTapGesture { .. }
            | WindowEvent::RotationGesture { .. }
            | WindowEvent::TouchpadPressure { .. }
            | WindowEvent::AxisMotion { .. }
            | WindowEvent::Touch(_)
            | WindowEvent::ScaleFactorChanged { .. }
            | WindowEvent::ThemeChanged(_)
            | WindowEvent::Occluded(_) => Self::Ignored,
        }
    }
}
