package ru.dbotthepony.kstarbound.defs.world

import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import com.google.gson.JsonObject
import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.defs.PerlinNoiseParameters
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.util.random.AbstractPerlinNoise

@JsonFactory
data class CelestialConfig(
	val systemProbability: Double,
	val constellationProbability: Double,
	val constellationLineCountRange: Vector2i,
	val constellationMaxTries: Int,
	val maximumConstellationLineLength: Double,
	val minimumConstellationLineLength: Double,
	val minimumConstellationMagnitude: Double,
	val minimumConstellationLineCloseness: Double,

	val systemTypes: ImmutableMap<String, System>,
	val systemTypePerlin: PerlinNoiseParameters,
	val systemTypeBins: ImmutableList<Pair<Double, String>>,

	val planetaryTypes: ImmutableMap<String, Planet>,
	val satelliteTypes: ImmutableMap<String, Satellite>,

	val terrestrialGraphics: ImmutableMap<String, JsonObject>,
	val terrestrialHorizonGraphics: ImmutableMap<String, JsonObject>,
	val asteroidsHorizons: String,
	val floatingDungeonHorizons: ImmutableMap<String, String>,

	val gasGiantGraphics: JsonObject,
) {
	init {
		systemTypeBins.forEach {
			require(it.second.isBlank() || it.second in systemTypes) { "System type is present in systemTypeBins, but not in systemTypes: ${it.second}" }
		}
	}

	@JsonFactory
	data class System(
		var typeName: String = "",
		/**
		 * This was present in original code, but never implemented
		 */
		val constellationCapable: Boolean = true,
		val baseParameters: JsonObject = JsonObject(),
		val variationParameters: ImmutableList<JsonObject> = ImmutableList.of(),
		val orbitRegions: ImmutableList<CelestialOrbitRegion> = ImmutableList.of(),
	)

	@JsonFactory
	data class Planet(
		var typeName: String = "",
		val satelliteProbability: Double = 0.0,
		val maxSatelliteCount: Int? = null,
		val baseParameters: JsonObject = JsonObject(),
		val variationParameters: ImmutableList<JsonObject> = ImmutableList.of(),
		val orbitParameters: JsonObject = JsonObject(),
	)

	@JsonFactory
	data class Satellite(
		var typeName: String = "",
		val baseParameters: JsonObject = JsonObject(),
		val variationParameters: ImmutableList<JsonObject> = ImmutableList.of(),
		val orbitParameters: ImmutableMap<String, ImmutableList<JsonObject>> = ImmutableMap.of(),
	)

	init {
		planetaryTypes.entries.forEach {
			it.value.typeName = it.key
		}

		systemTypes.entries.forEach {
			it.value.typeName = it.key
		}

		satelliteTypes.entries.forEach {
			it.value.typeName = it.key
		}
	}
}