use crate::config::parameters::*;

pub fn kozai_lidov_period(
    outer_period: f64,
    mass_ratio: f64,
    inner_semi: f64,
    outer_semi: f64,
    outer_ecc: f64,
) -> f64 {
    let alpha = inner_semi / outer_semi;
    outer_period / (mass_ratio * alpha * alpha) * (1.0 - outer_ecc * outer_ecc).powf(1.5)
}

pub fn mean_motion(semi_major_au: f64, central_mass: f64) -> f64 {
    let semi_major_m = semi_major_au * AU;
    (G * central_mass / (semi_major_m * semi_major_m * semi_major_m)).sqrt()
}

pub fn resonance_width(semi_major_au: f64, mass_ratio: f64, p: u32, q: u32) -> f64 {
    let coeff = (mass_ratio).powf(2.0 / 7.0);
    let factor = (q as f64 / p as f64).abs();
    semi_major_au * coeff * factor.sqrt() * 0.5
}

pub fn perihelion_precession_rate(semi_major_au: f64, ecc: f64, j2: f64, r_body: f64) -> f64 {
    let semi_major_m = semi_major_au * AU;
    let p = semi_major_m * (1.0 - ecc * ecc);
    3.0 * PI * j2 * r_body * r_body / (p * p)
}

pub fn synodic_period(period_1: f64, period_2: f64) -> f64 {
    let diff = (1.0 / period_1 - 1.0 / period_2).abs();
    if diff < 1.0e-30 {
        f64::INFINITY
    } else {
        1.0 / diff
    }
}

pub fn tisserand_from_elements(semi_major_au: f64, ecc: f64, inc_rad: f64, a_planet: f64) -> f64 {
    let a_ratio = a_planet / semi_major_au;
    a_ratio + 2.0 * ((semi_major_au / a_planet) * (1.0 - ecc * ecc)).sqrt() * inc_rad.cos()
}

pub fn secular_perturbation_timescale(
    semi_major_au: f64,
    perturber_semi_au: f64,
    mass_ratio: f64,
) -> f64 {
    let alpha = semi_major_au / perturber_semi_au;
    let n = mean_motion(semi_major_au, SOLAR_MASS);
    if n.abs() < 1.0e-30 || mass_ratio.abs() < 1.0e-30 {
        return f64::INFINITY;
    }
    1.0 / (n * mass_ratio * alpha * alpha * 0.25)
}
