use crate::satellites::triton::{NEPTUNETRITONDISTANCE, TRITONMASS};
use sciforge::hub::domain::astronomy::celestial::gravitational_force;
use sciforge::hub::domain::common::constants::{AU, G, SOLAR_MASS};

pub struct TidalForce {
    pub bodymass: f64,
    pub bodydistance: f64,
}

impl TidalForce {
    pub fn fromtriton() -> Self {
        Self {
            bodymass: TRITONMASS,
            bodydistance: NEPTUNETRITONDISTANCE,
        }
    }

    pub fn fromsun() -> Self {
        Self {
            bodymass: SOLAR_MASS,
            bodydistance: 30.07 * AU,
        }
    }

    pub fn tidalacceleration(&self) -> f64 {
        2.0 * G * self.bodymass * crate::NEPTUNEEQUATORIALRADIUS / self.bodydistance.powi(3)
    }

    pub fn tidalpotential(&self, theta: f64) -> f64 {
        let r = crate::NEPTUNEEQUATORIALRADIUS;
        let d = self.bodydistance;
        let m = self.bodymass;
        let base = -G * m * r * r / (d * d * d) * (1.5 * theta.cos().powi(2) - 0.5);
        (1.0 + crate::K2LOVE) * base
    }

    pub fn tidalbulgeheight(&self) -> f64 {
        let gsurface = *crate::SURFACEGRAVITY;
        crate::H2LOVE * self.tidalacceleration() * crate::NEPTUNEEQUATORIALRADIUS / gsurface
    }

    pub fn gravitationalattraction(&self) -> f64 {
        gravitational_force(crate::NEPTUNEMASS, self.bodymass, self.bodydistance)
    }
}

pub fn springtideamplitude() -> f64 {
    let triton = TidalForce::fromtriton();
    let sun = TidalForce::fromsun();
    triton.tidalbulgeheight() + sun.tidalbulgeheight()
}

pub fn neaptideamplitude() -> f64 {
    let triton = TidalForce::fromtriton();
    let sun = TidalForce::fromsun();
    (triton.tidalbulgeheight() - sun.tidalbulgeheight()).abs()
}

pub fn tritontosolartideratio() -> f64 {
    let triton = TidalForce::fromtriton();
    let sun = TidalForce::fromsun();
    triton.tidalacceleration() / sun.tidalacceleration()
}
