use crate::AXIAL_TILT_RAD;
use crate::ECCENTRICITY;
use crate::SEMI_MAJOR_AXIS_M;

pub const AXIAL_TILT_DEG: f64 = 0.034;

pub struct MercurySeason {
    pub true_anomaly_rad: f64,
    pub heliocentric_distance_m: f64,
    pub solar_flux_w_m2: f64,
}

impl MercurySeason {
    pub fn at_anomaly(true_anomaly_rad: f64) -> Self {
        let r = SEMI_MAJOR_AXIS_M * (1.0 - ECCENTRICITY * ECCENTRICITY)
            / (1.0 + ECCENTRICITY * true_anomaly_rad.cos());

        let solar_luminosity: f64 = 3.828e26;
        let flux = solar_luminosity / (4.0 * std::f64::consts::PI * r * r);

        Self {
            true_anomaly_rad,
            heliocentric_distance_m: r,
            solar_flux_w_m2: flux,
        }
    }

    pub fn perihelion() -> Self {
        Self::at_anomaly(0.0)
    }

    pub fn aphelion() -> Self {
        Self::at_anomaly(std::f64::consts::PI)
    }

    pub fn flux_ratio(&self) -> f64 {
        let mean_r = SEMI_MAJOR_AXIS_M;
        (mean_r * mean_r) / (self.heliocentric_distance_m * self.heliocentric_distance_m)
    }

    pub fn perihelion_to_aphelion_flux_ratio() -> f64 {
        let rp = SEMI_MAJOR_AXIS_M * (1.0 - ECCENTRICITY);
        let ra = SEMI_MAJOR_AXIS_M * (1.0 + ECCENTRICITY);
        (ra * ra) / (rp * rp)
    }
}

pub fn solar_declination_rad(true_anomaly_rad: f64) -> f64 {
    (AXIAL_TILT_RAD * true_anomaly_rad.sin()).asin()
}

pub fn is_hot_pole(lon_deg: f64) -> bool {
    let norm = ((lon_deg % 360.0) + 360.0) % 360.0;
    norm < 15.0 || (norm - 180.0).abs() < 15.0
}
