use std::sync::Arc;

use radn::{
    flow::{comparator::*, traversible::algorithms::subset::*},
    func::*,
    mrds::trees::unbalanced::*,
    rstd::tracing::*,
};
use rand::{Rng, SeedableRng};

type TracedMonad = instances::composition::CompositionInstance<
    TracedInstance,
    instances::result::ResultInstance<()>,
>;

trait FromSlice<R> {
    type Tree;
    type A;

    fn from_slice(self: &Arc<Self>, rng: &mut R, slice: &[Self::A]) -> Arc<Self::Tree>;
}

impl<'a, T: Monad<'a>, A: 'a + Send + Sync + Clone, R: 'a + rand::Rng> FromSlice<R>
    for UnbalancedConstructor<'a, T, A>
{
    type A = A;
    type Tree = UnbalancedTree<'a, T, A>;

    fn from_slice(self: &Arc<Self>, rng: &mut R, slice: &[Self::A]) -> Arc<Self::Tree> {
        if slice.is_empty() {
            self.leaf()
        } else {
            let key_at = rng.gen_range(0..slice.len());
            let key = slice[key_at].clone();
            let lslice = &slice[..key_at];
            let rslice = &slice[key_at + 1..];
            self.clone().node(
                self.clone().from_slice(rng, lslice),
                key,
                self.clone().from_slice(rng, rslice),
            )
        }
    }
}

fn main() {
    let ctr: Arc<UnbalancedConstructor<TracedMonad, _>> =
        UnbalancedConstructor::rc(Box::new(|node| {
            Box::new(move || TracedMonad::pure(node.clone()).after_resolution())
        }));
    let mut rng = rand::rngs::StdRng::seed_from_u64(426);
    let big: Vec<i32> = (0..(rng.gen_range(1000..2000))).collect();
    let key = big[rng.gen_range(0..big.len())];
    let small: Vec<i32> = big
        .iter()
        .filter(|x| **x != key && rng.gen_ratio(4, 5))
        .copied()
        .collect();
    let t_small = ctr.from_slice(&mut rng, &small);
    let t_big = ctr.from_slice(&mut rng, &big);
    let traced = t_subset_of_t(
        &DefaultComparator,
        t_small.clone(),
        t_big.clone(),
        None,
        None,
    );
    assert!(traced.value.is_ok());
    println!("{:?}", traced.render().to_vec());
}