// License: see LICENSE file at root directory of `master` branch

extern crate dia_semver;

use {
    core::str::FromStr,

    dia_semver::{Semver, PreRelease},
};

#[test]
fn kit() {
    assert_eq!(Semver::MAX_INPUT_STR_LEN, 2048_u16);

    assert!(Semver::new(1, 0, 0).is_stable());
    assert!(Semver::new(0, 0, 0).is_stable() == false);
    assert!(Semver::new(0, 0, 0).pre_release().is_none());
    assert!(Semver::new(0, 0, 0).build_metadata().is_none());
    assert!(Semver::from_str("1.0.0+abc").unwrap().is_stable());
    assert!(Semver::parse("1.0.0-xyz").unwrap().is_stable() == false);

    let s = Semver::new(1, 2, 3);
    assert!(s.pre_release().is_none() && s.build_metadata().is_none());
    assert_eq!(s.major(), 1);
    assert_eq!(s.minor(), 2);
    assert_eq!(s.patch(), 3);

    assert!(Semver::from_str("1.0.0").unwrap().is_early() == false);
    assert!(Semver::from_str("1.2.3-abc+xyz").unwrap().is_early() == false);
    assert!(Semver::from_str("0.9.9-xyz+abc").unwrap().is_early());
    assert!(Semver::new(0, 0, 0).is_early());

    assert_eq!(Semver::from_str("1.0.0-alpha").unwrap().parse_pre_release(), Some(PreRelease::Alpha));
    assert_eq!(Semver::from_str("1.0.0-ALPHA.1").unwrap().parse_pre_release(), Some(PreRelease::Alpha));
    assert_eq!(Semver::from_str("1.0.0-ALPHA00").unwrap().parse_pre_release(), Some(PreRelease::Alpha));
    assert_eq!(Semver::from_str("1.0.0-alpha-99").unwrap().parse_pre_release(), Some(PreRelease::Alpha));
    assert_eq!(Semver::from_str("1.0.0-al-99").unwrap().parse_pre_release(), Some(PreRelease::Other));
    assert_eq!(Semver::from_str("1.0.0").unwrap().parse_pre_release(), None);

    assert_eq!(Semver::from_str("1.0.0-beta").unwrap().parse_pre_release(), Some(PreRelease::Beta));
    assert_eq!(Semver::from_str("1.0.0-BETA.1").unwrap().parse_pre_release(), Some(PreRelease::Beta));
    assert_eq!(Semver::from_str("1.0.0-BETA00").unwrap().parse_pre_release(), Some(PreRelease::Beta));
    assert_eq!(Semver::from_str("1.0.0-beta-99").unwrap().parse_pre_release(), Some(PreRelease::Beta));
    assert_eq!(Semver::from_str("1.0.0-BET").unwrap().parse_pre_release(), Some(PreRelease::Other));
    assert_eq!(Semver::from_str("1.0.0").unwrap().parse_pre_release(), None);

    assert_eq!(Semver::from_str("1.0.0-rc").unwrap().parse_pre_release(), Some(PreRelease::RC));
    assert_eq!(Semver::from_str("1.0.0-RC.1").unwrap().parse_pre_release(), Some(PreRelease::RC));
    assert_eq!(Semver::from_str("1.0.0-RC00").unwrap().parse_pre_release(), Some(PreRelease::RC));
    assert_eq!(Semver::from_str("1.0.0-rc-99").unwrap().parse_pre_release(), Some(PreRelease::RC));
    assert_eq!(Semver::from_str("1.0.0-R").unwrap().parse_pre_release(), Some(PreRelease::Other));
    assert_eq!(Semver::from_str("1.0.0").unwrap().parse_pre_release(), None);

    let s = Semver::from_str("1.0.0-ALPHA").unwrap();
    assert!(s.parse_pre_release() == Some(PreRelease::Alpha) && s.is_stable() == false && s.is_early() == false);

    let s = Semver::from_str("0.0.1-BETA+123").unwrap();
    assert!(s.parse_pre_release() == Some(PreRelease::Beta) && s.is_stable() == false && s.is_early());

    let s = Semver::from_str("0.0.1-RC+123").unwrap();
    assert!(s.is_stable() == false && s.is_early() && s.parse_pre_release() == Some(PreRelease::RC));

    assert_eq!(Semver::from_str("0.0.1-abc+xyz").unwrap().new_patch().unwrap().to_string(), "0.0.2");
    assert_eq!(Semver::from_str("0").unwrap().new_patch().unwrap().to_string(), "0.0.1");

    assert_eq!(Semver::from_str("0.0.1-abc+xyz").unwrap().new_minor().unwrap().to_string(), "0.1.0");
    assert_eq!(Semver::from_str("0").unwrap().new_minor().unwrap().to_string(), "0.1.0");

    assert_eq!(Semver::from_str("0.0.1-abc+xyz").unwrap().new_major().unwrap().to_string(), "1.0.0");
    assert_eq!(Semver::from_str("0").unwrap().new_major().unwrap().to_string(), "1.0.0");

    assert_eq!(Semver::from_str("1.2.3+abc").unwrap().new_pre_release("alpha.1", false).unwrap().to_string(), "1.2.3-alpha.1");
    assert_eq!(Semver::from_str("1.2.3+abc").unwrap().new_pre_release("alpha.1", true).unwrap().to_string(), "1.2.3-alpha.1+abc");
    assert_eq!(Semver::from_str("1.2.3-alpha.2+abc").unwrap().new_pre_release("beta.1", false).unwrap().to_string(), "1.2.3-beta.1");
    assert_eq!(Semver::from_str("1.2.3-BETA.1+abc").unwrap().new_pre_release("beta.2", true).unwrap().to_string(), "1.2.3-beta.2+abc");
    assert_eq!(Semver::from_str("1.2.3").unwrap().new_pre_release("RC.1", false).unwrap().to_string(), "1.2.3-RC.1");
    assert_eq!(Semver::from_str("1.2.3").unwrap().new_pre_release("rc.2", true).unwrap().to_string(), "1.2.3-rc.2");

    assert_eq!(Semver::from_str("1.2.3+abc").unwrap().new_build_metadata("xyz", false).unwrap().to_string(), "1.2.3+xyz");
    assert_eq!(Semver::from_str("1.2.3+abc").unwrap().new_build_metadata("xyz", true).unwrap().to_string(), "1.2.3+xyz");
    assert_eq!(Semver::from_str("1.2.3-alpha.2+abc").unwrap().new_build_metadata("swift", false).unwrap().to_string(), "1.2.3+swift");
    assert_eq!(Semver::from_str("1.2.3-BETA.1+abc").unwrap().new_build_metadata("swift", true).unwrap().to_string(), "1.2.3-BETA.1+swift");
    assert_eq!(Semver::from_str("1.2.3").unwrap().new_build_metadata("fedora", false).unwrap().to_string(), "1.2.3+fedora");
    assert_eq!(Semver::from_str("1.2.3").unwrap().new_build_metadata("fedora", true).unwrap().to_string(), "1.2.3+fedora");

    assert_eq!(PreRelease::Alpha.to_string(), "alpha");
    assert_ne!(PreRelease::Alpha.to_string(), "Alpha");
    assert_ne!(PreRelease::Alpha.to_string(), "ALPHA");

    assert_eq!(PreRelease::Beta.to_string(), "beta");
    assert_ne!(PreRelease::Beta.to_string(), "Beta");
    assert_ne!(PreRelease::Beta.to_string(), "BETA");

    assert_eq!(PreRelease::RC.to_string(), "rc");
    assert_ne!(PreRelease::RC.to_string(), "RC");
    assert_ne!(PreRelease::RC.to_string(), "Rc");
    assert_ne!(PreRelease::RC.to_string(), "rC");

    // Test if we accidentally take ownership while implementing std::fmt::Display for PreRelease
    let alpha = PreRelease::Alpha;
    println!("{}", alpha);
    println!("{}", alpha.to_string());
    assert_eq!(alpha, PreRelease::Alpha);
    assert_ne!(alpha, PreRelease::RC);

    let s = Semver::new(1, 2, 3);
    assert_eq!(s, s.clone());
    assert!(s < s.clone().new_patch().unwrap());
    assert!(s > s.clone().new_pre_release("abc", false).unwrap());
    assert_eq!(s, s.clone().new_build_metadata("xyz", false).unwrap());

    // compatible_with()
    assert!(Semver::new(0, 1, 2).compatible_with(&Semver::new(0, 1, 2)));
    assert!(Semver::new(0, 1, 2).compatible_with(&Semver::new(0, 1, 3)) == false);
    assert!(Semver::from_str("0.1.2-abc").unwrap().compatible_with(&Semver::from_str("0.1.2-abc").unwrap()));
    assert!(Semver::from_str("0.1.2-abc").unwrap().compatible_with(&Semver::from_str("0.1.2-abc+xyz").unwrap()));
    assert!(Semver::from_str("0.1.2-abc").unwrap().compatible_with(&Semver::from_str("0.1.3-abc+xyz").unwrap()) == false);
    assert!(Semver::from_str("0.1.2-abc").unwrap().compatible_with(&Semver::from_str("0.1.2-ABC").unwrap()) == false);

    // Overflow
    let max_version_number = Semver::default().major().wrapping_sub(1);
    assert_eq!(Semver::new(max_version_number, 1, 2).new_major(), None);
    assert_eq!(Semver::new(1, max_version_number, 2).new_minor(), None);
    assert_eq!(Semver::new(1, 2, max_version_number).new_patch(), None);
}
