use sciforge::hub::domain::geology::petrology::{
    differentiation_index, liquidus_temperature, mg_number, solidus_depression,
    total_alkali_silica, viscosity_arrhenius,
};

pub struct CryoMagma {
    pub h2owtpercent: f64,
    pub nh3wtpercent: f64,
    pub ch4wtpercent: f64,
    pub sio2wtpercent: f64,
    pub mgowtpercent: f64,
    pub feowtpercent: f64,
    pub temperaturek: f64,
}

impl CryoMagma {
    pub fn waterammonia() -> Self {
        Self {
            h2owtpercent: 70.0,
            nh3wtpercent: 25.0,
            ch4wtpercent: 5.0,
            sio2wtpercent: 0.0,
            mgowtpercent: 0.0,
            feowtpercent: 0.0,
            temperaturek: 200.0,
        }
    }

    pub fn methanerich() -> Self {
        Self {
            h2owtpercent: 40.0,
            nh3wtpercent: 10.0,
            ch4wtpercent: 45.0,
            sio2wtpercent: 0.0,
            mgowtpercent: 0.0,
            feowtpercent: 0.0,
            temperaturek: 150.0,
        }
    }

    pub fn silicatecore() -> Self {
        Self {
            h2owtpercent: 5.0,
            nh3wtpercent: 0.0,
            ch4wtpercent: 0.0,
            sio2wtpercent: 49.0,
            mgowtpercent: 8.0,
            feowtpercent: 10.0,
            temperaturek: 5000.0,
        }
    }

    pub fn mgnumber(&self) -> f64 {
        if self.mgowtpercent.abs() < 1e-30 && self.feowtpercent.abs() < 1e-30 {
            return 0.0;
        }
        mg_number(self.mgowtpercent, self.feowtpercent)
    }

    pub fn totalalkali(&self) -> f64 {
        total_alkali_silica(self.nh3wtpercent, self.sio2wtpercent)
    }

    pub fn liquidustempc(&self) -> f64 {
        liquidus_temperature(self.sio2wtpercent, self.h2owtpercent, 1000.0)
    }

    pub fn viscositypas(&self) -> f64 {
        let a = 1e-3;
        let ea = 5e4;
        viscosity_arrhenius(a, ea, self.temperaturek)
    }

    pub fn solidusdepressionc(&self) -> f64 {
        solidus_depression(self.h2owtpercent, 1000.0, 1.0)
    }

    pub fn differentiationidx(&self) -> f64 {
        differentiation_index(
            self.sio2wtpercent,
            self.nh3wtpercent,
            self.ch4wtpercent,
            0.0,
        )
    }
}

pub fn cryovolcanicexplosivityindex(ejectavolumekm3: f64) -> u8 {
    if ejectavolumekm3 < 1e-6 {
        0
    } else if ejectavolumekm3 < 1e-4 {
        1
    } else if ejectavolumekm3 < 1e-3 {
        2
    } else if ejectavolumekm3 < 1e-2 {
        3
    } else if ejectavolumekm3 < 0.1 {
        4
    } else if ejectavolumekm3 < 1.0 {
        5
    } else if ejectavolumekm3 < 10.0 {
        6
    } else if ejectavolumekm3 < 100.0 {
        7
    } else {
        8
    }
}
