use petname::Petnames;

mod mocks;

#[test]
#[cfg(feature = "default-words")]
fn petnames_default_has_adjectives() {
    let petnames = Petnames::default();
    assert_ne!(petnames.adjectives.len(), 0);
}

#[test]
#[cfg(feature = "default-words")]
fn petnames_default_has_adverbs() {
    let petnames = Petnames::default();
    assert_ne!(petnames.adverbs.len(), 0);
}

#[test]
#[cfg(feature = "default-words")]
fn petnames_default_has_names() {
    let petnames = Petnames::default();
    assert_ne!(petnames.nouns.len(), 0);
}

#[test]
fn petnames_retain_applies_given_predicate() {
    let petnames_expected = Petnames::new("bob", "bob", "bob jane");
    let mut petnames = Petnames::new("alice bob carol", "alice bob", "bob carol jane");
    petnames.retain(|word| word.len() < 5);
    assert_eq!(petnames_expected, petnames);
}

#[test]
#[cfg(feature = "default-words")]
fn petnames_default_has_non_zero_cardinality() {
    let petnames = Petnames::default();
    // This test will need to be adjusted when word lists change.
    assert_eq!(0, petnames.cardinality(0));
    assert_eq!(1052, petnames.cardinality(1));
    assert_eq!(1260296, petnames.cardinality(2));
    assert_eq!(2054282480, petnames.cardinality(3));
    assert_eq!(3348480442400, petnames.cardinality(4));
}

#[test]
fn petnames_generate_uses_adverb_adjective_name() {
    let petnames = Petnames {
        adjectives: vec!["adjective"].into(),
        adverbs: vec!["adverb"].into(),
        nouns: vec!["noun"].into(),
    };
    assert_eq!(
        petnames.namer(3, "-").iter(&mut mocks::StepRng::new(0, 1)).next(),
        Some("adverb-adjective-noun".into())
    );
}

#[test]
fn petnames_iter_yields_names() {
    let mut rng = mocks::StepRng::new(0, 1);
    let petnames = Petnames::new("foo", "bar", "baz");
    let namer = petnames.namer(3, ".");
    let mut names = namer.iter(&mut rng);
    assert_eq!(Some("bar.foo.baz".to_string()), names.next());
}

#[test]
fn petnames_iter_yields_nothing_when_empty() {
    let mut rng = mocks::StepRng::new(0, 1);
    let petnames = Petnames::new("", "", "");
    assert_eq!(0, petnames.cardinality(3));
    let namer = petnames.namer(3, ".");
    let mut names = namer.iter(&mut rng);
    assert_eq!(None, names.next());
}

#[test]
fn petnames_generate_into_works() {
    let mut rng = mocks::StepRng::new(0, 1);
    let words = ["adj", "adv", "noun"];
    let petnames = Petnames::new(words[0], words[1], words[2]);
    let mut buf = String::new();
    petnames.namer(3, " ").generate_into(&mut buf, &mut rng);
    assert_eq!("adv adj noun", &buf);
}
