use sciforge::hub::prelude::biology::ecology::{
    shannon_diversity, simpson_diversity, species_area,
};

pub struct Ecosystem {
    pub name: &'static str,
    pub areakm2: f64,
    pub speciescounts: Vec<u64>,
    pub netprimaryproductivitygcm2yr: f64,
    pub meantemperaturek: f64,
    pub energyinputwm2: f64,
}

impl Ecosystem {
    pub fn totalspecies(&self) -> u64 {
        self.speciescounts.len() as u64
    }

    pub fn totalindividuals(&self) -> u64 {
        self.speciescounts.iter().sum()
    }

    pub fn shannonindex(&self) -> f64 {
        let total = self.totalindividuals();
        if total == 0 {
            return 0.0;
        }
        let proportions: Vec<f64> = self
            .speciescounts
            .iter()
            .map(|&c| c as f64 / total as f64)
            .collect();
        shannon_diversity(&proportions)
    }

    pub fn simpsondiversity(&self) -> f64 {
        let total = self.totalindividuals();
        if total == 0 {
            return 0.0;
        }
        let proportions: Vec<f64> = self
            .speciescounts
            .iter()
            .map(|&c| c as f64 / total as f64)
            .collect();
        simpson_diversity(&proportions)
    }

    pub fn expectedspeciesfromarea(&self, z: f64, c: f64) -> f64 {
        species_area(c, z, self.areakm2)
    }

    pub fn totalnppgcyr(&self) -> f64 {
        self.netprimaryproductivitygcm2yr * self.areakm2 * 1e6
    }

    pub fn biomassturnovertimeyr(&self, biomassgcm2: f64) -> f64 {
        if self.netprimaryproductivitygcm2yr.abs() < 1e-30 {
            return f64::INFINITY;
        }
        biomassgcm2 / self.netprimaryproductivitygcm2yr
    }
}

pub fn hypotheticalatmosphericbiome() -> Ecosystem {
    Ecosystem {
        name: "Hypothetical Neptune Atmospheric Biome",
        areakm2: 0.0,
        speciescounts: vec![],
        netprimaryproductivitygcm2yr: 0.0,
        meantemperaturek: crate::ONEBARTEMPK,
        energyinputwm2: crate::INTERNALHEATINGWM2,
    }
}
