use asteroidsfactory::config::parameters::SOLAR_MASS;
use asteroidsfactory::types::*;

fn main() {
    let apollo = near_earth::NearEarthAsteroid::new(500.0, 2500.0, 1.5, 0.4)
        .with_inclination(10.0)
        .with_albedo(0.15);

    let mass = apollo.mass;
    let g = apollo.surface_gravity();
    let v_esc = apollo.escape_velocity();
    let period = apollo.orbital_period();
    let peri = apollo.perihelion_au();
    let aph = apollo.aphelion_au();
    let h_mag = apollo.absolute_magnitude();
    let tj = apollo.tisserand_jupiter();
    let temp = apollo.equilibrium_temp_perihelion();

    assert!(mass > 0.0);
    assert!(g > 0.0);
    assert!(v_esc > 0.0);
    assert!(period > 0.0);
    assert!(peri < aph);
    assert!(h_mag > 0.0);
    assert!(tj > 0.0 && tj < 6.0);
    assert!(temp > 0.0);

    let vesta = main_belt::MainBeltAsteroid::new(265000.0, 3456.0, 2.362)
        .with_eccentricity(0.089)
        .with_inclination(7.14)
        .with_spectral_type(main_belt::SpectralType::V)
        .with_rotation_period(5.342);

    let vesta_mass = vesta.mass;
    let vesta_period = vesta.orbital_period();
    let in_gap = vesta.is_in_kirkwood_gap();

    assert!(vesta_mass > 1.0e20);
    assert!(vesta_period > 0.0);
    assert!(!in_gap);

    let jupiter_trojan = trojan::Trojan::new(50000.0, 2000.0, 5.2)
        .with_lagrange_point(trojan::TrojanPoint::L4)
        .with_libration_amplitude(12.0)
        .with_eccentricity(0.06)
        .with_inclination(15.0);

    let lib_period = jupiter_trojan.libration_period();
    let lag_angle = jupiter_trojan.lagrange_angle();
    let stability = jupiter_trojan.stability_parameter(SOLAR_MASS);

    assert!(lib_period > 0.0);
    assert!((lag_angle - std::f64::consts::PI / 3.0).abs() < 0.01);
    assert!(stability > 0.0);

    let chiron = centaur::Centaur::new(120000.0, 1000.0, 13.7, 0.38)
        .with_inclination(6.9)
        .with_albedo(0.15);

    let chiron_tj = chiron.tisserand_jupiter();
    let chiron_tn = chiron.tisserand_neptune();
    let lifetime = chiron.dynamical_lifetime_estimate();

    assert!(chiron_tj > 0.0);
    assert!(chiron_tn > 0.0);
    assert!(lifetime > 0.0);

    let didymos = binary::BinaryAsteroid::new(390.0, 80.0, 2170.0, 1180.0)
        .with_heliocentric_orbit(1.644, 0.384)
        .with_mutual_eccentricity(0.03);

    let mut_period = didymos.mutual_orbital_period();
    let is_stable = didymos.is_stable();
    let is_contact = didymos.is_contact_binary();

    assert!(mut_period > 0.0);
    assert!(is_stable);
    assert!(!is_contact);

    let bennu = rubble_pile::RubblePile::new(245.0, 3400.0, 0.5)
        .with_orbit(1.126, 0.204)
        .with_rotation_period(4.288);

    let bennu_bulk = bennu.bulk_density;
    let spin_lim = bennu.spin_limit_period();
    let spin_ok = bennu.is_spin_stable();
    let yorp = bennu.yorp_timescale(1.126);

    assert!(bennu_bulk < bennu.grain_density);
    assert!(spin_lim > 0.0);
    assert!(spin_ok);
    assert!(yorp > 0.0);

    let psyche = metallic::MetallicAsteroid::new(113000.0, 0.85)
        .with_nickel_fraction(0.06)
        .with_orbit(2.922, 0.134);

    let metal_mass = psyche.metal_content_mass();
    let is_diff = psyche.is_differentiated();
    let core_r = psyche.core_radius_estimate();

    assert!(metal_mass > 0.0);
    assert!(is_diff);
    assert!(core_r > 0.0 && core_r <= psyche.radius);

    let apophis = pha::PotentiallyHazardousAsteroid::new(185.0, 2600.0, 0.922, 0.191, 0.00025)
        .with_inclination(3.3)
        .with_albedo(0.3);

    let is_pha = apophis.is_pha();
    let energy_mt = apophis.impact_energy_megatons();
    let torino = apophis.torino_scale_estimate();
    let crater = apophis.crater_diameter_estimate();

    assert!(is_pha);
    assert!(energy_mt > 0.0);
    assert!(torino <= 10);
    assert!(crater > 0.0);

    let sum = mass
        + g
        + v_esc
        + period
        + peri
        + aph
        + h_mag
        + tj
        + temp
        + vesta_mass
        + vesta_period
        + lib_period
        + lag_angle
        + stability
        + chiron_tj
        + chiron_tn
        + lifetime
        + mut_period
        + didymos.mutual_orbital_velocity_primary()
        + bennu_bulk
        + spin_lim
        + yorp
        + metal_mass
        + core_r
        + energy_mt
        + crater;

    assert!(sum > 0.0);
    assert!(!in_gap);
    assert!(is_stable);
    assert!(is_diff);
    assert!(is_pha);
    assert!(torino <= 10);
}
