package moe.nea.firmament.util.data import java.util.UUID import java.util.concurrent.CompletableFuture import kotlinx.serialization.KSerializer import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.buildJsonObject import moe.nea.firmament.Firmament import moe.nea.firmament.gui.config.storage.ConfigStorageClass import moe.nea.firmament.gui.config.storage.FirmamentConfigLoader import moe.nea.firmament.util.SBData sealed class IDataHolder { fun markDirty(future: CompletableFuture? = null) { FirmamentConfigLoader.markDirty(this, future) } init { require(this.javaClass.getAnnotation(Config::class.java) != null) } abstract fun keys(): Collection abstract fun saveTo(key: T): JsonObject abstract fun loadFrom(key: T, jsonObject: JsonObject) abstract fun explicitDefaultLoad() abstract fun clear() abstract val storageClass: ConfigStorageClass } open class ProfileKeyedConfig( val prefix: String, val serializer: KSerializer, val default: () -> T & Any, ) : IDataHolder() { override val storageClass: ConfigStorageClass get() = ConfigStorageClass.PROFILE private var _data: MutableMap? = null val data: T & Any get() { val map = _data ?: error("Config $this not loaded — forgot to register?") map[SBData.profileIdOrNil]?.let { return it } val newValue = default() map[SBData.profileIdOrNil] = newValue return newValue } override fun keys(): Collection { return _data!!.keys } override fun saveTo(key: UUID): JsonObject { val d = _data!! return buildJsonObject { put(prefix, Firmament.json.encodeToJsonElement(serializer, d[key] ?: return@buildJsonObject)) } } override fun loadFrom(key: UUID, jsonObject: JsonObject) { var map = _data if (map == null) { map = mutableMapOf() _data = map } map[key] = jsonObject[prefix] ?.let { Firmament.json.decodeFromJsonElement(serializer, it) } ?: default() } override fun explicitDefaultLoad() { _data = mutableMapOf() } override fun clear() { _data = null } } abstract class GenericConfig( val prefix: String, val serializer: KSerializer, val default: () -> T, ) : IDataHolder() { private var _data: T? = null val data get() = _data ?: error("Config $this not loaded — forgot to register?") override fun keys(): Collection { return listOf(Unit) } override fun explicitDefaultLoad() { _data = default() } open fun onLoad() { } override fun saveTo(key: Unit): JsonObject { return buildJsonObject { put(prefix, Firmament.json.encodeToJsonElement(serializer, data)) } } override fun loadFrom(key: Unit, jsonObject: JsonObject) { _data = jsonObject[prefix]?.let { Firmament.json.decodeFromJsonElement(serializer, it) } ?: default() onLoad() } override fun clear() { _data = null } }