use sciforge::hub::domain::geology::tectonics::{
    airy_root, euler_pole_velocity, flexural_rigidity, geothermal_gradient, heat_flow,
    isostatic_equilibrium,
};

pub const ICEMANTLEDENSITY: f64 = 1600.0;
pub const ROCKYCOREDENSITY: f64 = 5000.0;
pub const INTERIORVISCOSITY: f64 = 1e18;
pub const ICESHELLTHICKNESS: f64 = 7000000.0;

pub struct InteriorConvectionCell {
    pub name: &'static str,
    pub eulerpolelatdeg: f64,
    pub eulerpolelondeg: f64,
    pub angularvelocitydegmyr: f64,
    pub areakm2: f64,
}

impl InteriorConvectionCell {
    pub fn velocityatpoint(&self, latdeg: f64, londeg: f64) -> f64 {
        let lat1 = self.eulerpolelatdeg.to_radians();
        let lon1 = self.eulerpolelondeg.to_radians();
        let lat2 = latdeg.to_radians();
        let lon2 = londeg.to_radians();
        let angulardistance =
            (lat1.sin() * lat2.sin() + lat1.cos() * lat2.cos() * (lon2 - lon1).cos()).acos();
        euler_pole_velocity(
            self.angularvelocitydegmyr.to_radians() / crate::SECONDSPERYEAR / 1e6,
            crate::NEPTUNEMEANRADIUS,
            angulardistance,
        )
    }

    pub fn velocitycmperyear(&self, latdeg: f64, londeg: f64) -> f64 {
        self.velocityatpoint(latdeg, londeg) * crate::SECONDSPERYEAR * 100.0
    }
}

pub fn equatorialcell() -> InteriorConvectionCell {
    InteriorConvectionCell {
        name: "Equatorial Convection",
        eulerpolelatdeg: 0.0,
        eulerpolelondeg: 0.0,
        angularvelocitydegmyr: 0.001,
        areakm2: 1e9,
    }
}

pub fn polarcell() -> InteriorConvectionCell {
    InteriorConvectionCell {
        name: "Polar Convection",
        eulerpolelatdeg: 85.0,
        eulerpolelondeg: 0.0,
        angularvelocitydegmyr: 0.0005,
        areakm2: 5e8,
    }
}

pub fn iceshellrootdepth(iceheightm: f64) -> f64 {
    airy_root(iceheightm, ICEMANTLEDENSITY, ROCKYCOREDENSITY)
}

pub fn iceshellflexuralrigidity(thicknessm: f64, youngsmodulus: f64, poissonsratio: f64) -> f64 {
    flexural_rigidity(youngsmodulus, thicknessm, poissonsratio)
}

pub fn surfaceheatflow(conductivity: f64, tempgradient: f64) -> f64 {
    heat_flow(conductivity, tempgradient)
}

pub fn temperatureatdepth(surfacetemp: f64, depthm: f64, gradientkperm: f64) -> f64 {
    surfacetemp + geothermal_gradient(surfacetemp, depthm, gradientkperm)
}

pub fn isostaticbalance(icethickness: f64) -> f64 {
    isostatic_equilibrium(ICEMANTLEDENSITY, icethickness, ROCKYCOREDENSITY)
}
