use super::*;
use crate::alive::retrieve;
use rand::distributions::Alphanumeric;
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha20Rng;
use std::io::Write;

#[test]
fn bin_diff_test() -> Result<(), anyhow::Error> {
    env_logger::try_init().unwrap_or(());

    let repo = working_copy::memory::Memory::new();
    let changes = changestore::memory::Memory::new();
    let mut contents = Vec::new();
    repo.add_file("file", contents.clone());
    let env = pristine::sanakirja::Pristine::new_anon()?;
    let id = {
        let txn = env.arc_txn_begin().unwrap();
        txn.write().add_file("file", 0).unwrap();
        let channel = txn.write().open_or_create_channel("main").unwrap();
        let h = record_all(&repo, &changes, &txn, &channel, "").unwrap();
        let id = *txn.read().get_internal(&h.into()).unwrap().unwrap();
        txn.commit().unwrap();
        id
    };
    let mut rng = ChaCha20Rng::seed_from_u64(1234);
    for i in 0..1000 {
        contents.extend((&mut rng).sample_iter(&Alphanumeric).take(80));
        contents.push(b'\n');
        repo.write_file("file", Inode::ROOT)
            .unwrap()
            .write_all(&contents)
            .unwrap();
        if i % 10 == 0 {
            let txn = env.arc_txn_begin().unwrap();
            let channel = txn.write().open_or_create_channel("main").unwrap();
            record_all(&repo, &changes, &txn, &channel, "").unwrap();
            txn.commit().unwrap();
        }
    }
    {
        let txn = env.arc_txn_begin().unwrap();
        let channel = txn.write().open_or_create_channel("main").unwrap();
        record_all(&repo, &changes, &txn, &channel, "").unwrap();
        txn.commit().unwrap();
    }
    let len = contents.len();
    if contents[len / 2] == b'y' {
        contents[len / 2] = b'x'
    } else {
        contents[len / 2] = b'y'
    }
    {
        let txn = env.arc_txn_begin().unwrap();
        let channel = txn.write().open_or_create_channel("main").unwrap();
        debug_to_file(&*txn.read(), &channel, "debug").unwrap();
        let mut rec = crate::record::Builder::new();
        let rec = rec.recorded();
        let vertex = Position {
            change: id,
            pos: ChangePosition(1u64.into()),
        };
        let mut ret = retrieve(
            &*txn.read(),
            txn.read().graph(&*channel.read()),
            vertex,
            false,
        )?;
        rec.lock().diff(
            &changes,
            &txn,
            &channel,
            crate::record::Algorithm::Myers,
            false,
            String::new(),
            Inode::ROOT,
            vertex.to_option(),
            &mut ret,
            &contents,
            &None,
            &crate::DEFAULT_SEPARATOR,
        )?;
        debug!("{:#?}", rec.lock().actions);
        record_all(&repo, &changes, &txn, &channel, "").unwrap();
        debug_to_file(&*txn.read(), &channel, "debug").unwrap();
        // txn.commit().unwrap()
    }
    Ok(())
}