mod cosmic;
mod mission_design;
mod monte_carlo;
mod orbit_determination;
mod propagation;
mod propulsion;

use std::sync::Arc;

use anise::{
    almanac::metaload::MetaFile,
    constants::celestial_objects::{EARTH, MOON, SUN},
    prelude::Almanac,
};
use propagation::{GMAT_EARTH_GM, GMAT_MOON_GM, GMAT_SUN_GM};

fn base_almanac() -> Almanac {
    use std::path::PathBuf;

    let manifest_dir: PathBuf = [env!("CARGO_MANIFEST_DIR"), "../data/01_planetary"]
        .iter()
        .collect();

    Almanac::new(&manifest_dir.join("pck08.pca").to_string_lossy())
        .unwrap()
        .load(
            &manifest_dir
                .join("earth_longterm_000101_251211_250915.bpc")
                .to_string_lossy(),
        )
        .unwrap()
        .load(
            &manifest_dir
                .join("earth_latest_high_prec.bpc")
                .to_string_lossy(),
        )
        .unwrap()
}

pub fn test_almanac() -> Almanac {
    use std::path::PathBuf;

    let manifest_dir: PathBuf = [env!("CARGO_MANIFEST_DIR"), "../data/01_planetary"]
        .iter()
        .collect();

    base_almanac()
        .load(&manifest_dir.join("de440s.bsp").to_string_lossy())
        .unwrap()
}

pub fn test_almanac_arcd() -> Arc<Almanac> {
    Arc::new(test_almanac())
}

pub fn test_almanac_gmat_arcd() -> Arc<Almanac> {
    // We don't want to store the de438 file in the repo, so we grab it from the cloud if the CRC of the local cache does not match.
    let mut de438 = MetaFile {
        uri: "http://public-data.nyxspace.com/anise/de438.bsp".to_string(),
        crc32: Some(1111895644),
    };
    de438.process(true).unwrap();

    let mut almanac = test_almanac();
    almanac = almanac.load(&de438.uri).unwrap();
    // Update GM values
    let mut earth = almanac.get_planetary_data_from_id(EARTH).unwrap();
    earth.mu_km3_s2 = GMAT_EARTH_GM;
    almanac.set_planetary_data_from_id(EARTH, earth).unwrap();

    let mut sun = almanac.get_planetary_data_from_id(SUN).unwrap();
    sun.mu_km3_s2 = GMAT_SUN_GM;
    almanac.set_planetary_data_from_id(SUN, sun).unwrap();

    let mut moon = almanac.get_planetary_data_from_id(MOON).unwrap();
    moon.mu_km3_s2 = GMAT_MOON_GM;
    almanac.set_planetary_data_from_id(MOON, moon).unwrap();

    Arc::new(almanac)
}
