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

pmb_spawn = {}

local world_data = {
    spawn_pos = false,
    spawn_near_death = false,
    range = 50,
    players = {}
}

local function save_spawn_data()
    local data = minetest.serialize(world_data)
    local file = io.open(save_path..DIR_DELIM.."pmb_spawn.txt", "w")
    if not file then return end
    file:write(data)
    file:close()
end
local function load_spawn_data()
    local file = io.open(save_path..DIR_DELIM.."pmb_spawn.txt", "r")
    if not file then return end
    local data = minetest.deserialize(file:read("a"), true)
    file:close()
    for key, val in pairs(world_data) do
        world_data[key] = data[key] or world_data[key]
    end
end

function pmb_spawn.set_spawn(pos)
    world_data.spawn_pos = vector.copy(pos)
    save_spawn_data()
end
function pmb_spawn.set_spawn_for(player, pos)
    world_data.players[player:get_player_name()] = (pos and vector.copy(pos)) or nil
    save_spawn_data()
end

minetest.register_privilege("pmb_spawn", {
    description = S("Allows a player to set the world spawn"),
    give_to_singleplayer = false
})

minetest.register_chatcommand("spawn", {
    params = "",
    description = S("Sets the world spawn to the current position of the player"),
    privs = {pmb_spawn = true},
    func = function(name, param)
        local player = minetest.get_player_by_name(name)
        local parse = string.split(param, " ")
        if parse[1] == "set" then
            if player then
                local p = player:get_pos()
                pmb_spawn.set_spawn(p)
                return true, S("Set spawn to x"..p.x..", y"..p.y..", z"..p.z)
            end
        elseif parse[1] == "setplayer" then
            player = minetest.get_player_by_name(parse[2])
            if player then
                local p = player:get_pos()
                pmb_spawn.set_spawn_for(player, p)
                return true, S("Set "..parse[2].."'s spawn to x"..p.x..", y"..p.y..", z"..p.z..".")
            end
        elseif parse[1] == "clearplayer" then
            player = minetest.get_player_by_name(parse[2])
            if player then
                pmb_spawn.set_spawn_for(player, nil)
                return true, S("Removed "..parse[2].."'s spawn; they will now respawn at worldspawn.")
            end
        elseif param == "" then
            pmb_spawn.respawn_player(player)
        end
        return false, S("Error: Invalid. Use /spawn set or /spawn setplayer myname")
    end
})

-- make this find a nearby location instead of a fixed one eventually
function pmb_spawn.get_spawn_pos(player)
    local name = player:get_player_name()
    if world_data.players[name] then
        return world_data.players[name]
    end
    if world_data.spawn_pos then
        return world_data.spawn_pos
    end
    return false
end

function pmb_spawn.respawn_player(player)
    local r = pmb_spawn.get_spawn_pos(player)
    if r then
        player:set_pos(r)
        return true
    else return false end
end

minetest.register_on_respawnplayer(pmb_spawn.respawn_player)

load_spawn_data()
