#![allow(missing_docs)]
mod utils;

use kbd::hotkey::Hotkey;
use kbd::hotkey::Modifier;
use kbd::key::Key;
use kbd_global::error::ManagerStopped;
use kbd_global::error::RegisterError;

#[test]
fn register_and_drop_handle_unregisters_hotkey() {
    let manager = utils::test_manager();
    let hotkey = Hotkey::new(Key::C).modifier(Modifier::Ctrl);

    let handle = manager
        .register(hotkey, || {})
        .expect("register should succeed");

    assert!(manager.is_registered(hotkey).expect("query should succeed"));

    drop(handle);

    // Command channel is FIFO: the Unregister from drop is enqueued before
    // this IsRegistered query, so drain_commands() processes them in order.
    assert!(!manager.is_registered(hotkey).expect("query should succeed"));
}

#[test]
fn duplicate_hotkey_registration_returns_conflict_error() {
    let manager = utils::test_manager();
    let hotkey = Hotkey::new(Key::A).modifier(Modifier::Ctrl);

    let _first = manager
        .register(hotkey, || {})
        .expect("first registration should succeed");

    let duplicate = manager.register(hotkey, || {});
    assert!(matches!(duplicate, Err(RegisterError::AlreadyRegistered)));
}

#[test]
fn is_key_pressed_returns_false_when_no_keys_pressed() {
    let manager = utils::test_manager();

    assert!(
        !manager
            .is_key_pressed(Key::A)
            .expect("query should succeed")
    );
}

#[test]
fn active_modifiers_returns_empty_when_no_keys_pressed() {
    let manager = utils::test_manager();

    let modifiers = manager.active_modifiers().expect("query should succeed");
    assert!(modifiers.is_empty());
}

#[test]
fn shutdown_stops_handle_unregistration_commands() {
    let manager = utils::test_manager();

    let handle = manager
        .register(Hotkey::new(Key::B).modifier(Modifier::Alt), || {})
        .expect("register should succeed");

    manager.shutdown().expect("shutdown should succeed");

    let unregister = handle.unregister();
    assert!(matches!(unregister, Err(ManagerStopped)));
}

#[test]
fn register_sequence_returns_guard() {
    let manager = utils::test_manager();

    let sequence = kbd::hotkey::HotkeySequence::new(vec![
        Hotkey::new(Key::K).modifier(Modifier::Ctrl),
        Hotkey::new(Key::C).modifier(Modifier::Ctrl),
    ])
    .unwrap();

    let guard = manager
        .register_sequence(sequence, || {})
        .expect("sequence registration should succeed");

    drop(guard);
}

#[test]
fn register_sequence_accepts_string_input() {
    let manager = utils::test_manager();

    let guard = manager
        .register_sequence("Ctrl+K, Ctrl+C", || {})
        .expect("sequence string registration should succeed");

    drop(guard);
}

#[test]
fn register_sequence_accepts_vec_hotkeys_input() {
    let manager = utils::test_manager();

    let guard = manager
        .register_sequence(
            vec![
                Hotkey::new(Key::K).modifier(Modifier::Ctrl),
                Hotkey::new(Key::C).modifier(Modifier::Ctrl),
            ],
            || {},
        )
        .expect("sequence vec registration should succeed");

    drop(guard);
}

#[test]
fn register_sequence_reports_parse_error_for_string_input() {
    let manager = utils::test_manager();

    let result = manager.register_sequence("Ctrl+K, Ctrl+Nope", || {});
    assert!(matches!(result, Err(RegisterError::Parse(_))));
}

#[test]
fn pending_sequence_is_none_when_idle() {
    let manager = utils::test_manager();

    let pending = manager
        .pending_sequence()
        .expect("pending query should succeed");
    assert!(pending.is_none());
}
