package ballistics.flightLine

import ballistics.types.FleghtLineSector
import ballistics.types.FlightLine
import kotlin.math.PI
import kotlin.math.truncate

internal class EarthCovering {
    var coverings = mutableMapOf<Int, MutableList<FleghtLineSector>>()

    fun getBInd(b: Double): Int {
        var b2: Double = b * 180.0 / PI
        b2 = 90.0 - b2
        var k: Int = truncate(b2 / 2.0).toInt()
        if (k > 89) k = 89
        return k
    }

    fun getLInd(l2: Double): Int {
        var l: Double = l2 * 180.0 / PI
        if (l < 0) l += 360.0
        var k: Int = truncate(l / 2.0).toInt()
        if (k > 179) k = 179
        return k
    }

    fun getInd(
        b: Double,
        l: Double,
    ): Int {
        return getBInd(b) * 180 + getLInd(l)
    }

    fun addCoverings(
        frst: FlightLine,
        sec: FlightLine,
    ) {
        val bmax = getBInd(minOf(frst.leftOuterSwath.lat, frst.rightOuterSwath.lat, sec.leftOuterSwath.lat, sec.rightOuterSwath.lat))
        val bmin = getBInd(maxOf(frst.leftOuterSwath.lat, frst.rightOuterSwath.lat, sec.leftOuterSwath.lat, sec.rightOuterSwath.lat))
        var lmin = getLInd(minOf(frst.leftOuterSwath.long, frst.rightOuterSwath.long, sec.leftOuterSwath.long, sec.rightOuterSwath.long))
        var lmax = getLInd(maxOf(frst.leftOuterSwath.long, frst.rightOuterSwath.long, sec.leftOuterSwath.long, sec.rightOuterSwath.long))

        if (lmax - lmin > 90) {
            lmax = checkLmax(frst, sec)
            lmin = checkLmin(frst, sec)
            val l = lmin
            lmin = lmax
            lmax = l + 179
        }

        for (bi in bmin..bmax) {
            for (li in lmin..lmax) {
                val ll = if (li >= 180) li - 180 else li
                val ind = bi * 180 + ll
                if (coverings.containsKey(ind)) {
                    coverings[ind]!!.add(FleghtLineSector(frst.t, sec.t))
                } else {
                    coverings.put(ind, mutableListOf(FleghtLineSector(frst.t, sec.t)))
                }
            }
        }
    }


    fun checkLmax(frst: FlightLine,  sec: FlightLine) : Int{
        var buf = 2 * PI
        if (frst.leftOuterSwath.long > PI / 2) {
            buf = frst.leftOuterSwath.long
        }
        if (frst.rightOuterSwath.long > PI / 2 && frst.rightOuterSwath.long < buf) {
            buf = frst.rightOuterSwath.long
        }
        if (sec.rightOuterSwath.long > PI / 2 && sec.rightOuterSwath.long < buf) {
            buf = sec.rightOuterSwath.long
        }
        if (sec.leftOuterSwath.long > PI / 2 && sec.leftOuterSwath.long < buf) {
            buf = sec.leftOuterSwath.long
        }
        return getLInd(buf)
    }

    fun checkLmin(frst: FlightLine,  sec: FlightLine) : Int{
        var buf = 0.0
        if (frst.leftOuterSwath.long < PI / 2) {
            buf = frst.leftOuterSwath.long
        }
        if (frst.rightOuterSwath.long < PI / 2 && frst.rightOuterSwath.long > buf) {
            buf = frst.rightOuterSwath.long
        }
        if (sec.rightOuterSwath.long < PI / 2 && sec.rightOuterSwath.long > buf) {
            buf = sec.rightOuterSwath.long
        }
        if (sec.leftOuterSwath.long < PI / 2 && sec.leftOuterSwath.long > buf) {
            buf = sec.leftOuterSwath.long
        }
        return getLInd(buf)
    }

    fun getCoverings(
        b: Double,
        l: Double,
    ): Iterable<FleghtLineSector> {
        return coverings.getOrDefault(getInd(b, l), listOf<FleghtLineSector>())
    }
}
