use core::task::{Context, Poll};

use alloc::boxed::Box;
use async_trait::async_trait;
use device_api::pwm::{PwmChannelDevice, PwmControllerDevice};
use yggdrasil_abi::error::Error;

use crate::{device::char::CharDevice, vfs::FileReadiness};

// TODO PWM controller operations
#[async_trait]
impl CharDevice for PwmControllerDevice {
    async fn read(&self, buffer: &mut [u8]) -> Result<usize, Error> {
        let _ = buffer;
        Err(Error::InvalidOperation)
    }
    async fn write(&self, buffer: &[u8]) -> Result<usize, Error> {
        let _ = buffer;
        Err(Error::InvalidOperation)
    }
    fn read_nonblocking(&self, buffer: &mut [u8]) -> Result<usize, Error> {
        let _ = buffer;
        Err(Error::InvalidOperation)
    }
    fn write_nonblocking(&self, buffer: &[u8]) -> Result<usize, Error> {
        let _ = buffer;
        Err(Error::InvalidOperation)
    }
    fn device_request(&self, option: u32, buffer: &mut [u8], len: usize) -> Result<usize, Error> {
        let _ = (option, buffer, len);
        todo!()
    }
}

impl FileReadiness for PwmControllerDevice {
    fn poll_read(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
        let _ = cx;
        todo!()
    }
}

#[async_trait]
impl CharDevice for PwmChannelDevice {
    async fn read(&self, buffer: &mut [u8]) -> Result<usize, Error> {
        self.read_nonblocking(buffer)
    }
    async fn write(&self, buffer: &[u8]) -> Result<usize, Error> {
        self.write_nonblocking(buffer)
    }
    fn read_nonblocking(&self, buffer: &mut [u8]) -> Result<usize, Error> {
        if buffer.len() < 8 {
            return Err(Error::BufferTooSmall);
        }
        let mut len = 8;
        let duty_cycle = self.device.duty_cycle(self.channel)?;
        buffer[0..8].copy_from_slice(&u64::to_ne_bytes(duty_cycle));
        if buffer.len() >= 16 {
            let period = self.device.channel_period(self.channel)?;
            buffer[8..16].copy_from_slice(&u64::to_ne_bytes(period));
            len += 8;
        }
        Ok(len)
    }
    fn write_nonblocking(&self, buffer: &[u8]) -> Result<usize, Error> {
        if buffer.len() < 8 {
            return Err(Error::InvalidArgument);
        }
        let mut len = 8;
        let duty_cycle = u64::from_ne_bytes(buffer[0..8].try_into().unwrap());
        let period = if buffer.len() >= 16 {
            len += 8;
            Some(u64::from_ne_bytes(buffer[8..16].try_into().unwrap()))
        } else {
            None
        };
        if let Some(period) = period {
            self.device.set_channel_period(self.channel, period)?;
        }
        if duty_cycle != u64::MAX {
            self.device.set_duty_cycle(self.channel, duty_cycle)?;
        }
        Ok(len)
    }
    fn device_request(&self, option: u32, buffer: &mut [u8], len: usize) -> Result<usize, Error> {
        let _ = (option, buffer, len);
        todo!()
    }
}

impl FileReadiness for PwmChannelDevice {
    fn poll_read(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
        let _ = cx;
        todo!()
    }
}
