use sciforge::hub::domain::geology::seismology::{
    gutenberg_richter, moment_magnitude, p_wave_velocity, s_wave_velocity, seismic_moment,
    travel_time,
};

pub struct LobateScarp {
    pub name: &'static str,
    pub length_km: f64,
    pub height_m: f64,
}

impl LobateScarp {
    pub fn estimated_seismic_moment(&self, shear_modulus_pa: f64) -> f64 {
        let fault_depth_m = self.height_m * 5.0;
        let area_m2 = self.length_km * 1000.0 * fault_depth_m;
        let displacement = self.height_m;
        shear_modulus_pa * area_m2 * displacement
    }

    pub fn estimated_magnitude(&self, shear_modulus_pa: f64) -> f64 {
        moment_magnitude(self.estimated_seismic_moment(shear_modulus_pa))
    }
}

pub fn major_scarps() -> Vec<LobateScarp> {
    vec![
        LobateScarp {
            name: "Discovery Rupes",
            length_km: 650.0,
            height_m: 2000.0,
        },
        LobateScarp {
            name: "Beagle Rupes",
            length_km: 600.0,
            height_m: 1000.0,
        },
        LobateScarp {
            name: "Enterprise Rupes",
            length_km: 820.0,
            height_m: 3000.0,
        },
        LobateScarp {
            name: "Victoria Rupes",
            length_km: 400.0,
            height_m: 1500.0,
        },
        LobateScarp {
            name: "Carnegie Rupes",
            length_km: 215.0,
            height_m: 1000.0,
        },
    ]
}

pub struct MercuryQuake {
    pub latitude: f64,
    pub longitude: f64,
    pub depth_km: f64,
    pub seismic_moment_nm: f64,
}

impl MercuryQuake {
    pub fn from_magnitude(lat: f64, lon: f64, depth_km: f64, mw: f64) -> Self {
        Self {
            latitude: lat,
            longitude: lon,
            depth_km,
            seismic_moment_nm: seismic_moment(mw),
        }
    }

    pub fn moment_magnitude(&self) -> f64 {
        moment_magnitude(self.seismic_moment_nm)
    }

    pub fn p_wave_arrival_s(&self, distance_km: f64, vp: f64) -> f64 {
        travel_time(distance_km * 1000.0, vp)
    }

    pub fn s_wave_arrival_s(&self, distance_km: f64, vs: f64) -> f64 {
        travel_time(distance_km * 1000.0, vs)
    }
}

pub fn estimated_global_contraction_km() -> f64 {
    7.0
}

pub fn seismic_activity_expected() -> bool {
    true
}

pub fn max_expected_magnitude() -> f64 {
    5.0
}

pub fn crust_p_wave_velocity() -> f64 {
    let bulk_modulus = 6.0e10;
    let shear_modulus = 3.5e10;
    let density = crate::CRUST_DENSITY;
    p_wave_velocity(bulk_modulus, shear_modulus, density)
}

pub fn crust_s_wave_velocity() -> f64 {
    let shear_modulus = 3.5e10;
    let density = crate::CRUST_DENSITY;
    s_wave_velocity(shear_modulus, density)
}

pub fn annual_frequency(magnitude: f64) -> f64 {
    let a = 4.0;
    let b = 1.0;
    gutenberg_richter(a, b, magnitude)
}
