use alloc::sync::Arc;
use yggdrasil_abi::error::Error;

use crate::device::Device;

pub enum PwmChannelMode {
    OneShot,
    Repeat,
}

#[derive(Debug)]
pub struct PwmControllerInfo {
    // If true, channel period can be configured individually,
    // if false, channel 0 is used to set the period, and cannot be used to output PWM
    pub per_channel_period: bool,
    pub channel_count: usize,
}

pub struct PwmControllerDevice {
    pub device: Arc<dyn PwmController>,
}

pub struct PwmChannelDevice {
    pub device: Arc<dyn PwmController>,
    pub channel: u32,
}

pub trait PwmController: Device {
    fn controller_info(&self) -> Result<PwmControllerInfo, Error>;

    fn channel_period(&self, channel: u32) -> Result<u64, Error>;
    fn set_channel_period(&self, channel: u32, period: u64) -> Result<u64, Error>;
    fn duty_cycle(&self, channel: u32) -> Result<u64, Error>;
    fn set_duty_cycle(&self, channel: u32, t: u64) -> Result<(), Error>;

    fn stop_channel(&self, channel: u32) -> Result<(), Error>;
}

impl From<Arc<dyn PwmController>> for PwmControllerDevice {
    fn from(value: Arc<dyn PwmController>) -> Self {
        Self { device: value }
    }
}

impl Device for PwmControllerDevice {
    fn display_name(&self) -> &str {
        self.device.display_name()
    }
}

impl Device for PwmChannelDevice {
    fn display_name(&self) -> &str {
        self.device.display_name()
    }
}
