use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
use cantrip::{Convert, Map};
use crate::extensions::util::{TestCollection, TestMap, assert_map_equal, assert_set_equal};
#[allow(clippy::too_many_lines)]
pub(crate) fn test_map<'a, C>(a_source: &C, b_source: &C, e_source: &C)
where
C: TestMap<'a, i64, i64> + Convert<(i64, i64)>,
C::This<i64, i64>: TestCollection<(i64, i64)>,
for<'i> &'i C: IntoIterator<Item = (&'i i64, &'i i64)>,
{
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.add(4, 4), HashMap::from([(1, 1), (2, 2), (3, 3), (4, 4)]));
let a = a_source.clone();
assert_map_equal(&a.add(1, 4), HashMap::from([(1, 4), (2, 2), (3, 3)]));
assert_map_equal(&e.add(1, 1), HashMap::from([(1, 1)]));
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.add_multi(vec![(4, 4), (5, 5)]), HashMap::from([(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]));
let a = a_source.clone();
assert_map_equal(&a.add_multi(vec![(1, 4), (5, 5)]), HashMap::from([(1, 4), (2, 2), (3, 3), (5, 5)]));
assert_map_equal(&e.add_multi(vec![(1, 1), (2, 2)]), HashMap::from([(1, 1), (2, 2)]));
let a = a_source.clone();
let e = e_source.clone();
assert!(a.all(|(&k, &v)| k > 0 && v > 0));
assert!(e.all(|(&k, _)| k > 0));
assert!(!a.all(|(&k, _)| k > 2));
let a = a_source.clone();
let e = e_source.clone();
assert!(a.any(|(&k, &v)| k > 0 && v > 1));
assert!(!a.any(|(&k, _)| k > 5));
assert!(!e.any(|(&k, _)| k > 0));
assert_eq!(a.collect::<BTreeSet<(i64, i64)>>(), BTreeSet::from([(1, 1), (2, 2), (3, 3)]));
assert_eq!(e.collect::<BTreeSet<(i64, i64)>>(), BTreeSet::new());
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.count_by(|(&k, &v)| k == 2 && v == 2), 1);
assert_eq!(a.count_by(|(&k, _)| k == 5), 0);
assert_eq!(e.count_by(|(&k, _)| k == 5), 0);
let b = b_source.clone();
assert_eq!(a.count_unique(), 3);
assert_eq!(b.count_unique(), 2);
assert_eq!(e.count_unique(), 0);
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.delete(&2), HashMap::from([(1, 1), (3, 3)]));
assert_map_equal(&e.delete(&2), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.delete_multi(&vec![1, 3]), HashMap::from([(2, 2)]));
let a = a_source.clone();
assert_map_equal(&a.delete_multi(&HashMap::from([(1, 1), (3, 3)]).keys()), HashMap::from([(2, 2)]));
let a = a_source.clone();
assert_map_equal(&a.delete_multi(&HashMap::from([(1, 1), (3, 3)]).values()), HashMap::from([(2, 2)]));
assert_map_equal(&e.delete_multi(&vec![1]), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert!(a.disjoint(&vec![4, 5]));
assert!(a.disjoint(&vec![]));
assert!(!a.disjoint(&vec![3, 4]));
assert!(e.disjoint(&vec![1]));
assert_map_equal(&HashMap::fill_with(|| (1, 1), 1), HashMap::from([(1, 1)]));
assert_map_equal(&HashMap::fill_with(|| (1, 1), 0), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.filter(|(&k, &v)| k != 2 && v != 2), HashMap::from([(1, 1), (3, 3)]));
assert_map_equal(&e.filter(|(&k, &v)| k != 2 && v != 2), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.filter_keys(|&k| k != 2), HashMap::from([(1, 1), (3, 3)]));
assert_map_equal(&e.filter_keys(|&k| k != 2), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.filter_values(|&v| v != 2), HashMap::from([(1, 1), (3, 3)]));
assert_map_equal(&e.filter_values(|&v| v != 2), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.filter_map(|(k, v)| if k < 2 { Some((k, v + 1)) } else { None }), HashMap::from([(1, 2)]));
assert_map_equal(&e.filter_map(|(k, v)| if k < 2 { Some((k, v + 1)) } else { None }), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.filter_map_ref(|(&k, &v)| if k < 2 { Some((k, v + 1)) } else { None }), HashMap::from([(1, 2)]));
assert_map_equal(&e.filter_map_ref(|(&k, &v)| if k < 2 { Some((k, v + 1)) } else { None }), HashMap::new());
assert_eq!(a.find(|(&k, &v)| k == 2 && v == 2), Some((&2, &2)));
assert_eq!(a.find(|(&k, _)| k == 5), None);
assert_eq!(e.find(|(&k, _)| k == 5), None);
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.find_map(|(k, v)| if k == 2 { Some(v) } else { None }), Some(2));
assert_eq!(e.find_map(|(k, v)| if k == 2 { Some(v) } else { None }), None);
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.find_map_ref(|(&k, &v)| if k == 2 { Some(v) } else { None }), Some(2));
assert_eq!(e.find_map_ref(|(&k, &v)| if k == 2 { Some(v) } else { None }), None);
assert_map_equal(
&a.flat_map(|(k, v)| vec![(-k, v), (k, v)]),
HashMap::from([(-1, 1), (-2, 2), (-3, 3), (1, 1), (2, 2), (3, 3)]),
);
assert_map_equal(&e.flat_map(|(k, v)| vec![(-k, v), (k, v)]), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(
&a.flat_map_ref(|(&k, &v)| vec![(-k, v), (k, v)]),
HashMap::from([(-1, 1), (-2, 2), (-3, 3), (1, 1), (2, 2), (3, 3)]),
);
assert_map_equal(&e.flat_map_ref(|(&k, &v)| vec![(-k, v), (k, v)]), HashMap::new());
assert_eq!(a.fold(0, |acc, (k, v)| acc + k + v), 12);
assert_eq!(e.fold(0, |acc, (k, v)| acc + k + v), 0);
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.fold_ref(0, |acc, (&k, &v)| acc + k + v), 12);
assert_eq!(e.fold_ref(0, |acc, (&k, &v)| acc + k + v), 0);
let mut acc = 0;
a.for_each(|(&k, &v)| acc += k + v);
assert_eq!(acc, 12);
e.for_each(|(&k, &v)| acc += k + v);
assert_eq!(acc, 12);
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.intersect(&vec![(4, 4), (2, 2), (3, 4), (4, 5)]), HashMap::from([(2, 2)]));
assert_map_equal(&e.intersect(&vec![(1, 1)]), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.map(|(k, v)| (k, k + v)), HashMap::from([(1, 2), (2, 4), (3, 6)]));
assert_map_equal(&e.map(|(k, v)| (k, k + v)), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.map_ref(|(&k, &v)| (k, k + v)), HashMap::from([(1, 2), (2, 4), (3, 6)]));
assert_map_equal(&e.map_ref(|(&k, &v)| (k, k + v)), HashMap::new());
assert_map_equal(&a.map_keys(|&k| k + 1), HashMap::from([(2, 1), (3, 2), (4, 3)]));
assert_map_equal(&e.map_keys(|&k| k + 1), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.map_values(|&v| v + 1), HashMap::from([(1, 2), (2, 3), (3, 4)]));
assert_map_equal(&e.map_values(|&v| v + 1), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.max_by(|x, y| x.0.cmp(y.0)), Some((&3, &3)));
assert_eq!(e.max_by(|x, y| x.0.cmp(y.0)), None);
assert_eq!(a.max_by_key(|(k, _)| -k), Some((&1, &1)));
assert_eq!(e.max_by_key(|(k, _)| -k), None);
assert_eq!(a.max_of(), Some((&3, &3)));
assert_eq!(e.max_of(), None);
assert_eq!(a.min_by(|x, y| x.0.cmp(y.0)), Some((&1, &1)));
assert_eq!(e.min_by(|x, y| x.0.cmp(y.0)), None);
assert_eq!(a.min_by_key(|(k, _)| -k), Some((&3, &3)));
assert_eq!(e.min_by_key(|(k, _)| -k), None);
assert_eq!(a.min_of(), Some((&1, &1)));
assert_eq!(e.min_of(), None);
assert_eq!(a.minmax_by(|x, y| x.0.cmp(y.0)), Some(((&1, &1), (&3, &3))));
assert_eq!(e.minmax_by(|x, y| x.0.cmp(y.0)), None);
assert_eq!(a.minmax_by_key(|(k, _)| -k), Some(((&3, &3), (&1, &1))));
assert_eq!(e.minmax_by_key(|(k, _)| -k), None);
assert_eq!(a.minmax_of(), Some(((&1, &1), (&3, &3))));
assert_eq!(e.minmax_of(), None);
let a = a_source.clone();
let e = e_source.clone();
let (a_even, a_odd) = a.partition(|(&k, _)| k % 2 == 0);
assert_map_equal(&a_even, HashMap::from([(2, 2)]));
assert_map_equal(&a_odd, HashMap::from([(1, 1), (3, 3)]));
let (e_even, e_odd) = e.partition(|(&k, _)| k % 2 == 0);
assert_map_equal(&e_even, HashMap::new());
assert_map_equal(&e_odd, HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
let (a_even, a_odd) = a.partition_map(|(k, v)| if k % 2 == 0 { Ok((k + 3, v)) } else { Err((k, v)) });
assert_map_equal(&a_even, HashMap::from([(5, 2)]));
assert_map_equal(&a_odd, HashMap::from([(1, 1), (3, 3)]));
let (e_even, e_odd) = e.partition_map(|(k, v)| if k % 2 == 0 { Ok((k + 3, v)) } else { Err((k, v)) });
assert_map_equal(&e_even, HashMap::new());
assert_map_equal(&e_odd, HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
let (a_even, a_odd) = a.partition_map_ref(|(&k, &v)| if k % 2 == 0 { Ok((k + 3, v)) } else { Err((k, v)) });
assert_map_equal(&a_even, HashMap::from([(5, 2)]));
assert_map_equal(&a_odd, HashMap::from([(1, 1), (3, 3)]));
let (e_even, e_odd) = e.partition_map_ref(|(&k, &v)| if k % 2 == 0 { Ok((k + 3, v)) } else { Err((k, v)) });
assert_map_equal(&e_even, HashMap::new());
assert_map_equal(&e_odd, HashMap::new());
assert_eq!(a.product_keys(), 6);
assert_eq!(e.product_keys(), 1);
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.product_values(), 6);
assert_eq!(e.product_values(), 1);
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.reduce(|(a, b), (k, v)| (a + k, b + v)), Some((6, 6)));
assert_eq!(e.reduce(|(a, b), (k, v)| (a + k, b + v)), None);
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.reduce_ref(|(&a, &b), (&k, &v)| (a + k, b + v)), Some((6, 6)));
assert_eq!(e.reduce_ref(|(&a, &b), (&k, &v)| (a + k, b + v)), None);
assert!(a.subset(&vec![4, 3, 2, 2, 1]));
assert!(e.subset(&vec![1]));
assert!(!a.subset(&vec![1, 2]));
assert!(!a.subset(&vec![]));
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.substitute(&3, 4, 4), HashMap::from([(1, 1), (2, 2), (4, 4)]));
assert_map_equal(&e.substitute(&3, 4, 4), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_map_equal(&a.substitute_multi(&vec![2, 3], vec![(4, 4), (5, 5)]), HashMap::from([(1, 1), (4, 4), (5, 5)]));
assert_map_equal(&e.substitute_multi(&vec![2, 3], vec![(4, 4), (5, 5)]), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert!(a.superset(&vec![3, 1]));
assert!(a.superset(&vec![]));
assert!(!a.superset(&vec![1, 2, 3, 4]));
assert!(!a.superset(&vec![1, 2, 2]));
assert!(!a.superset(&vec![3, 4]));
assert!(!e.superset(&vec![1]));
assert_eq!(a.sum_keys(), 6);
assert_eq!(e.sum_keys(), 0);
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.sum_values(), 6);
assert_eq!(e.sum_values(), 0);
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.to_bmap(), BTreeMap::from([(1, 1), (2, 2), (3, 3)]));
assert_eq!(e.to_bmap(), BTreeMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.to_bset(), BTreeSet::from([(1, 1), (2, 2), (3, 3)]));
assert_eq!(e.to_bset(), BTreeSet::new());
let a = a_source.clone();
let e = e_source.clone();
assert_set_equal(a.to_deque(), vec![(1, 1), (2, 2), (3, 3)]);
assert_eq!(e.to_deque(), VecDeque::new());
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(
a.to_heap().into_iter().collect::<HashSet<_>>(),
BinaryHeap::from([(1, 1), (2, 2), (3, 3)]).into_iter().collect()
);
assert_eq!(e.to_heap().into_iter().collect::<HashSet<_>>(), BinaryHeap::from([]).into_iter().collect());
let a = a_source.clone();
let e = e_source.clone();
assert_set_equal(a.to_keys(), vec![1, 2, 3]);
assert_set_equal(e.to_keys(), vec![]);
let a = a_source.clone();
let e = e_source.clone();
assert_set_equal(a.to_list(), vec![(1, 1), (2, 2), (3, 3)]);
assert_eq!(e.to_list(), LinkedList::new());
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.to_map(), HashMap::from([(1, 1), (2, 2), (3, 3)]));
assert_eq!(e.to_map(), HashMap::new());
let a = a_source.clone();
let e = e_source.clone();
assert_eq!(a.to_set(), HashSet::from([(1, 1), (2, 2), (3, 3)]));
assert_eq!(e.to_set(), HashSet::new());
let a = a_source.clone();
let e = e_source.clone();
assert_set_equal(a.to_values(), vec![1, 2, 3]);
assert_set_equal(e.to_values(), vec![]);
let a = a_source.clone();
let e = e_source.clone();
assert_set_equal(a.to_vec(), vec![(1, 1), (2, 2), (3, 3)]);
assert_eq!(e.to_vec(), vec![]);
assert_map_equal(&HashMap::unit(1, 1), HashMap::from([(1, 1)]));
}