package space.nstart.pcp.complan.types

import org.locationtech.jts.geom.Geometry
import org.locationtech.jts.geom.LineString
import org.locationtech.jts.geom.Polygon
import org.locationtech.jts.io.WKTReader
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SquareViewParamDTO


data class GeoJsonItem(
    val geometry: Geometry,
    val properties: Map<String, Any>,
){
    companion object {
//        /**
//         * Создание слоя интервалов с атрибутивной информацией
//         * @param
//         * @return
//         */
//        fun createIntervalsLay(ka: KaPass): List<GeoJsonItem> {
//            val rez = mutableListOf<GeoJsonItem>()
//            for (view in ka.views) {
//                var unionGeom: Geometry? = view.matPlan.interval.geometry//.contour[0].geometry
//
//                if (unionGeom == null) continue
//                val resItem = GeoJsonItem(
//                    geometry = unionGeom,//, //.geometryToDeg(),
//                    properties = mapOf(
//                        "Аппарат" to "${ka.ka.kaId}",
//                        "Время нач." to view.matPlan.tMinLDT.toString(),//.toDateString(),
//                        "Время кон." to view.matPlan.tMaxLDT.toString(),//.toDateString(),
//                        "Виток" to view.matPlan.vit,
//                        "Регион" to "${view.matPlan.interval.obj.reqRegionId}",
//                    )
//                )
//                rez.add(resItem)
//            }
//
//            return rez
//        }

        /**
         * Создание слоя интервалов с атрибутивной информацией
         * @return Возвращает заполненный [GeoJsonItem] с геометрией контура и атрибутивной информацией
         */
        fun createIntervalsLay(interval: List<IntervalItemDTO>): List<GeoJsonItem> {
            val rez = mutableListOf<GeoJsonItem>()
            for(interval in interval) {

                if(WKTReader().read(interval.geometry).getGeometryN(0).coordinates.first() != WKTReader().read(interval.geometry).getGeometryN(0).coordinates.last())
                    continue

                val resItem = GeoJsonItem(
                    geometry = WKTReader().read(interval.geometry),
                    properties = mapOf(
//                        "№" to "${interval.num}",
//                        "Region" to "${interval.regionId}",
//                        "Interval" to "${interval.id}",
                        "mpl" to getMplStringForLay(interval.mpl)
//                        "mpl" to interval.mpl.map { "[kaid ${it.noradId}, rev ${it.revolutionBegin}, time ${it.timeBegin}]" },
//                        "mpl" to "${interval.mpl}",
                    )
                )
                rez.add(resItem)
            }
            return rez
        }

        /**
         * Формирование атрибутивной информации по матрице планирования
         * @return Возвращает строку с перечнем прохождений КА в минималистическом формате
         * КА[[виток время][..]..]
         */
        fun getMplStringForLay(mpl : List<SquareViewParamDTO>) : String {
            val kaList = mutableSetOf<Long>()//.addAll(mpl.map { it.noradId })

            mpl.sortedBy { it.timeBegin }

            mpl.forEach {
                kaList.add(it.noradId)
            }

            val res = StringBuilder()

            val kaListTmp = kaList.sortedBy { it }

            kaListTmp.forEach { kaId ->
                val str = mpl.filter { it.noradId == kaId }.sortedBy { it.timeBegin }.map { "[rev ${it.revolutionBegin}, time ${it.timeBegin}, gamma ${(it.gammaMin + it.gammaMax)/2}, gammaMin ${it.gammaMin}, gammaMax ${it.gammaMax}]" }

                res.append("noradId:$kaId")
                res.append("[")
                str.forEach { res.append(it) }
                res.append("]")
            }

            return res.toString()
        }

        /**
         * Создание слоя маршрутов с атрибутивной информацией
         * @return Возвращает заполненный [GeoJsonItem] с геометрией контура и атрибутивной информацией
         */
        fun createSurveyLay(surveys: List<SurveyContour>): List<GeoJsonItem> {
            val rez = mutableListOf<GeoJsonItem>()
            for(survey in surveys) {

                val geometry = WKTReader().read(survey.geometry)

                if (geometry !is Polygon) { continue }

                if(geometry.getGeometryN(0).coordinates.first() != geometry.getGeometryN(0).coordinates.last())
                    continue

                val resItem = GeoJsonItem(
                    geometry = geometry,
                    properties = mapOf(
                        "noradId" to survey.mpl.noradId,
                        "rev" to survey.rev,
                        "gamma" to survey.gamma,
                        "time" to survey.time.toString(),
                        "duration" to survey.duration,
//                        "mpl" to survey.mpl.toString(),
                    )
                )
                rez.add(resItem)
            }
            return rez
        }

        /**
         * Создание слоя с атрибутивной информацией
         * @return Возвращает заполненный [GeoJsonItem] с геометрией контура и атрибутивной информацией
         */
        fun createAnyLay(pols: List<Polygon>): MutableList<GeoJsonItem> {
            val rez = mutableListOf<GeoJsonItem>()
            for (pol in pols) {
                val resItem = GeoJsonItem(
                    geometry = pol,//,
                    properties = mapOf()
                )
                rez.add(resItem)
            }
            return rez
        }

        /**
         * Создание слоя с атрибутивной информацией
         * @return Возвращает заполненный [GeoJsonItem] с геометрией контура и атрибутивной информацией
         */
        fun createRequestLay(requests: List<RequestItemDTO>): List<GeoJsonItem> {
            val rez = mutableListOf<GeoJsonItem>()
            for (item in requests) {
                val resItem = GeoJsonItem(
                    geometry = WKTReader().read(item.geometry),//,
                    properties = mapOf(
                        "UUID" to "${item.id}",
                        "Name" to "${item.name}",
                        "Interval_begin" to "${item.intervalBegin}",
                        "Interval_end" to "${item.intervalEnd}",
                        "Importance" to "${item.importance}",
                        "Priority" to "${item.priority}",
                        "Resulution" to "${item.resolution}",
                    )
                )
                rez.add(resItem)
            }
            return rez
        }
        /**
         * Создание слоя с атрибутивной информацией
         * @return Возвращает заполненный [GeoJsonItem] с геометрией контура и атрибутивной информацией
         */
        fun createAplCatalogLay(aplCatalog: List<AplObjItem>): List<GeoJsonItem> {
            val rez = mutableListOf<GeoJsonItem>()
            for (item in aplCatalog) {
                val resItem = GeoJsonItem(
                    geometry = item.geometry,
                    properties = mapOf(
                        "UUID" to "${item.id}",
                        "Name" to "${item.name}",
//                        "Interval_begin" to "${item.intervalBegin}",
//                        "Interval_end" to "${item.intervalEnd}",
//                        "Importance" to "${item.importance}",
//                        "Priority" to "${item.priority}",
//                        "Resulution" to "${item.resolution}",
                    )
                )
                rez.add(resItem)
            }
            return rez
        }

        /**
         * Создание слой для отображения из LineString
         * @return Возвращает заполненный [GeoJsonItem] с геометрией контура и атрибутивной информацией
         */
        fun createLineStringLay(lines: List<LineString>): MutableList<GeoJsonItem> {
            val rez = mutableListOf<GeoJsonItem>()
            for (item in lines) {
                val resItem = GeoJsonItem(
                    geometry = item,//,
                    properties = mapOf()
                )
                rez.add(resItem)
            }
            return rez
        }

    }
}
