use super::*;
use crate::change::*;
use crate::working_copy::WorkingCopy;
#[test]
fn add_non_utf8_file_test() -> Result<(), anyhow::Error> {
    env_logger::try_init().unwrap_or(());
    let mut buf = Vec::new();
    use std::io::Read;
    let mut fh = std::fs::File::open("src/tests/data/1252.1")?;
    fh.read_to_end(&mut buf)?;
    let mut repo = working_copy::memory::Memory::new();
    repo.add_file("file", buf);
    let env = pristine::sanakirja::Pristine::new_anon()?;
    let mut txn = env.mut_txn_begin();
    let mut channel = txn.open_or_create_channel("main")?;
    txn.add_file("file")?;
    let store = changestore::memory::Memory::new();
    let (h, change) = record_all(&mut repo, &store, &mut txn, &mut channel, "")?;
    let mut v = Vec::new();
    change
        .write(
            &store,
            Some(h),
            |l, _p| format!("{}:{}", l.path, l.line),
            true,
            &mut v,
        )
        .unwrap();
    for l in std::str::from_utf8(&v).unwrap().lines() {
        error!("{:?}", l);
    }
    let lines = std::str::from_utf8(&v).unwrap().lines();
    assert_eq!(
        1,
        lines
            .clone()
            .filter(|l| l.starts_with("+") && l.contains("French / Français (Windows CP 1252)"))
            .count()
    );
    assert_eq!(
        1,
        lines
            .filter(|l| l.starts_with("+") && l.contains("€‚ƒ„…†‡, Salut"))
            .count()
    );
    Ok(())
}
/// Change a non-utf-8 text file.
#[test]
fn change_non_utf8_file_test() -> Result<(), anyhow::Error> {
    env_logger::try_init().unwrap_or(());
    let mut buf = Vec::new();
    use std::io::Read;
    let mut fh = std::fs::File::open("src/tests/data/8859-1.1")?;
    fh.read_to_end(&mut buf)?;
    let mut repo = working_copy::memory::Memory::new();
    repo.add_file("file", buf);
    let env = pristine::sanakirja::Pristine::new_anon()?;
    let mut txn = env.mut_txn_begin();
    let mut channel = txn.open_or_create_channel("main")?;
    txn.add_file("file")?;
    let store = changestore::memory::Memory::new();
    record_all(&mut repo, &store, &mut txn, &mut channel, "")?;
    let mut buf = Vec::new();
    {
        use std::io::Read;
        let mut fh = std::fs::File::open("src/tests/data/8859-1.2")?;
        fh.read_to_end(&mut buf)?;
    }
    repo.write_file::<_, std::io::Error, _>("file", |w| {
        w.write_all(&buf).unwrap();
        Ok(())
    })?;
    let (h1, change1) = record_all(&mut repo, &store, &mut txn, &mut channel, "")?;
    // only one line was changed
    let mut v = Vec::new();
    change1
        .write(
            &store,
            Some(h1),
            |l, _p| format!("{}:{}", l.path, l.line),
            true,
            &mut v,
        )
        .unwrap();
    for l in std::str::from_utf8(&v).unwrap().lines() {
        error!("{:?}", l);
    }
    assert_eq!(
        1,
        std::str::from_utf8(&v)
            .unwrap()
            .lines()
            .filter(|l| l.starts_with("-")
                && l.contains("French / Français (ISO Latin-1 / ISO 8859-1)"))
            .count()
    );
    Ok(())
}
fn record_all<T: MutTxnT, R: WorkingCopy, P: ChangeStore>(
    repo: &mut R,
    store: &P,
    txn: &mut T,
    channel: &mut ChannelRef<T>,
    prefix: &str,
) -> Result<(Hash, Change), anyhow::Error>
where
    R::Error: Send + Sync + 'static,
{
    let mut state = Builder::new();
    state.record(txn, Algorithm::default(), channel, repo, store, prefix)?;
    let rec = state.finish();
    let changes = rec
        .actions
        .into_iter()
        .map(|rec| rec.globalize(txn))
        .collect();
    let change0 = crate::change::Change::make_change(
        txn,
        &channel,
        changes,
        rec.contents,
        crate::change::ChangeHeader {
            message: "test".to_string(),
            authors: vec![],
            description: None,
            // Beware of changing the following line: two changes
            // doing the same thing will be equal. Sometimes we don't
            // want that, as in tests::unrecord::unrecord_double.
            timestamp: chrono::Utc::now(),
        },
        Vec::new(),
    );
    let hash = store.save_change(&change0)?;
    apply::apply_local_change(txn, channel, &change0, hash, &rec.updatables)?;
    Ok((hash, change0))
}