//! Input injection module
//!
//! Handles mouse and keyboard input simulation using Windows SendInput API.

mod keyboard;
mod mouse;

pub use keyboard::vk_is_extended;
pub use keyboard::KeyboardController;
pub use mouse::MouseController;

use anyhow::Result;

/// Combined input controller for mouse and keyboard
pub struct InputController {
    mouse: MouseController,
    keyboard: KeyboardController,
}

impl InputController {
    /// Create a new input controller
    pub fn new() -> Result<Self> {
        Ok(Self {
            mouse: MouseController::new()?,
            keyboard: KeyboardController::new()?,
        })
    }

    /// Get mouse controller
    #[allow(dead_code)]
    pub fn mouse(&mut self) -> &mut MouseController {
        &mut self.mouse
    }

    /// Get keyboard controller
    #[allow(dead_code)]
    pub fn keyboard(&mut self) -> &mut KeyboardController {
        &mut self.keyboard
    }

    /// Move mouse to absolute position
    pub fn mouse_move(&mut self, x: i32, y: i32) -> Result<()> {
        self.mouse.move_to(x, y)
    }

    /// Click mouse button
    pub fn mouse_click(&mut self, button: MouseButton, down: bool) -> Result<()> {
        if down {
            self.mouse.button_down(button)
        } else {
            self.mouse.button_up(button)
        }
    }

    /// Scroll mouse wheel
    pub fn mouse_scroll(&mut self, delta_x: i32, delta_y: i32) -> Result<()> {
        self.mouse.scroll(delta_x, delta_y)
    }

    /// Press or release a key by virtual-key code only (scan code derived from the VK).
    #[allow(dead_code)]
    pub fn key_event(&mut self, vk_code: u16, down: bool) -> Result<()> {
        if down {
            self.keyboard.key_down(vk_code)
        } else {
            self.keyboard.key_up(vk_code)
        }
    }

    /// Inject a full-fidelity key event (VK + hardware scan code + extended-key flag).
    ///
    /// This is the path used for relayed viewer keystrokes so that scan-code injection
    /// (layout-independent) and the correct `KEYEVENTF_EXTENDEDKEY` flag are applied.
    pub fn key_event_full(
        &mut self,
        vk_code: u16,
        scan_code: u16,
        is_extended: bool,
        down: bool,
    ) -> Result<()> {
        self.keyboard
            .key_event_full(vk_code, scan_code, is_extended, down)
    }

    /// Release any modifier keys currently held down on the remote.
    ///
    /// Invoked when the viewer loses focus or the session ends so a Ctrl/Alt/Shift/Win
    /// whose key-up never arrived does not stay latched on the remote desktop.
    #[allow(dead_code)]
    pub fn release_all_modifiers(&mut self) -> Result<()> {
        self.keyboard.release_all_modifiers()
    }

    /// Type a unicode character
    #[allow(dead_code)]
    pub fn type_unicode(&mut self, ch: char) -> Result<()> {
        self.keyboard.type_char(ch)
    }

    /// Send Ctrl+Alt+Delete (requires special handling on Windows)
    pub fn send_ctrl_alt_del(&mut self) -> Result<()> {
        self.keyboard.send_sas()
    }
}

/// Mouse button types
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MouseButton {
    Left,
    Right,
    Middle,
    // Extra mouse buttons; not yet produced by the viewer input mapping.
    #[allow(dead_code)]
    X1,
    #[allow(dead_code)]
    X2,
}

impl Default for InputController {
    fn default() -> Self {
        Self::new().expect("Failed to create input controller")
    }
}
