use alloc::boxed::Box;
use async_trait::async_trait;
use bytemuck::{Pod, Zeroable};
use libk::dma::BusAddress;
use ygg_driver_usb::error::UsbError;
use yggdrasil_abi::define_bitfields;

pub mod command;
pub mod event;
pub mod transfer;

pub use event::{EventRing, EventRingSegmentTable};

#[async_trait]
pub trait CommandExecutor {
    fn ring_doorbell(&self, index: usize, target: u8);

    async fn reset_endpoint(
        &self,
        slot_id: u8,
        endpoint_id: u8,
        dequeue_pointer: BusAddress,
        dequeue_cycle: bool,
    ) -> Result<(), UsbError>;
}

pub trait GenericRing {
    fn bus_base(&self) -> BusAddress;
}

define_bitfields! {
    pub LinkTrbFlags : u32 {
        (10..16) => ty,
        4 => chain,
        1 => toggle_cycle,
        0 => cycle
    }
}

#[derive(Clone, Copy, Debug, Pod, Zeroable)]
#[repr(C, align(16))]
pub struct LinkTrb {
    pub address: BusAddress,
    _0: u32,
    pub flags: LinkTrbFlags,
}

impl LinkTrb {
    pub fn new(address: BusAddress, cycle_bit: bool) -> Self {
        Self {
            address,
            _0: 0,
            flags: LinkTrbFlags::new(6, true, true, cycle_bit),
        }
    }
}
