local modname = minetest.get_current_modname()

--localize some stuff for performance
local Random = PcgRandom
local floor = math.floor
local table_insert = table.insert
local ipairs = ipairs

local registered_populators = {}
local accumulated_weight = 0
--test seed: 6888913275966624651

_G[modname] = {}
_G[modname].register_dungeon_populator = function(weight, func)
	--we add weight to 0 so it's converted to number if it's a string
	weight = 0 + weight
	assert(weight > 0 and floor(weight) == weight,
		"Error registering dungeon populator: weight must be a positive whole number")
	accumulated_weight = accumulated_weight + weight
		
	for i = 1, #registered_populators + 1
	do
		local v = registered_populators[i]
		if not v or v[1] < weight
		then
			table_insert(registered_populators, i, {weight, func})
			return
		end
	end
end

--1/3 of rooms are empty by default
minetest.register_on_mods_loaded(function()
		if accumulated_weight == 0
		then
			accumulated_weight = 1
		end
		_G[modname].register_dungeon_populator(accumulated_weight * 2, function()end) --TODO: make setting
	end)



do
	local _, gennotify = minetest.get_gen_notify()
	gennotify.dungeon = true
	minetest.set_gen_notify(gennotify)
end

local function populate_dungeon(pos, rand)
	local roll = rand:next(1, accumulated_weight)
	for i, v in ipairs(registered_populators)
	do
		roll = roll - v[1]
		if roll < 1
		then
			v[2](pos, rand)
			return
		end
	end
end

minetest.register_on_generated(function(minp, maxp, blockseed)
		local gennotify = minetest.get_mapgen_object("gennotify")
		local poslist = gennotify["dungeon"] or {}
		local rand = Random(blockseed)
		for i, pos in ipairs(poslist)
		do
			populate_dungeon(pos, rand)
		end
	end)
