package org.nstart.dep265.tletools.zeptomoby.core

import org.nstart.dep265.tletools.zeptomoby.core.iau.IAU
import org.nstart.dep265.tletools.zeptomoby.core.iau.IAU76
import org.nstart.dep265.tletools.zeptomoby.core.wgs.WGS
import org.nstart.dep265.tletools.zeptomoby.core.wgs.WGS72
import kotlin.math.atan
import kotlin.math.floor
import kotlin.math.pow
import kotlin.math.sqrt

@Suppress("unused")
object Globals {

    const val pi: Double = Math.PI
    const val twoPi: Double = 2.0 * org.nstart.dep265.tletools.zeptomoby.core.Globals.pi
    const val radsPerDeg = org.nstart.dep265.tletools.zeptomoby.core.Globals.pi / 180.0

    const val gm          = 398601.2   // Earth gravitational constant, km^3/sec^2
    const val geoSyncAlt  = 42241.892  // km
    const val earthDia    = 12800.0    // km
    const val daySidereal = 86164.09   // sec
    const val day24HR     = 86400      // sec

    const val ae          = 1.0
    var iau: IAU = IAU76
    var wgs: WGS = WGS72
        set(value) {
            field = value

            org.nstart.dep265.tletools.zeptomoby.core.Globals.ck2 = org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.j2 * 0.5
            org.nstart.dep265.tletools.zeptomoby.core.Globals.ck4 = -3.0 * org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.j4 / 8.0
            org.nstart.dep265.tletools.zeptomoby.core.Globals.xj3 = org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.j3
            org.nstart.dep265.tletools.zeptomoby.core.Globals.qo = org.nstart.dep265.tletools.zeptomoby.core.Globals.ae + 120.0 / org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer
            org.nstart.dep265.tletools.zeptomoby.core.Globals.s = org.nstart.dep265.tletools.zeptomoby.core.Globals.ae + 78.0  / org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer
            org.nstart.dep265.tletools.zeptomoby.core.Globals.xke = sqrt(3600.0 * org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.ge / (org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer * org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer * org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer))
            org.nstart.dep265.tletools.zeptomoby.core.Globals.qoms2t = (org.nstart.dep265.tletools.zeptomoby.core.Globals.qo - org.nstart.dep265.tletools.zeptomoby.core.Globals.s).pow(4)
        }

    var ck2              = org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.j2 * 0.5
    var ck4              = -3.0 * org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.j4 * 0.125
    var xj3              = org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.j3
    var qo               = org.nstart.dep265.tletools.zeptomoby.core.Globals.ae + 120.0 / org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer
    var s                = org.nstart.dep265.tletools.zeptomoby.core.Globals.ae + 78.0  / org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer
    const val hrPerDay   = 24.0          // Hours per day   (solar)
    const val minPerDay  = 1440.0        // Minutes per day (solar)
    const val secPerDay  = 86400.0       // Seconds per day (solar)
    const val omegaE     = 1.00273790934 // earth rotation per sidereal day
    var xke              = sqrt(3600.0 * org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.ge /           //sqrt(ge) ER^3/min^2
                                        (org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer * org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer * org.nstart.dep265.tletools.zeptomoby.core.Globals.wgs.xkmPer))
    var qoms2t           = (org.nstart.dep265.tletools.zeptomoby.core.Globals.qo - org.nstart.dep265.tletools.zeptomoby.core.Globals.s).pow(4)            //(QO - S)^4 ER^4

    fun sqr(x: Double) = x*x

    fun fmod(numerator: Double, denominator: Double): Double {
        val tquot = floor(numerator / denominator).toLong()
        return numerator - tquot * denominator
    }

    fun fmod2p(arg: Double): Double {
        val modU = org.nstart.dep265.tletools.zeptomoby.core.Globals.fmod(
            arg,
            org.nstart.dep265.tletools.zeptomoby.core.Globals.twoPi
        )
        return if (modU < 0.0) modU + org.nstart.dep265.tletools.zeptomoby.core.Globals.twoPi else modU
    }

    fun acTan(sinX: Double, cosX: Double): Double =
        if (cosX == 0.0) (if (sinX > 0.0) org.nstart.dep265.tletools.zeptomoby.core.Globals.pi * 0.5 else 1.5 * org.nstart.dep265.tletools.zeptomoby.core.Globals.pi)
        else (if (cosX > 0.0) atan(sinX/cosX) else org.nstart.dep265.tletools.zeptomoby.core.Globals.pi + atan(sinX/cosX))

    fun rad2deg(r: Double): Double = Math.toDegrees(r)
    fun deg2rad(d: Double): Double = Math.toRadians(d)
}