package ru.dbotthepony.kstarbound.defs.quest

import com.google.common.collect.ImmutableMap
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.TypeAdapter
import com.google.gson.annotations.JsonAdapter
import ru.dbotthepony.kommons.io.readMap
import ru.dbotthepony.kommons.io.writeBinaryString
import ru.dbotthepony.kommons.io.writeMap
import ru.dbotthepony.kstarbound.io.readInternedString
import ru.dbotthepony.kstarbound.json.VersionedAdapter
import ru.dbotthepony.kstarbound.json.builder.FactoryAdapter
import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import ru.dbotthepony.kstarbound.network.syncher.legacyCodec
import ru.dbotthepony.kstarbound.network.syncher.nativeCodec
import java.io.DataInputStream
import java.io.DataOutputStream

@JsonAdapter(QuestDescriptor.Adapter::class)
data class QuestDescriptor(
	val questId: String,
	val templateId: String = questId,
	val parameters: ImmutableMap<String, QuestParameter> = ImmutableMap.of(),
	val seed: Long = makeSeed(),
) {
	constructor(stream: DataInputStream, isLegacy: Boolean) : this(
		stream.readInternedString(),
		stream.readInternedString(),
		ImmutableMap.copyOf(stream.readMap({ readInternedString() }, { QuestParameter(this, isLegacy) })),
		stream.readLong()
	)

	fun write(stream: DataOutputStream, isLegacy: Boolean) {
		stream.writeBinaryString(questId)
		stream.writeBinaryString(templateId)
		stream.writeMap(parameters, { writeBinaryString(it) }, { it.write(this, isLegacy) })
		stream.writeLong(seed)
	}

	class Adapter(gson: Gson) : VersionedAdapter<QuestDescriptor>("QuestDescriptor", FactoryAdapter.createFor(QuestDescriptor::class, gson))

	companion object {
		val CODEC = nativeCodec(::QuestDescriptor, QuestDescriptor::write)
		val LEGACY_CODEC = legacyCodec(::QuestDescriptor, QuestDescriptor::write)

		fun makeSeed(): Long {
			return System.nanoTime().rotateLeft(27).xor(System.currentTimeMillis())
		}
	}
}
