use super::dpper::dpper;
use super::dspace::dspace;
use super::satrec::SatRec;
use std::f64::consts::PI;
pub fn sgp4_lowlevel(satrec: &mut SatRec, tsince: f64) -> Result<([f64; 3], [f64; 3]), i32> {
let mut coseo1: f64 = 0.0;
let mut cosip: f64;
let cosisq: f64;
let delm: f64;
let delomg: f64;
let mut em: f64;
let mut eo1: f64;
let mut ep: f64;
let mut argpm: f64;
let mut argpp: f64;
let mut sineo1: f64 = 0.0;
let mut sinip: f64;
let mut su: f64;
let t3: f64;
let t4: f64;
let mut tem5: f64;
let mut temp: f64;
let mut tempa: f64;
let mut tempe: f64;
let mut templ: f64;
let mut inclm: f64;
let mut mm: f64;
let mut nm: f64;
let mut nodem: f64;
let mut xincp: f64;
let mut xlm: f64;
let mut mp: f64;
let mut nodep: f64;
let tc: f64;
let mut dndt: f64 = 0.0;
let delmtemp: f64;
let mut ktr: i32;
const TEMP4: f64 = 1.5e-12;
const TWOPI: f64 = 2.0 * std::f64::consts::PI;
const X2O3: f64 = 2.0 / 3.0;
let vkmpersec: f64 = satrec.radiusearthkm * satrec.xke / 60.0;
satrec.t = tsince;
satrec.error = 0;
let xmdf: f64 = satrec.mdot.mul_add(satrec.t, satrec.mo);
let argpdf: f64 = satrec.argpdot.mul_add(satrec.t, satrec.argpo);
let nodedf: f64 = satrec.nodedot.mul_add(satrec.t, satrec.nodeo);
argpm = argpdf;
mm = xmdf;
let t2: f64 = satrec.t * satrec.t;
nodem = satrec.nodecf.mul_add(t2, nodedf);
tempa = satrec.cc1.mul_add(-satrec.t, 1.0);
tempe = satrec.bstar * satrec.cc4 * satrec.t;
templ = satrec.t2cof * t2;
if satrec.isimp != 1 {
delomg = satrec.omgcof * satrec.t;
delmtemp = satrec.eta.mul_add(f64::cos(xmdf), 1.0);
delm = satrec.xmcof * (delmtemp * delmtemp).mul_add(delmtemp, -satrec.delmo);
temp = delomg + delm;
mm = xmdf + temp;
argpm = argpdf - temp;
t3 = t2 * satrec.t;
t4 = t3 * satrec.t;
tempa = satrec.d4.mul_add(-t4, satrec.d3.mul_add(-t3, satrec.d2.mul_add(-t2, tempa)));
tempe += satrec.bstar * satrec.cc5 * (f64::sin(mm) - satrec.sinmao);
templ = t4.mul_add(satrec.t.mul_add(satrec.t5cof, satrec.t4cof), satrec.t3cof.mul_add(t3, templ));
}
nm = satrec.no_unkozai;
em = satrec.ecco;
inclm = satrec.inclo;
if satrec.method == 'd' {
tc = satrec.t;
dspace(
satrec.irez,
satrec.d2201,
satrec.d2211,
satrec.d3210,
satrec.d3222,
satrec.d4410,
satrec.d4422,
satrec.d5220,
satrec.d5232,
satrec.d5421,
satrec.d5433,
satrec.dedt,
satrec.del1,
satrec.del2,
satrec.del3,
satrec.didt,
satrec.dmdt,
satrec.dnodt,
satrec.domdt,
satrec.argpo,
satrec.argpdot,
satrec.t,
tc,
satrec.gsto,
satrec.xfact,
satrec.xlamo,
satrec.no_unkozai,
&mut satrec.atime,
&mut em,
&mut argpm,
&mut inclm,
&mut satrec.xli,
&mut mm,
&mut satrec.xni,
&mut nodem,
&mut dndt,
&mut nm,
);
}
if nm <= 0.0 {
satrec.error = 2;
return Err(satrec.error);
}
let am: f64 = f64::powf(satrec.xke / nm, X2O3) * tempa * tempa;
nm = satrec.xke / f64::powf(am, 1.5);
em -= tempe;
if !(-0.001..1.0).contains(&em) {
satrec.error = 1;
return Err(satrec.error);
}
if em < 1.0e-6 {
em = 1.0e-6;
}
mm += satrec.no_unkozai * templ;
xlm = mm + argpm + nodem;
let _emsq: f64 = em * em;
nodem %= TWOPI; argpm %= TWOPI; xlm %= TWOPI; mm = (xlm - argpm - nodem) % TWOPI;
satrec.am = am;
satrec.em = em;
satrec.im = inclm;
satrec.om = nodem;
satrec.om = argpm;
satrec.mm = mm;
satrec.nm = nm;
let sinim: f64 = f64::sin(inclm);
let cosim: f64 = f64::cos(inclm);
ep = em;
xincp = inclm;
argpp = argpm;
nodep = nodem;
mp = mm;
sinip = sinim;
cosip = cosim;
if satrec.method == 'd' {
dpper(
satrec.e3,
satrec.ee2,
satrec.peo,
satrec.pgho,
satrec.pho,
satrec.pinco,
satrec.plo,
satrec.se2,
satrec.se3,
satrec.sgh2,
satrec.sgh3,
satrec.sgh4,
satrec.sh2,
satrec.sh3,
satrec.si2,
satrec.si3,
satrec.sl2,
satrec.sl3,
satrec.sl4,
satrec.t,
satrec.xgh2,
satrec.xgh3,
satrec.xgh4,
satrec.xh2,
satrec.xh3,
satrec.xi2,
satrec.xi3,
satrec.xl2,
satrec.xl3,
satrec.xl4,
satrec.zmol,
satrec.zmos,
satrec.inclo,
'n',
&mut ep,
&mut xincp,
&mut nodep,
&mut argpp,
&mut mp,
satrec.operationmode,
);
if xincp < 0.0 {
xincp = -xincp;
nodep += PI;
argpp -= PI;
}
if !(0.0..=1.0).contains(&ep) {
satrec.error = 3;
return Err(satrec.error);
}
}
if satrec.method == 'd' {
sinip = f64::sin(xincp);
cosip = f64::cos(xincp);
satrec.aycof = -0.5 * satrec.j3oj2 * sinip;
if f64::abs(cosip + 1.0) > 1.5e-12 {
satrec.xlcof = -0.25 * satrec.j3oj2 * sinip * 5.0f64.mul_add(cosip, 3.0) / (1.0 + cosip);
} else {
satrec.xlcof = -0.25 * satrec.j3oj2 * sinip * 5.0f64.mul_add(cosip, 3.0) / TEMP4;
}
}
let axnl: f64 = ep * f64::cos(argpp);
temp = 1.0 / (am * ep.mul_add(-ep, 1.0));
let aynl: f64 = ep.mul_add(f64::sin(argpp), temp * satrec.aycof);
let xl: f64 = (temp * satrec.xlcof).mul_add(axnl, mp + argpp + nodep);
let u: f64 = (xl - nodep) % TWOPI;
eo1 = u;
tem5 = 9999.9;
ktr = 1;
while (f64::abs(tem5) >= 1.0e-12) && (ktr <= 10) {
sineo1 = f64::sin(eo1);
coseo1 = f64::cos(eo1);
tem5 = sineo1.mul_add(-aynl, coseo1.mul_add(-axnl, 1.0));
tem5 = (axnl.mul_add(sineo1, aynl.mul_add(-coseo1, u)) - eo1) / tem5;
if f64::abs(tem5) >= 0.95 {
if tem5 > 0.0 {
tem5 = 0.95;
} else {
tem5 = -0.95;
}
}
eo1 += tem5;
ktr += 1;
}
let ecose: f64 = axnl.mul_add(coseo1, aynl * sineo1);
let esine: f64 = axnl.mul_add(sineo1, -(aynl * coseo1));
let el2: f64 = axnl.mul_add(axnl, aynl * aynl);
let pl: f64 = am * (1.0 - el2);
if pl < 0.0 {
satrec.error = 4;
return Err(satrec.error);
}
let rl: f64 = am * (1.0 - ecose);
let rdotl: f64 = f64::sqrt(am) * esine / rl;
let rvdotl: f64 = f64::sqrt(pl) / rl;
let betal: f64 = f64::sqrt(1.0 - el2);
temp = esine / (1.0 + betal);
let sinu: f64 = am / rl * axnl.mul_add(-temp, sineo1 - aynl);
let cosu: f64 = am / rl * aynl.mul_add(temp, coseo1 - axnl);
su = f64::atan2(sinu, cosu);
let sin2u: f64 = (cosu + cosu) * sinu;
let cos2u: f64 = (2.0 * sinu).mul_add(-sinu, 1.0);
temp = 1.0 / pl;
let temp1: f64 = 0.5 * satrec.j2 * temp;
let temp2: f64 = temp1 * temp;
if satrec.method == 'd' {
cosisq = cosip * cosip;
satrec.con41 = 3.0f64.mul_add(cosisq, -1.0);
satrec.x1mth2 = 1.0 - cosisq;
satrec.x7thm1 = 7.0f64.mul_add(cosisq, -1.0);
}
let mrt: f64 = rl.mul_add((1.5 * temp2 * betal).mul_add(-satrec.con41, 1.0), 0.5 * temp1 * satrec.x1mth2 * cos2u);
su -= 0.25 * temp2 * satrec.x7thm1 * sin2u;
let xnode: f64 = (1.5 * temp2 * cosip).mul_add(sin2u, nodep);
let xinc: f64 = (1.5 * temp2 * cosip * sinip).mul_add(cos2u, xincp);
let mvt: f64 = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / satrec.xke;
let rvdot: f64 = rvdotl + nm * temp1 * satrec.x1mth2.mul_add(cos2u, 1.5 * satrec.con41) / satrec.xke;
let sinsu: f64 = f64::sin(su);
let cossu: f64 = f64::cos(su);
let snod: f64 = f64::sin(xnode);
let cnod: f64 = f64::cos(xnode);
let sini: f64 = f64::sin(xinc);
let cosi: f64 = f64::cos(xinc);
let xmx: f64 = -snod * cosi;
let xmy: f64 = cnod * cosi;
let ux: f64 = xmx.mul_add(sinsu, cnod * cossu);
let uy: f64 = xmy.mul_add(sinsu, snod * cossu);
let uz: f64 = sini * sinsu;
let vx: f64 = xmx.mul_add(cossu, -(cnod * sinsu));
let vy: f64 = xmy.mul_add(cossu, -(snod * sinsu));
let vz: f64 = sini * cossu;
if mrt < 1.0 {
satrec.error = 6;
return Err(satrec.error);
}
Ok((
[
(mrt * ux) * satrec.radiusearthkm,
(mrt * uy) * satrec.radiusearthkm,
(mrt * uz) * satrec.radiusearthkm,
],
[
mvt.mul_add(ux, rvdot * vx) * vkmpersec,
mvt.mul_add(uy, rvdot * vy) * vkmpersec,
mvt.mul_add(uz, rvdot * vz) * vkmpersec,
],
))
}