package ballistics.flightLine

import ballistics.orbitalPoints.AbstractOrbPointsCalculator
import ballistics.types.BallisticsError
import ballistics.types.FlightLine
import ballistics.types.OrbitalPoint
import ballistics.types.Orientation
import ballistics.types.WorkCSType
import ballistics.utils.earth.getEarth


internal class FlightLineCalculator(
    var opc: AbstractOrbPointsCalculator,
    var rollMin: Double,
    var rollMax: Double,
    var wcs: WorkCSType = WorkCSType.WCSOrbit,
) {
    var step = 60.0
    val eart = getEarth(opc.earthType)
    var flightLine = mutableListOf<FlightLine>()
    var pc = PointOnEarthCalculator(opc.earthType, wcs)
    var earthCoveringCalculator: EarthCovering = EarthCovering()
    var needToCalcEarthCovering: Boolean = true


    fun calculate(
        tn: Double,
        tk: Double,
    ): BallisticsError {
        flightLine.clear()
        earthCoveringCalculator.coverings.clear()

        var t = tn

        val stepper = opc.getStepper()
        var point: OrbitalPoint?

        point = stepper.calculate(t)
        if (point == null)
            return BallisticsError.STEPPER_ERROR

        flightLine.add(calcFl(point))
        t += step

        while (t <= tk) {
            point = stepper.calculate(t)
            if (point == null) {
                println("Ошибка выхода на заданное время в середине расчета")
                return BallisticsError.STEPPER_ERROR
            }
            val fl = calcFl(point)

            if (needToCalcEarthCovering) {
                earthCoveringCalculator.addCoverings(flightLine.last(), fl)
            }

            flightLine.add(fl)
            t += step
        }

        return BallisticsError.OK
    }

    private fun calcFl(point: OrbitalPoint): FlightLine {
        return FlightLine(
            point.t,
            point.vit,
            if (point.v.z >= 0) 0 else 1,
            pc.pointOnEarth(point, Orientation(0.0, -rollMax, 0.0))!!,
            pc.pointOnEarth(point, Orientation(0.0, -rollMin, 0.0))!!,
            pc.pointOnEarth(point, Orientation(0.0, 0.0, 0.0))!!,
            pc.pointOnEarth(point, Orientation(0.0, rollMin, 0.0))!!,
            pc.pointOnEarth(point, Orientation(0.0, rollMax, 0.0))!!,
        )
    }

    fun clear(){
        flightLine.clear()
        earthCoveringCalculator.coverings.clear()
        opc.clear()
    }
}
