local mod_name = minetest.get_current_modname()
local mod_path = minetest.get_modpath(mod_name)
local S = minetest.get_translator(mod_name)

br_spawn = {}
br_spawn.player = world_storage:get_key("br_core:spawn") or {}
local pl = br_spawn.player

function br_spawn.spawn_player(player)
    local pos = player:get_pos()
end

local function get_shell()
    return {
        name = "",
        level = 0,
    }
end

function br_core.get_level(pos)
    return math.floor((pos.y + br_core.offset) / br_core.level_height)
end
local function update_player(player)
    if pl[player:get_player_name()] then
        local pli = pl[player:get_player_name()]
        pli.level = br_core.get_level(player:get_pos())
        world_storage:set_key("br_core:spawn", br_spawn.player)
    end
end

local function init_player(player)
    local d = get_shell()
    d.level = -1
    d.name = player:get_player_name()
    pl[d.name] = d
end

function br_spawn.get_level_y(level)
    return level * br_core.level_height - br_core.offset + (br_core.level[level].base_height or 0)
end

function br_spawn.relocate_player(player, level)
    if not pl[player:get_player_name()] then init_player(player) end
    local pli = pl[player:get_player_name()]
    if level and level ~= pli.level then
        br_core.on_changed_level(player, pli.level, level)
        pli.level = level
    elseif level ~= pli.level then
        br_core.on_changed_level(player, pli.level, 0)
        pli.level = 0
    end
    local ppos = player:get_pos()
    for i=5, 15 do
        ppos.y = br_spawn.get_level_y(pli.level)
        ppos = vector.offset(ppos, (math.random() * 2 - 1)*4*(i), 0, (math.random() * 2 - 1)*4*(i))
        local has_floor = false
        if not minetest.registered_nodes[minetest.get_node(ppos).name].walkable then
            for k=1, 10 do
                local p = vector.offset(ppos, 0, -k, 0)
                if minetest.registered_nodes[minetest.get_node(p).name].walkable then
                    has_floor = true
                    break
                end
            end
        end
        if has_floor then break end
    end
    player:set_pos(ppos)
end

minetest.register_on_joinplayer(function(player, last_login)
    if br_core.dev_mode then
        player:hud_add({
            hud_elem_type = "image",
            alignment = {x=0, y=0},
            position = {x=0.5, y=0.5},
            name = "crosshair",
            text = "crosshair2.png",
            z_index = 800,
            scale = {x = 1, y = 1},
            offset = {x = 0, y = 0},
        })
    end
    if (not last_login) and (not pl[player:get_player_name()]) then
        init_player(player)
        minetest.after(0.1, br_spawn.relocate_player, player, 0)
    elseif not pl[player:get_player_name()] then
        init_player(player)
    end
end)

minetest.register_on_leaveplayer(function(player)
    update_player(player)
end)
minetest.register_on_dieplayer(function(player)
    update_player(player)
end)

function br_spawn.unstuck(player)
    local pos = vector.offset(vector.floor(player:get_pos()), 0.5, 0.5, 0.5)
    local yaw = 1
    for i=1, 100 do
        yaw = (i * 1.897) % 6.28
        local dir = minetest.yaw_to_dir(yaw)
        local ppos = vector.add(vector.multiply(dir, i*2), pos)
        local tpos = vector.offset(ppos, 0, 1, 0)
        if (not minetest.is_creative_enabled(player:get_player_name()))
        and not (minetest.registered_nodes[minetest.get_node(tpos).name].walkable
            and minetest.registered_nodes[minetest.get_node(ppos).name].walkable
            and minetest.get_item_group(minetest.get_node(tpos).name, "full_solid") > 0)
        or i == 100 then
            player:set_pos(ppos)
            return false
        else
            -- player:set_pos(ppos)
            -- minetest.log(i.." gave up")
            -- return true
        end
    end
end

-- make sure you're not stuck in a wall
local timer = 0
minetest.register_globalstep(function(dtime)
    if timer < 1 then timer = timer + dtime return
    else timer = 0 end
    for i, player in pairs(minetest.get_connected_players()) do
        local ppos = player:get_pos()
        local pos = vector.offset(ppos, 0, 1, 0)
        local pli = pl[player:get_player_name()]
        if (not minetest.is_creative_enabled(player:get_player_name()))
        and (math.abs(ppos.y % 1) == 0.5) and minetest.registered_nodes[minetest.get_node(pos).name].walkable
        and minetest.registered_nodes[minetest.get_node(ppos).name].walkable
        and minetest.get_item_group(minetest.get_node(pos).name, "full_solid") > 0 then
            -- minetest.log("getting unstuck")
            br_spawn.unstuck(player)
        end
    end
end)


minetest.register_on_respawnplayer(function(player)
    local pli = pl[player:get_player_name()]
    local tolevel = pli.level
    minetest.after(0.1, function()
        br_spawn.relocate_player(player, tolevel)
    end)
end)
