package ru.dbotthepony.kstarbound.defs

import com.google.gson.JsonSyntaxException
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap
import ru.dbotthepony.kommons.gson.consumeNull

class ColorReplacements private constructor(private val mapping: Int2IntOpenHashMap) {
	constructor(mapping: Map<Int, Int>) : this(Int2IntOpenHashMap(mapping))

	fun replace(color: Int): Int {
		return mapping.getOrDefault(color, color)
	}

	companion object : TypeAdapter<ColorReplacements>() {
		val EMPTY = ColorReplacements(Int2IntOpenHashMap())

		override fun write(out: JsonWriter, value: ColorReplacements?) {
			if (value == null)
				out.nullValue()
			else {
				out.beginObject()

				for ((k, v) in value.mapping) {
					out.name(k.toString(16))
					out.value(v.toString(16))
				}

				out.endObject()
			}
		}

		override fun read(`in`: JsonReader): ColorReplacements? {
			if (`in`.consumeNull())
				return null
			else if (`in`.peek() == JsonToken.STRING) {
				if (`in`.nextString() != "")
					throw JsonSyntaxException("Invalid color replacement definition near ${`in`.path}")

				return ColorReplacements.EMPTY
			}

			val mapping = Int2IntOpenHashMap()

			`in`.beginObject()

			while (`in`.peek() != JsonToken.END_OBJECT) {
				val k = `in`.nextName()
				val v = `in`.nextString()

				mapping[k.toInt(16)] = v.toInt(16)
			}

			`in`.endObject()

			return ColorReplacements(mapping)
		}
	}
}
