core.set_gen_notify({dungeon = true})

local possible_mobs = {"mobs_monster:stone_monster",
                       "mobs_skeletons:skeleton_archer",
                       "mobs_monster:oerkki",
                       "mobs_ghost_redo:ghost",
                       "yams_mobs:explosion_master"}

function spawn_dungeon_mob(pos, dm)
    local mob_name
    if dm then
        mob_name = "mobs_monster:dungeon_master"
    else
        local max_index = 2
        if pos.y > 1000 or pos.y <= -1024 then
            max_index = 5
        elseif pos.y <= -512 then
            max_index = 4
        elseif pos.y <= -256 then
            max_index = 3
        end

        -- YAMS-TODO: make this less crappy
        local n = math.random(1, max_index)
        -- 5% chance for explosion masters
        if n == 5 and math.random(1, 100) > 5 then
            n = math.random(1, 4)
        end

        mob_name = possible_mobs[n]
    end

    local m = mobs:add_mob(pos, {name = mob_name})
    if m then
        m.lifetimer = 99999  -- So that it never despawns
    end
end

-- This placeholder node needs to be used due to:
-- https://github.com/minetest/minetest/issues/4759
core.register_node(":yams_rpg:dungeon_mob_spot", {
    drawtype = "airlike",
    groups = {not_in_creative_inventory = 1},
    on_timer = function(pos, elapsed)
        -- Spawn the mob and remove the node once a player gets close enough
        local players = core.get_connected_players()
        for _, player in pairs(players) do
            local player_pos = player:get_pos()
            local dist = vector.distance(pos, player_pos)

            if dist < 24 then
                local dm = (core.get_node(pos).param2 == 1)
                local light = core.get_natural_light(pos, 0.5)

                -- Do not spawn mobs in dungeon rooms exposed to the sun
                if light and light <= 4 then
                    spawn_dungeon_mob(pos, dm)
                end

                -- Remove the timer either way
                core.remove_node(pos)
                return false
            end
        end

        return true  -- Repeats the timer
    end
})

function add_mobs_to_dungeon(minp, maxp, blockseed)
    local gennotify = core.get_mapgen_object("gennotify")
    local poslist = gennotify["dungeon"]

    if not poslist then return end

    table.shuffle(poslist)

    local place_dm = 1  -- Only place one dungeon master in a dungeon

    for _, pos in pairs(poslist) do
        -- Nether dungeons are not implemented at the moment
        if pos.y <= -20000 then
            break
        end

        pos.y = pos.y + 1  -- Otherwise a mob spawns partially in a node

        -- Always place a dungeon master, then skip a few rooms afterwards
        if place_dm == 1 or math.random(1, 4) ~= 1 then
            core.set_node(pos, {name= "yams_rpg:dungeon_mob_spot",
                                    param2 = place_dm})
            local timer = core.get_node_timer(pos)
            timer:start(1)

            place_dm = 0
        end
    end
end

core.register_on_generated(add_mobs_to_dungeon)
