package ru.dbotthepony.kstarbound.collect

import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectMap

class IdMap<T : Any>(val min: Int = 0, val max: Int = Int.MAX_VALUE, private val map: MutableMap<Int, T> = Int2ObjectAVLTreeMap()) : MutableMap<Int, T> by map {
	private var nextIndex = min - 1
	private val range = max - min

	init {
		require(range > 1) { "Invalid range for ID Map: $min .. $max" }
	}

	private fun next(): Int {
		if (++nextIndex > max) {
			nextIndex = min
		}

		return nextIndex
	}

	fun add(value: T): Int {
		var i = 0
		var index = next()

		if (map is Int2ObjectMap) {
			while ((map as Int2ObjectMap).containsKey(index)) {
				index = next()

				if (i++ > range) {
					throw RuntimeException("No more free slots in ID Map")
				}
			}
		} else {
			while (map.containsKey(index)) {
				index = next()

				if (i++ > range) {
					throw RuntimeException("No more free slots in ID Map")
				}
			}
		}

		map[index] = value
		return index
	}

	override fun clear() {
		nextIndex = min - 1
		map.clear()
	}
}
