use super::{Change, ChangeSet, ICacheUpdater, IChangeSet, IConnectableCache, IObservableCache, ObservableCache};
use ferroui_system::collections::generic::Dictionary;
use ferroui_system::{IDisposable, IObservable};
use std::hash::Hash;
use std::rc::Rc;
pub trait IIntermediateCache<T, K>: IObservableCache<T, K> {
fn edit(&self, update: &mut dyn FnMut(&mut dyn ICacheUpdater<T, K>));
}
pub struct IntermediateCache<T, K> {
inner: ObservableCache<T, K>,
}
impl<T, K> Clone for IntermediateCache<T, K> {
fn clone(&self) -> Self {
Self { inner: self.inner.clone() }
}
}
impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> Default for IntermediateCache<T, K> {
fn default() -> Self {
Self::new()
}
}
impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> IntermediateCache<T, K> {
pub fn new() -> Self {
Self { inner: ObservableCache::without_key_selector() }
}
pub fn from_source<C: IChangeSet<T, K>>(source: Rc<dyn IObservable<C>>) -> Self {
Self { inner: ObservableCache::from_source(source) }
}
pub fn edit(&self, update: impl FnOnce(&mut dyn ICacheUpdater<T, K>)) {
self.inner.update_from_intermediate(update);
}
pub fn suspend_count(&self) -> Rc<dyn IDisposable> {
self.inner.suspend_count()
}
pub fn suspend_notifications(&self) -> Rc<dyn IDisposable> {
self.inner.suspend_notifications()
}
pub fn add_or_update(&self, item: T, key: K) {
self.edit(|updater| updater.add_or_update_with_key(item, key));
}
pub fn clear(&self) {
self.edit(|updater| updater.clear());
}
pub fn remove_key(&self, key: K) {
self.edit(|updater| updater.remove_key(&key));
}
pub fn remove_keys(&self, keys: impl IntoIterator<Item = K>) {
let keys: Vec<K> = keys.into_iter().collect();
self.edit(|updater| updater.remove_keys(&mut keys.into_iter()));
}
}
impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> IConnectableCache<T, K> for IntermediateCache<T, K> {
fn count_changed(&self) -> Rc<dyn IObservable<usize>> {
self.inner.count_changed()
}
fn connect_with(&self, predicate: Option<Rc<dyn Fn(&T) -> bool>>, suppress_empty_change_sets: bool) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
self.inner.connect_with(predicate, suppress_empty_change_sets)
}
fn preview_with(&self, predicate: Option<Rc<dyn Fn(&T) -> bool>>) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
self.inner.preview_with(predicate)
}
fn watch(&self, key: K) -> Rc<dyn IObservable<Change<T, K>>> {
self.inner.watch(key)
}
}
impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> IObservableCache<T, K> for IntermediateCache<T, K> {
fn count(&self) -> usize {
self.inner.count()
}
fn items(&self) -> Vec<T> {
self.inner.items()
}
fn keys(&self) -> Vec<K> {
self.inner.keys()
}
fn key_values(&self) -> Dictionary<K, T> {
self.inner.key_values()
}
fn lookup(&self, key: &K) -> Option<T> {
self.inner.lookup(key)
}
}
impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> IIntermediateCache<T, K> for IntermediateCache<T, K> {
fn edit(&self, update: &mut dyn FnMut(&mut dyn ICacheUpdater<T, K>)) {
self.inner.update_from_intermediate(|updater| update(updater));
}
}
impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> IDisposable for IntermediateCache<T, K> {
fn dispose(&self) {
self.inner.dispose();
}
}