use std::os::fd::OwnedFd;

// pub use yggdrasil_abi::io::{KeyboardKey, KeyboardKeyEvent};

use serde::{Deserialize, Serialize};

use crate::input::Key;

#[derive(Debug, Serialize, Deserialize)]
pub struct WindowInfo {
    pub window_id: u32,
    pub surface_stride: usize,
    pub surface_mapping_size: usize,
    pub width: u32,
    pub height: u32,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct KeyModifiers {
    pub ctrl: bool,
    pub shift: bool,
    pub alt: bool,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct KeyEvent {
    pub modifiers: KeyModifiers,
    pub key: Key,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct KeyInput {
    pub modifiers: KeyModifiers,
    pub key: Key,
    pub input: Option<char>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct KeyboardKeyEvent {
    pub key: Key,
    pub state: bool,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum WindowEvent {
    KeyPressed(KeyEvent),
    KeyReleased(KeyEvent),
    KeyInput(KeyInput),
    Resized { width: u32, height: u32 },
    FocusChanged(bool),
    Destroyed,
    RedrawRequested,
    CloseRequested,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum WindowManagementEvent {
    WindowCreated { workspace: Option<usize>, wid: u32 },
    WindowRemoved { workspace: Option<usize>, wid: u32 },
    WorkspaceChanged { old: usize, new: usize },
    WorkspaceActivity { mask: u32, max: usize },
}

#[derive(Debug, Serialize, Deserialize)]
pub enum EventData {
    // Server events
    KeyboardKey(KeyboardKeyEvent),
    RedrawRequested,

    // Window events
    WindowEvent(u32, WindowEvent),

    // Window management events (only if subscribed)
    WindowManagementEvent(WindowManagementEvent),

    // Request-responses
    ServerHello(u32),
    NewWindowInfo(WindowInfo),
}

#[derive(Debug)]
pub struct Event {
    pub data: EventData,
    pub file: Option<OwnedFd>,
}

impl KeyModifiers {
    pub const SHIFT: Self = Self {
        shift: true,
        ctrl: false,
        alt: false,
    };

    pub const CTRL: Self = Self {
        shift: false,
        ctrl: true,
        alt: false,
    };

    pub const CTRL_SHIFT: Self = Self {
        shift: true,
        ctrl: true,
        alt: false,
    };

    pub const ALT: Self = Self {
        shift: false,
        ctrl: false,
        alt: true,
    };

    pub const ALT_SHIFT: Self = Self {
        shift: true,
        ctrl: false,
        alt: true,
    };

    pub const NONE: Self = Self {
        shift: false,
        ctrl: false,
        alt: false,
    };
}
