brlapi 0.4.1

Safe Rust bindings for the BrlAPI library
// SPDX-License-Identifier: LGPL-2.1

//! Demonstration of cooperative braille display sharing with screen readers
//!
//! This example shows how to use the new cooperative API to politely share
//! the braille display with screen readers like Orca, using evidence-based
//! priority management and content-aware cooperation.
//!
//! Key features demonstrated:
//! - Simple notification functions that "just work"
//! - Evidence-based priority values (researched from real Orca behavior)
//! - Time-based cooperation that works across all braille display drivers
//! - Automatic yielding to screen readers
//!
//! Run with: cargo run --example cooperative_notifications

use brlapi::Result;
use brlapi::cooperative::{self, AppType, ContentQuality, CooperativeDisplay};
use std::thread;
use std::time::Duration;

fn main() -> Result<()> {
    println!("Cooperative Braille Display Sharing Demo");
    println!("=====================================");
    println!("This example demonstrates the new cooperative API for polite");
    println!("braille display sharing with screen readers like Orca.\n");

    // Demo 1: Simple notification functions (easiest API)
    println!("1. Simple notification functions...");
    demo_simple_notifications()?;
    thread::sleep(Duration::from_secs(1));

    // Demo 2: Application-type-based cooperation
    println!("\n2. Application-type-based cooperation...");
    demo_app_type_cooperation()?;
    thread::sleep(Duration::from_secs(1));

    // Demo 3: Content-quality-aware priority adjustment
    println!("\n3. Content-quality-aware priority adjustment...");
    demo_content_quality_cooperation()?;
    thread::sleep(Duration::from_secs(1));

    // Demo 4: Message queuing for busy displays
    println!("\n4. Message queuing for busy displays...");
    demo_message_queuing()?;

    println!("\n[SUCCESS] Cooperative display sharing demo completed!");
    println!("\nKey benefits of the cooperative API:");
    println!("- Automatic priority management based on Orca research");
    println!("- Content-aware priority adjustment like BRLTTY 6.1+");
    println!("- Polite yielding to screen readers");
    println!("- Simple API for common notification use cases");
    println!("- No complex retry logic needed - handled automatically");

    Ok(())
}

/// Demo 1: Simple notification functions for common use cases
fn demo_simple_notifications() -> Result<()> {
    println!("   Testing simple notification functions...");

    // Most common use case - simple notifications
    cooperative::notify("Build completed successfully")?;
    println!("   [SUCCESS] Sent: Build notification");

    thread::sleep(Duration::from_millis(1500));

    // Higher priority alerts
    cooperative::alert("Critical error occurred!")?;
    println!("   [SUCCESS] Sent: Critical alert");

    thread::sleep(Duration::from_millis(1500));

    // Debug messages (low priority)
    cooperative::debug("Breakpoint hit at line 42")?;
    println!("   [SUCCESS] Sent: Debug message");

    println!("   Simple notifications completed - these use automatic cooperation");
    Ok(())
}

/// Demo 2: Application-type-based cooperation using evidence-based priorities
fn demo_app_type_cooperation() -> Result<()> {
    println!("   Testing different application types with research-based priorities...");

    // Background application (low priority, yields to screen readers)
    println!("   Creating background app (priority 35)...");
    let mut background = CooperativeDisplay::background_app()?;
    background.show_status("Processing file 5 of 20")?;
    println!("   [SUCCESS] Background app: Status update sent");

    thread::sleep(Duration::from_millis(1000));

    // User application (priority 45, slightly below screen reader base of 50)
    println!("   Creating user app (priority 45)...");
    let user_app = CooperativeDisplay::open(AppType::UserApp)?;
    user_app.show_message("Operation completed successfully")?;
    println!("   [SUCCESS] User app: Completion message sent");

    thread::sleep(Duration::from_millis(1000));

    // System alert (priority 65, above screen reader base)
    println!("   Creating system alert (priority 65)...");
    let system_alert = CooperativeDisplay::open(AppType::SystemAlert)?;
    system_alert.show_message("System maintenance required")?;
    println!("   [SUCCESS] System alert: Maintenance notice sent");

    println!("   Application type cooperation completed");
    Ok(())
}

/// Demo 3: Content-quality-aware priority adjustment (BRLTTY 6.1+ style)
fn demo_content_quality_cooperation() -> Result<()> {
    println!("   Testing content-quality-aware priority adjustment...");

    let display = CooperativeDisplay::open(AppType::UserApp)?;

    // Poor quality content (base priority + 0)
    println!("   Showing poor quality content (base priority)...");
    display.show_content("Background task is running", ContentQuality::Poor)?;
    println!("   [SUCCESS] Poor quality: Background info displayed");

    thread::sleep(Duration::from_millis(1000));

    // Fair quality content (base priority + 10)
    println!("   Showing fair quality content (priority +10)...");
    display.show_content("File saved successfully", ContentQuality::Fair)?;
    println!("   [SUCCESS] Fair quality: Status message displayed");

    thread::sleep(Duration::from_millis(1000));

    // Good quality content (base priority + 20, overrides Orca like terminal widgets)
    println!("   Showing good quality content (priority +20)...");
    display.show_content("Press Enter to continue", ContentQuality::Good)?;
    println!("   [SUCCESS] Good quality: Interactive prompt displayed");

    println!("   Content quality cooperation completed");
    println!("   Note: Good quality content (priority +20) exceeds screen reader base (50)");
    Ok(())
}

/// Demo 4: Message queuing for cooperative handling of busy displays
fn demo_message_queuing() -> Result<()> {
    println!("   Testing message queuing for busy displays...");

    let mut display = CooperativeDisplay::open(AppType::UserApp)?;

    // Queue several messages
    println!("   Queueing multiple messages...");
    display.queue_message("Task 1 started", ContentQuality::Fair)?;
    display.queue_message("Task 2 started", ContentQuality::Fair)?;
    display.queue_message("ERROR: Task 3 failed!", ContentQuality::Good)?;
    display.queue_message("All tasks completed", ContentQuality::Fair)?;

    println!(
        "   [SUCCESS] Queued {} messages",
        display.pending_messages()
    );

    // Process the queue cooperatively
    println!("   Processing message queue cooperatively...");
    let processed = display.process_queue()?;
    println!("   [SUCCESS] Processed {} messages from queue", processed);

    if display.pending_messages() > 0 {
        println!(
            "   Note: {} messages remain queued (display may be busy)",
            display.pending_messages()
        );
    }

    println!("   Message queuing completed");
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_cooperative_example_functions() {
        // Test that the example functions don't panic
        // Actual BrlAPI functionality depends on daemon availability

        println!("Testing cooperative notification example functions...");

        // These should not panic even if BrlAPI is unavailable
        let result1 = demo_simple_notifications();
        let result2 = demo_app_type_cooperation();
        let result3 = demo_content_quality_cooperation();
        let result4 = demo_message_queuing();

        // Log results but don't fail tests if BrlAPI unavailable
        match (result1, result2, result3, result4) {
            (Ok(()), Ok(()), Ok(()), Ok(())) => {
                println!("[SUCCESS] All cooperative demo functions completed");
            }
            _ => {
                println!("[INFO] Some demo functions failed (expected if no BrlAPI daemon)");
            }
        }
    }

    #[test]
    fn test_priority_relationships() {
        // Test that our priority system maintains correct relationships

        // User app with good content should exceed screen reader base
        let user_base = AppType::UserApp.base_priority();
        let screen_reader_base = AppType::ScreenReader.base_priority();
        let good_boost = ContentQuality::Good.priority_offset();

        assert!(user_base + good_boost as u32 > screen_reader_base);

        // System alerts should exceed screen reader base
        assert!(AppType::SystemAlert.base_priority() > screen_reader_base);

        // Background tasks should be below user apps
        assert!(AppType::BackgroundTask.base_priority() < user_base);

        println!("[SUCCESS] Priority relationships verified");
    }
}