use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

/// CacheStatistics holds statistics generated by Client Side Caching.
#[derive(Debug, Default, Eq, PartialEq)]
pub struct CacheStatistics {
    /// Count of how many cache hits occurred.
    pub hit: usize,
    /// Count of how many cache misses occurred.
    pub miss: usize,
    /// Count of how many cache item is invalidated via [`crate::types::PushKind::Invalidate`] or LRU.
    /// If there is multiple cache item per key it will be increased multiple times instead of 1.
    pub invalidate: usize,
}

#[derive(Default)]
pub(crate) struct Statistics {
    hit: AtomicUsize,
    miss: AtomicUsize,
    invalidate: AtomicUsize,
}

impl Statistics {
    pub(crate) fn increase_hit(&self, val: usize) {
        self.hit.fetch_add(val, Ordering::Relaxed);
    }

    pub(crate) fn increase_miss(&self, val: usize) {
        self.miss.fetch_add(val, Ordering::Relaxed);
    }

    pub(crate) fn increase_invalidate(&self, val: usize) {
        self.invalidate.fetch_add(val, Ordering::Relaxed);
    }
}

impl From<Arc<Statistics>> for CacheStatistics {
    fn from(value: Arc<Statistics>) -> Self {
        CacheStatistics {
            hit: value.hit.load(Ordering::Relaxed),
            miss: value.miss.load(Ordering::Relaxed),
            invalidate: value.invalidate.load(Ordering::Relaxed),
        }
    }
}
