package ru.dbotthepony.kstarbound import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.TypeAdapter import com.google.gson.stream.JsonReader import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap import kotlinx.coroutines.future.asCompletableFuture import kotlinx.coroutines.future.await import kotlinx.coroutines.launch import ru.dbotthepony.kstarbound.json.FastJsonTreeReader import ru.dbotthepony.kstarbound.json.VersionedJson import java.util.concurrent.Future object VersionRegistry { private val versions = Object2IntOpenHashMap() fun currentVersion(name: String): Int { return versions.getInt(name) } fun make(name: String, contents: JsonElement): VersionedJson { return VersionedJson(name, currentVersion(name), contents) } fun migrate(read: VersionedJson, identifier: String = read.id): JsonElement { if (read.version != currentVersion(identifier)) { throw IllegalStateException("NYI: Migrating $identifier from ${read.version} to ${currentVersion(identifier)}") } return read.content } fun load(name: String, reader: JsonReader, adapter: TypeAdapter): T { val read = this.adapter.read(reader) ?: throw NullPointerException("Expected versioned json $name, but found null") return adapter.fromJsonTree(migrate(read, name)) } fun load(name: String, reader: JsonElement, adapter: TypeAdapter): T { val read = this.adapter.read(FastJsonTreeReader(reader)) ?: throw NullPointerException("Expected versioned json $name, but found null") return adapter.fromJsonTree(migrate(read, name)) } fun load(name: String, reader: JsonReader): JsonElement { val read = this.adapter.read(reader) ?: throw NullPointerException("Expected versioned json $name, but found null") return migrate(read, name) } fun load(name: String, reader: JsonElement): JsonElement { val read = this.adapter.read(FastJsonTreeReader(reader)) ?: throw NullPointerException("Expected versioned json $name, but found null") return migrate(read, name) } fun load(reader: JsonElement): JsonElement { return migrate(VersionedJson.fromJson(reader)) } private val adapter by lazy { Starbound.gson.getAdapter(VersionedJson::class.java) } fun load(): Future<*> { return Starbound.GLOBAL_SCOPE.launch { val json = Starbound.loadJsonAsset("/versioning.config").await() ?: throw NoSuchElementException("Unable to load /versioning.config! Expect HUGE problems!") json as JsonObject for ((k, v) in json.entrySet()) { versions[k] = v.asInt } }.asCompletableFuture() } }