use std::sync::{Arc, Mutex};

#[cfg(feature = "software-energy-lab")]
mod hwmon;
#[cfg(feature = "software-energy-lab")]
mod ina;
#[cfg(feature = "software-energy-lab")]
mod nvml;
#[cfg(feature = "software-energy-lab")]
mod rapl;

pub trait Probe: Send + Sync {
    /// Gets the difference in value since the last time this energy probe was created/reset.
    fn elapsed(&self) -> indexmap::IndexMap<String, f32>;

    /// Resets this probe, such that the next time `elapsed` is called,
    /// the difference compared to the value at this reset is returned.
    fn reset(&mut self);
}

pub type Probes = Vec<Arc<Mutex<dyn Probe>>>;

#[cfg(feature = "software-energy-lab")]
pub fn get_available_probes() -> Probes {
    hwmon::hwmon()
        .chain(
            [ina::ina(), nvml::nvml(), rapl::rapl()]
                .into_iter()
                .filter_map(|x| x),
        )
        .collect()
}

#[cfg(not(feature = "software-energy-lab"))]
pub fn get_available_probes() -> Probes {
    vec![]
}

pub fn get_probes_elapsed(probes: &Probes) -> indexmap::IndexMap<String, f32> {
    probes
        .iter()
        .rev()
        .map(|probe| probe.lock().unwrap().elapsed())
        .flatten()
        .collect()
}

pub fn reset_probes(probes: &mut Probes) {
    for probe in &mut probes.iter_mut() {
        probe.lock().unwrap().reset();
    }
}
