use crate::sys::token::Token;

use super::Driver;
use super::wire::Wire;

#[derive(Clone, Copy)]
pub struct CqeView {
    wire: Wire,
    pub result: i32,
    pub flags: u32,
}

#[derive(Clone, Copy)]
pub enum CqeKind {
    Accept(Token),
    Recv(Token),
    Write(Token),
}

impl CqeView {
    #[inline(always)]
    pub fn kind(&self) -> CqeKind {
        match self.wire {
            Wire::Accept(t) => CqeKind::Accept(t),
            Wire::Recv(t) => CqeKind::Recv(t),
            Wire::Write(t) => CqeKind::Write(t),
            Wire::Request(_) | Wire::Ignore => {
                unreachable!(
                    "dope invariant violated: CqeView constructed for non-handler wire kind"
                )
            }
        }
    }

    #[inline(always)]
    pub fn more(&self) -> bool {
        io_uring::cqueue::more(self.flags)
    }

    #[inline(always)]
    pub fn buffer_select(&self) -> Option<u16> {
        io_uring::cqueue::buffer_select(self.flags)
    }

    #[inline(always)]
    pub fn notif(&self) -> bool {
        io_uring::cqueue::notif(self.flags)
    }
}

pub trait CqeRouter {
    fn on_cqe(&mut self, driver: &mut Driver, cqe: CqeView);
}

#[derive(Clone, Copy)]
pub(in crate::driver) struct RawCqe {
    pub user_data: u64,
    pub result: i32,
    pub flags: u32,
}

#[inline(always)]
pub(in crate::driver) fn make_view(wire: Wire, result: i32, flags: u32) -> CqeView {
    CqeView {
        wire,
        result,
        flags,
    }
}
