// SPDX-License-Identifier: Apache-2.0
//! select_fanin — fan-in multiplexing with `select!`.
//!
//! Two producers send values at different rates.  A single consumer uses
//! `select!` to receive from whichever producer is ready first, merging
//! both streams into one.  This is the "fan-in" pattern from Go's concurrency
//! tutorial.
//!
//! Run with:
//!   cargo run --example select_fanin

use std::time::Duration;
use go_lib::{chan::chan, go, select};

#[go_lib::main]
fn main() {
    // Two buffered channels — producers fill them at their own pace.
    let (fast_tx, fast_rx) = chan::<i32>(8);
    let (slow_tx, slow_rx) = chan::<i32>(4);

    // Fast producer: 6 values, 5 ms apart.
    go!(move || {
        for i in 0..6_i32 {
            go_lib::sleep(Duration::from_millis(5));
            fast_tx.send(i);
        }
    });

    // Slow producer: 3 values, 15 ms apart.
    go!(move || {
        for i in 10..13_i32 {
            go_lib::sleep(Duration::from_millis(15));
            slow_tx.send(i);
        }
    });

    // Consumer: receive exactly 9 values from whichever channel is ready.
    let mut received = Vec::new();
    for _ in 0..9 {
        select! {
            recv(fast_rx) -> v => {
                if let Some(n) = v { received.push(('F', n)); }
            }
            recv(slow_rx) -> v => {
                if let Some(n) = v { received.push(('S', n)); }
            }
        }
    }

    println!("received {} values in arrival order:", received.len());
    for (src, val) in &received {
        println!("  {src}: {val}");
    }

    let fast_count = received.iter().filter(|(s, _)| *s == 'F').count();
    let slow_count = received.iter().filter(|(s, _)| *s == 'S').count();
    println!("fast={fast_count} slow={slow_count}");
    assert_eq!(fast_count, 6);
    assert_eq!(slow_count, 3);
}
