use crate::{pool_buffer::QuotaPoolBuffer, quota::QuotaResult, quota_id::QuotaId};

#[derive(Debug)]
pub struct StaleQuotaRef;

pub struct QuotaRef<'a> {
    pub(crate) buffer: &'a QuotaPoolBuffer,
    pub(crate) id: QuotaId,
}

impl<'a> QuotaRef<'a> {
    #[inline]
    pub(crate) fn new(buffer: &'a QuotaPoolBuffer, id: QuotaId) -> Self {
        Self { buffer, id }
    }

    #[inline]
    pub fn consume(&self, cost: u64) -> Result<QuotaResult, StaleQuotaRef> {
        if let Some(quota) = self.buffer.raw_quota(self.id) {
            Ok(quota.consume(cost))
        } else {
            Err(StaleQuotaRef)
        }
    }

    #[inline]
    pub fn last_read_time(&self) -> Result<std::time::Duration, StaleQuotaRef> {
        if let Some(duration_ns) = self.buffer.last_access_time_ns(self.id) {
            Ok(std::time::Duration::from_nanos(*duration_ns))
        } else {
            Err(StaleQuotaRef)
        }
    }

    #[inline]
    pub fn elapsed_since_refill(&self) -> Result<std::time::Duration, StaleQuotaRef> {
        if let Some(duration_ns) = self.buffer.elapsed_since_refill_ns(self.id) {
            Ok(std::time::Duration::from_nanos(*duration_ns))
        } else {
            Err(StaleQuotaRef)
        }
    }
}

#[cfg(test)]
mod tests;
