//! This module is a bit 'misplaced' if spelled out like '`gix_pack::cache::object::`*' but is best placed here for code reuse and
//! general usefulness.
use crate::cache;

#[cfg(feature = "object-cache-dynamic")]
mod memory {
    use crate::{cache, cache::set_vec_to_slice};
    use clru::WeightScale;
    use std::num::NonZeroUsize;

    struct Entry {
        data: Vec<u8>,
        kind: gix_object::Kind,
    }

    type Key = gix_hash::ObjectId;

    struct CustomScale;

    impl WeightScale<Key, Entry> for CustomScale {
        fn weight(&self, key: &Key, value: &Entry) -> usize {
            value.data.len() + std::mem::size_of::<Entry>() + key.as_bytes().len()
        }
    }

    /// An LRU cache with hash map backing and an eviction rule based on the memory usage for object data in bytes.
    pub struct MemoryCappedHashmap {
        inner: clru::CLruCache<Key, Entry, gix_hashtable::hash::Builder, CustomScale>,
        free_list: Vec<Vec<u8>>,
        debug: gix_features::cache::Debug,
    }

    impl MemoryCappedHashmap {
        /// The amount of bytes we can hold in total, or the value we saw in `new(…)`.
        pub fn capacity(&self) -> usize {
            self.inner.capacity()
        }
        /// Return a new instance which evicts least recently used items if it uses more than `memory_cap_in_bytes`
        /// object data.
        pub fn new(memory_cap_in_bytes: usize) -> MemoryCappedHashmap {
            MemoryCappedHashmap {
                inner: clru::CLruCache::with_config(
                    clru::CLruCacheConfig::new(NonZeroUsize::new(memory_cap_in_bytes).expect("non zero"))
                        .with_hasher(gix_hashtable::hash::Builder)
                        .with_scale(CustomScale),
                ),
                free_list: Vec::new(),
                debug: gix_features::cache::Debug::new(format!("MemoryCappedObjectHashmap({memory_cap_in_bytes}B)")),
            }
        }
    }

    impl cache::Object for MemoryCappedHashmap {
        /// Put the object going by `id` of `kind` with `data` into the cache.
        fn put(&mut self, id: gix_hash::ObjectId, kind: gix_object::Kind, data: &[u8]) {
            self.debug.put();
            let Some(data) = set_vec_to_slice(self.free_list.pop().unwrap_or_default(), data) else {
                return;
            };
            let res = self.inner.put_with_weight(id, Entry { data, kind });
            match res {
                Ok(Some(previous_entry)) => self.free_list.push(previous_entry.data),
                Ok(None) => {}
                Err((_key, value)) => self.free_list.push(value.data),
            }
        }

        /// Try to retrieve the object named `id` and place its data into `out` if available and return `Some(kind)` if found.
        fn get(&mut self, id: &gix_hash::ObjectId, out: &mut Vec<u8>) -> Option<gix_object::Kind> {
            let res = self.inner.get(id).and_then(|e| {
                set_vec_to_slice(out, &e.data)?;
                Some(e.kind)
            });
            if res.is_some() {
                self.debug.hit()
            } else {
                self.debug.miss()
            }
            res
        }
    }
}
#[cfg(feature = "object-cache-dynamic")]
pub use memory::MemoryCappedHashmap;

/// A cache implementation that doesn't do any caching.
pub struct Never;

impl cache::Object for Never {
    /// Noop
    fn put(&mut self, _id: gix_hash::ObjectId, _kind: gix_object::Kind, _data: &[u8]) {}

    /// Noop
    fn get(&mut self, _id: &gix_hash::ObjectId, _out: &mut Vec<u8>) -> Option<gix_object::Kind> {
        None
    }
}

impl<T: cache::Object + ?Sized> cache::Object for Box<T> {
    fn put(&mut self, id: gix_hash::ObjectId, kind: gix_object::Kind, data: &[u8]) {
        use std::ops::DerefMut;
        self.deref_mut().put(id, kind, data)
    }

    fn get(&mut self, id: &gix_hash::ObjectId, out: &mut Vec<u8>) -> Option<gix_object::Kind> {
        use std::ops::DerefMut;
        self.deref_mut().get(id, out)
    }
}
