use crate::eval::expr::{eval_bool, Expr};
use crate::trace::Trace;
use rayon::prelude::*;

/// Find all timestep indices where the expression evaluates to true.
/// Single-threaded — iterates sequentially.
pub fn find(trace: &dyn Trace, expr: &Expr) -> Vec<usize> {
    (0..=trace.max_index())
        .filter(|&idx| eval_bool(trace, expr, idx))
        .collect()
}

/// Find all matching indices using rayon parallel iteration.
/// Splits the index range across CPU cores for true multi-core evaluation.
/// The Trace must be Send+Sync (which our trait requires).
pub fn parallel_find(trace: &dyn Trace, expr: &Expr) -> Vec<usize> {
    let max = trace.max_index();
    let mut results: Vec<usize> = (0..=max)
        .into_par_iter()
        .filter(|&idx| eval_bool(trace, expr, idx))
        .collect();
    results.sort_unstable();
    results
}

/// Count matching indices in parallel.
pub fn parallel_count(trace: &dyn Trace, expr: &Expr) -> usize {
    let max = trace.max_index();
    (0..=max)
        .into_par_iter()
        .filter(|&idx| eval_bool(trace, expr, idx))
        .count()
}
