package ru.dbotthepony.kstarbound.defs.world

import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableMap
import com.google.common.collect.ImmutableSet
import ru.dbotthepony.kstarbound.Globals
import ru.dbotthepony.kstarbound.Registries
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.defs.AssetReference
import ru.dbotthepony.kstarbound.defs.ThingDescription
import ru.dbotthepony.kstarbound.defs.tile.TileDamageConfig
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.json.builder.JsonFlat

@JsonFactory
class BushVariant(
	val bushName: String,
	val modName: String,

	// because shapes don't contain absolute paths.
	// god damn it
	val directory: String,
	val shapes: ImmutableList<Shape>,

	val baseHueShift: Double,
	val modHueShift: Double,

	val descriptions: ImmutableMap<String, String> = ImmutableMap.of(),
	val ceiling: Boolean,

	val ephemeral: Boolean,
	val tileDamageParameters: TileDamageConfig,
) {
	@JsonFactory(asList = true)
	data class Shape(val image: String, val mods: ImmutableList<String>)

	@JsonFactory
	data class DataShape(val base: String, val mods: ImmutableMap<String, ImmutableList<String>> = ImmutableMap.of())

	@JsonFactory
	data class Data(
		val name: String,
		@JsonFlat
		val descriptions: ThingDescription,
		val shapes: ImmutableList<DataShape>,
		val mods: ImmutableSet<String> = ImmutableSet.of(),
		val ceiling: Boolean = false,
		val ephemeral: Boolean = true,
		val damageTable: AssetReference<TileDamageConfig>? = null,
		val health: Double = 1.0,
	)

	companion object {
		fun create(bushName: String, baseHueShift: Double, modName: String, modHueShift: Double): BushVariant {
			return create(Registries.bushVariants.getOrThrow(bushName), baseHueShift, modName, modHueShift)
		}

		fun create(data: Registry.Entry<Data>, baseHueShift: Double, modName: String, modHueShift: Double): BushVariant {
			return BushVariant(
				bushName = data.key,
				baseHueShift = baseHueShift,
				directory = data.file?.computeDirectory() ?: "/",
				modHueShift = modHueShift,
				ceiling = data.value.ceiling,
				descriptions = data.value.descriptions.fixDescription("${data.key} with $modName").toMap(),
				ephemeral = data.value.ephemeral,
				tileDamageParameters = (data.value.damageTable?.value ?: Globals.bushDamage).copy(totalHealth = data.value.health),
				modName = modName,
				shapes = data.value.shapes.stream().map { Shape(it.base, it.mods[modName] ?: ImmutableList.of()) }.collect(ImmutableList.toImmutableList())
			)
		}
	}
}
