package ru.dbotthepony.kstarbound.defs.dungeon

import com.google.common.collect.ImmutableList
import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.annotations.JsonAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kstarbound.json.getAdapter
import java.util.LinkedList

// dungeons are stored as images, and each pixel
// represents a different tile. To make sense
// of pixel's color, this class is used to lookup
// what to do.
@JsonAdapter(ImageTileSet.Adapter::class)
class ImageTileSet(list: List<DungeonTile> = listOf()) {
	private val mapping = Int2ObjectOpenHashMap<DungeonTile>()

	private val warnings = LinkedList<String>()

	init {
		for ((i, it) in list.withIndex()) {
			val replaced = mapping.put(it.index, it)

			// allow duplicates of same entry because vanilla files have them.
			if (replaced != null && replaced != it) {
				val color = RGBAColor.abgr(it.index)
				warnings.add("Duplicate tile [${color.redInt}, ${color.greenInt}, ${color.blueInt}, ${color.alphaInt}], overwriting: $replaced -> $it")
			}
		}
	}

	fun spewWarnings(prefix: String) {
		warnings.forEach {
			LOGGER.warn("$prefix: $it")
		}

		warnings.clear()
	}

	operator fun get(index: Int): DungeonTile? {
		return mapping.get(index)
	}

	operator fun get(red: Int, green: Int, blue: Int, alpha: Int): DungeonTile? {
		return mapping.get(red.and(0xFF).shl(24) or green.and(0xFF).shl(16) or blue.and(0xFF).shl(8) or alpha.and(0xFF))
	}

	operator fun get(index: RGBAColor): DungeonTile? {
		return this[index.redInt, index.greenInt, index.blueInt, index.alphaInt]
	}

	val isNotEmpty: Boolean
		get() = mapping.isNotEmpty()

	class Adapter(gson: Gson) : TypeAdapter<ImageTileSet>() {
		private val list = gson.getAdapter<ImmutableList<DungeonTile>>()

		override fun write(out: JsonWriter, value: ImageTileSet) {
			TODO("Not yet implemented")
		}

		override fun read(`in`: JsonReader): ImageTileSet {
			return ImageTileSet(list.read(`in`))
		}
	}

	companion object {
		private val LOGGER = LogManager.getLogger()
	}
}
