package ru.dbotthepony.kstarbound.defs.item

import com.google.common.collect.ImmutableList
import com.google.common.collect.ImmutableSet
import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.annotations.JsonAdapter
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import ru.dbotthepony.kommons.util.Either
import ru.dbotthepony.kstarbound.Registry
import ru.dbotthepony.kstarbound.defs.`object`.ObjectDefinition
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.json.getAdapter
import java.util.stream.Stream
import kotlin.properties.Delegates

@JsonAdapter(TreasureChestDefinition.Adapter::class)
data class TreasureChestDefinition(
	val variants: ImmutableList<Variant>,
) {
	var name: String by Delegates.notNull()

	@JsonFactory
	data class Variant(
		val containers: ImmutableSet<Registry.Ref<ObjectDefinition>>,
		val treasurePool: Either<ImmutableSet<Registry.Ref<TreasurePoolDefinition>>, Registry.Ref<TreasurePoolDefinition>>,
		val minimumLevel: Double = 0.0
	) {
		val validContainers: ImmutableSet<Registry.Entry<ObjectDefinition>> by lazy {
			containers.stream().filter { it.isPresent }.map { it.entry!! }.collect(ImmutableSet.toImmutableSet())
		}

		val validTreasurePools: ImmutableSet<Registry.Entry<TreasurePoolDefinition>> by lazy {
			treasurePool.map({ it.stream() }, { Stream.of(it) }).filter { it.isPresent }.map { it.entry!! }.collect(ImmutableSet.toImmutableSet())
		}
	}

	class Adapter(gson: Gson) : TypeAdapter<TreasureChestDefinition>() {
		private val variants = gson.getAdapter<ImmutableList<Variant>>()

		override fun write(out: JsonWriter, value: TreasureChestDefinition) {
			variants.write(out, value.variants)
		}

		override fun read(`in`: JsonReader): TreasureChestDefinition {
			return TreasureChestDefinition(variants.read(`in`))
		}
	}
}
