use fjall::{Guard, Slice};

use super::ItemWithRaw;
use crate::{DbError, DbResult, Entry, Record, logdb::KeyValue};

pub type IterFnPointer<T> = fn(fjall::Guard) -> Option<T>;
pub type TryFnPointer<T> = fn(fjall::Guard) -> DbResult<T>;
pub type RawFnPointer = fn(fjall::Guard) -> Option<KeyValue>;

pub type IterTree<T> = std::iter::FilterMap<fjall::Iter, IterFnPointer<T>>;
pub type TryIterTree<T> = std::iter::Map<fjall::Iter, TryFnPointer<T>>;
pub type RawIterTree = std::iter::FilterMap<fjall::Iter, RawFnPointer>;

#[inline]
pub fn entry_filter_map<Item: Record<Value = Slice>>(guard: Guard) -> Option<Entry<Item>> {
    match guard.into_inner() {
        Ok((key, value)) => {
            let id = Item::deser_key(&key);

            let value = Item::deser_owned(value);
            Some(Entry {
                key: id,
                val: value,
            })
        }
        Err(e) => {
            error!(%e);
            None
        }
    }
}

#[inline]
pub fn entry_map<Item: Record<Value = Slice>>(guard: Guard) -> DbResult<Entry<Item>> {
    guard.into_inner().map_err(DbError::from).map(|item| {
        let (key, value) = item;
        let id = Item::deser_key(&key);
        let val = Item::deser_owned(value);
        Entry { key: id, val }
    })
}

#[inline]
pub fn entry_map_with_raw<Item: Record<Value = Slice>>(
    guard: Guard,
) -> DbResult<ItemWithRaw<Item>> {
    guard.into_inner().map_err(DbError::from).map(|item| {
        let (key, value) = item;
        let id = Item::deser_key(&key);
        let val = Item::deser(&value);
        (key, value, Entry { key: id, val })
    })
}

#[inline]
pub fn entry_key_filter_map<Item: Record<Value = Slice>>(guard: Guard) -> Option<Item::SelfId> {
    match guard.key() {
        Ok(key) => Some(Item::deser_key(&key)),
        Err(e) => {
            error!(%e);
            None
        }
    }
}

#[inline]
pub fn raw_filter_map(guard: Guard) -> Option<KeyValue> {
    match guard.into_inner() {
        Ok(kv) => Some(kv),
        Err(e) => {
            error!(%e);
            None
        }
    }
}
