use anyhow::Result;

use super::super::*;

#[test]
#[ntest::timeout(600000)]
fn print_md_md5() -> Result<()> {
    let e = make_experiment!()?;
    print_md(e, "md5")
}

#[test]
#[ntest::timeout(600000)]
fn print_md_sha1() -> Result<()> {
    let e = make_experiment!()?;
    print_md(e, "sha1")
}

#[test]
#[ntest::timeout(600000)]
fn print_md_ripemd160() -> Result<()> {
    let e = make_experiment!()?;
    print_md(e, "ripemd160")
}

#[test]
#[ntest::timeout(600000)]
fn print_md_sha224() -> Result<()> {
    let e = make_experiment!()?;
    print_md(e, "sha224")
}

#[test]
#[ntest::timeout(600000)]
fn print_md_sha256() -> Result<()> {
    let e = make_experiment!()?;
    print_md(e, "sha256")
}

#[test]
#[ntest::timeout(600000)]
fn print_md_sha384() -> Result<()> {
    let e = make_experiment!()?;
    print_md(e, "sha384")
}

#[test]
#[ntest::timeout(600000)]
fn print_md_sha512() -> Result<()> {
    let e = make_experiment!()?;
    print_md(e, "sha512")
}

#[test]
#[ntest::timeout(600000)]
fn print_md_star() -> Result<()> {
    let e = make_experiment!()?;
    print_md(e, "*")
}

fn print_md<A: Into<Option<&'static str>>>(mut e: Experiment, arg: A) -> Result<()>
{
    let arg = arg.into();
    let foo = e.store("foo", "foo")?;
    let bar = e.store("bar", "bar")?;

    for with_colons in [false, true] {
        let mut args = vec![];

        if with_colons {
            args.push("--with-colons");
        }

        args.push("--print-md");
        if let Some(arg) = &arg {
            args.push(arg);
        }

        let extra_hashes = if arg == Some("*") {
            EXTRA_HASHES.len()
        } else {
            0
        };

        args.push(&foo);
        let diff = e.invoke(&args)?;
        diff.assert_success();
        diff.assert_limits(extra_hashes, 0, 0);

        args.push(&bar);
        let diff = e.invoke(&args)?;
        diff.assert_success();
        diff.assert_limits(extra_hashes * 2, 0, 0);
    }

    Ok(())
}

#[test]
#[ntest::timeout(600000)]
fn print_mds() -> Result<()> {
    let mut e = make_experiment!()?;

    let foo = e.store("foo", "foo")?;
    let bar = e.store("bar", "bar")?;

    for with_colons in [false, true] {
        let mut args = vec![];

        if with_colons {
            args.push("--with-colons");
        }

        args.push("--print-mds");

        args.push(&foo);
        let diff = e.invoke(&args)?;
        diff.assert_success();
        diff.assert_limits(EXTRA_HASHES.len(), 0, 0);

        args.push(&bar);
        let diff = e.invoke(&args)?;
        diff.assert_success();
        diff.assert_limits(EXTRA_HASHES.len() * 2, 0, 0);
    }

    Ok(())
}

const EXTRA_HASHES: &str = "\
/EXPERIMENT/foo: SHA3-256 = 76D3BC41 C9F588F7 FCD0D5BF 4718F8F8 4B1C41B2
                              08827031 00B9EB94 13807C01
/EXPERIMENT/foo: SHA3-512 = 4BCA2B13 7EDC580F E50A8898 3EF860EB ACA36C85
                              7B1F4928 39D6D739 2452A63C 82CBEBC6 8E3B70A2
                              A1480B4B B5D437A7 CBA6ECF9 D89F9FF3 CCD14CD6
                              146EA7E7
";
