// Input-device discovery, routing, and local/remote handoff control.

#[cfg(not(coverage))]
use anyhow::bail;
use anyhow::{Context, Result};
use evdev::{AbsoluteAxisCode, Device, EventType, KeyCode, RelativeAxisCode};
use std::collections::{HashMap, HashSet};
#[cfg(not(coverage))]
use std::os::unix::fs::MetadataExt;
#[cfg(not(coverage))]
use std::path::{Path, PathBuf};
use std::sync::{
    Arc,
    atomic::{AtomicBool, Ordering},
};
use std::time::Instant;
use tokio::{
    sync::broadcast::Sender,
    time::{Duration, interval},
};
use tracing::{debug, info, warn};

use lesavka_common::lesavka::{KeyboardReport, MouseReport};

use super::{
    keyboard::{KeyboardAggregator, build_keyboard_report, emit_live_keyboard_report},
    mouse::MouseAggregator,
};
use crate::layout::{Layout, apply as apply_layout};
use tokio::sync::mpsc::UnboundedSender;

pub struct InputAggregator {
    kbd_tx: Sender<KeyboardReport>,
    mou_tx: Sender<MouseReport>,
    dev_mode: bool,
    released: bool,
    magic_active: bool,
    pending_release: bool,
    pending_kill: bool,
    pending_keys: HashSet<KeyCode>,
    last_keyboard_report: [u8; 8],
    paste_tx: Option<UnboundedSender<String>>,
    keyboards: Vec<KeyboardAggregator>,
    mice: Vec<MouseAggregator>,
    selected_keyboard_path: Option<String>,
    selected_mouse_path: Option<String>,
    #[cfg(not(coverage))]
    known_input_paths: HashMap<PathBuf, u64>,
    capture_remote_boot: bool,
    quick_toggle_key: Option<KeyCode>,
    quick_toggle_down: bool,
    quick_toggle_debounce: Duration,
    last_quick_toggle_at: Option<Instant>,
    pending_release_started_at: Option<Instant>,
    pending_release_timeout: Duration,
    remote_failsafe_started_at: Option<Instant>,
    remote_failsafe_timeout: Duration,
    #[cfg(not(coverage))]
    routing_control_path: Option<PathBuf>,
    #[cfg(not(coverage))]
    last_routing_request_raw: Option<String>,
    #[cfg(not(coverage))]
    quick_toggle_control_path: Option<PathBuf>,
    #[cfg(not(coverage))]
    last_quick_toggle_request_raw: Option<String>,
    #[cfg(not(coverage))]
    clipboard_control_path: Option<PathBuf>,
    #[cfg(not(coverage))]
    clipboard_control_marker: u128,
    #[cfg(not(coverage))]
    wake_control_path: Option<PathBuf>,
    #[cfg(not(coverage))]
    last_wake_request_raw: Option<String>,
    wake_interval: Option<Duration>,
    last_hid_relayed_at: Instant,
    wake_nonce: u64,
    #[cfg(not(coverage))]
    routing_state_path: Option<PathBuf>,
    #[cfg(not(coverage))]
    published_remote_capture: Option<bool>,
    remote_capture_enabled: Arc<AtomicBool>,
}

include!("inputs/construction_and_scan.rs");
include!("inputs/run_loop.rs");
include!("inputs/routing_state.rs");

include!("inputs/device_classification.rs");
include!("inputs/toggle_keys.rs");
include!("inputs/runtime_controls.rs");

#[cfg(test)]
#[path = "tests/inputs.rs"]
mod tests;
