use std::ptr;
use std::time::{SystemTime, UNIX_EPOCH};
use crate::generated::binding::*;
pub(crate) fn new_device_performance_counter(
    raw: FuriosaSmiDevicePerformanceCounter,
) -> DevicePerformanceCounter {
    DevicePerformanceCounter { raw }
}
pub struct DevicePerformanceCounter {
    raw: FuriosaSmiDevicePerformanceCounter,
}
impl DevicePerformanceCounter {
        pub fn pe_performance_counters(&self) -> Vec<PePerformanceCounter> {
        let mut result = Vec::with_capacity(self.raw.pe_count as usize);
        for i in 0..self.raw.pe_count {
            result.push(new_pe_performance_counter(
                self.raw.pe_performance_counters[i as usize],
            ));
        }
        result
    }
}
pub(crate) fn new_pe_performance_counter(
    raw: FuriosaSmiPePerformanceCounter,
) -> PePerformanceCounter {
    PePerformanceCounter { raw }
}
pub struct PePerformanceCounter {
    raw: FuriosaSmiPePerformanceCounter,
}
impl PePerformanceCounter {
        pub fn timestamp(&self) -> SystemTime {
        UNIX_EPOCH + std::time::Duration::from_secs(self.raw.timestamp as u64)
    }
        pub fn cycle_count(&self) -> u64 {
        self.raw.cycle_count
    }
        pub fn task_execution_cycle(&self) -> u64 {
        self.raw.task_execution_cycle
    }
}
pub(crate) fn new_core_utilization(raw: FuriosaSmiCoreUtilization) -> CoreUtilization {
    CoreUtilization { raw }
}
pub struct CoreUtilization {
    raw: FuriosaSmiCoreUtilization,
}
impl CoreUtilization {
        pub fn pe_utilization(&self) -> Vec<PeUtilization> {
        let mut result = Vec::with_capacity(self.raw.pe_count as usize);
        for i in 0..self.raw.pe_count {
            result.push(new_pe_utilization(self.raw.pe[i as usize]));
        }
        result
    }
}
fn new_pe_utilization(raw: FuriosaSmiPeUtilization) -> PeUtilization {
    PeUtilization { raw }
}
pub struct PeUtilization {
    raw: FuriosaSmiPeUtilization,
}
impl PeUtilization {
        pub fn core(&self) -> u32 {
        self.raw.core
    }
        pub fn time_window_mill(&self) -> u32 {
        self.raw.time_window_mil
    }
        pub fn pe_usage_percentage(&self) -> f64 {
        self.raw.pe_usage_percentage
    }
}
pub(crate) fn new_memory_utilization(raw: FuriosaSmiMemoryUtilization) -> MemoryUtilization {
    MemoryUtilization { raw }
}
pub struct MemoryUtilization {
    raw: FuriosaSmiMemoryUtilization,
}
impl MemoryUtilization {
        pub fn total_bytes(&self) -> u64 {
        self.raw.total_bytes
    }
        pub fn in_use_bytes(&self) -> u64 {
        self.raw.in_use_bytes
    }
}
pub(crate) fn new_device_temperature(raw: FuriosaSmiDeviceTemperature) -> DeviceTemperature {
    DeviceTemperature { raw }
}
pub struct DeviceTemperature {
    raw: FuriosaSmiDeviceTemperature,
}
impl DeviceTemperature {
        pub fn soc_peak(&self) -> f64 {
        self.raw.soc_peak
    }
        pub fn ambient(&self) -> f64 {
        self.raw.ambient
    }
}
pub(crate) fn new_observer_instance(raw: FuriosaSmiObserverInstance) -> DeviceObserverInstance {
    DeviceObserverInstance { raw }
}
pub(crate) struct DeviceObserverInstance {
    raw: FuriosaSmiObserverInstance,
}
impl DeviceObserverInstance {
    pub(crate) fn raw(&self) -> FuriosaSmiObserverInstance {
        self.raw
    }
}
impl Drop for DeviceObserverInstance {
    fn drop(&mut self) {
        unsafe {
            furiosa_smi_destroy_observer(&mut self.raw as *mut FuriosaSmiObserverInstance);
        }
    }
}
fn default_pe_performance_counter() -> FuriosaSmiPePerformanceCounter {
    FuriosaSmiPePerformanceCounter {
        timestamp: 0,
        cycle_count: 0,
        task_execution_cycle: 0,
    }
}
pub(crate) fn default_device_performance_counter() -> FuriosaSmiDevicePerformanceCounter {
    FuriosaSmiDevicePerformanceCounter {
        pe_count: 0,
        pe_performance_counters: [default_pe_performance_counter();
            FURIOSA_SMI_MAX_PE_SIZE as usize],
    }
}
fn default_pe_utilization() -> FuriosaSmiPeUtilization {
    FuriosaSmiPeUtilization {
        core: 0,
        time_window_mil: 0,
        pe_usage_percentage: 0.0,
    }
}
pub(crate) fn default_memory_utilization() -> FuriosaSmiMemoryUtilization {
    FuriosaSmiMemoryUtilization {
        total_bytes: 0,
        in_use_bytes: 0,
    }
}
pub(crate) fn default_core_utilization() -> FuriosaSmiCoreUtilization {
    FuriosaSmiCoreUtilization {
        pe_count: 0,
        pe: [default_pe_utilization(); FURIOSA_SMI_MAX_PE_SIZE as usize],
    }
}
pub(crate) fn default_power_consumption() -> FuriosaSmiDevicePowerConsumption {
    FuriosaSmiDevicePowerConsumption { rms_total: 0.0 }
}
pub(crate) fn default_temperature() -> FuriosaSmiDeviceTemperature {
    FuriosaSmiDeviceTemperature {
        soc_peak: 0.0,
        ambient: 0.0,
    }
}
pub(crate) fn default_observer_instance() -> FuriosaSmiObserverInstance {
    ptr::null_mut()
}