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


local pl = world_storage:get_key("br_core:level_tracker") or {}

-- namespace
br_core.level_tracker = {}

local function get_shell()
    return {
        visited = {},
        completed = {},
    }
end

-- organise callbacks
local on_visit = {}
function br_core.register_on_visit_level(level, func)
    if not on_visit[level] then on_visit[level] = {} end
    on_visit[level][#on_visit[level]+1] = func
end
local on_complete = {}
function br_core.register_on_complete_level(level, func)
    if not on_complete[level] then on_complete[level] = {} end
    on_complete[level][#on_complete[level]+1] = func
end

local function check_player(player)
    if not pl[player:get_player_name()] then
        pl[player:get_player_name()] = get_shell()
    end
end

-- init the player on join
minetest.register_on_joinplayer(function(player, last_login)
    check_player(player)
end)

-- signal that the player has been updated
local function update()
    world_storage:set_key("br_core:level_tracker", pl)
end

-- true if player has visited this level
function br_core.level_tracker.has_visited(player, level)
    return (pl[player:get_player_name()] and pl[player:get_player_name()].visited[level] == true) or false
end
-- true if player has completed this level
function br_core.level_tracker.has_completed(player, level)
    return (pl[player:get_player_name()] and pl[player:get_player_name()].completed[level] == true) or false
end

-- get all info about the player
function br_core.level_tracker.get(player)
    return pl[player:get_player_name()]
end

-- declare this level visited
function br_core.level_tracker.visit(player, level)
    if on_visit[level] and not br_core.level_tracker.has_visited(player, level) then
        for i, func in pairs(on_visit[level]) do
            func(player, level)
        end
    end
    pl[player:get_player_name()].visited[level] = true
end
-- declare this level completed
function br_core.level_tracker.complete(player, level)
    if on_complete[level] and not br_core.level_tracker.has_complete(player, level) then
        for i, func in pairs(on_complete[level]) do
            func(player, level)
        end
    end
    pl[player:get_player_name()].completed[level] = true
end

-- handle visits
br_core.register_on_changed_level(function(player, from_level, to_level)
    if br_core.level[to_level] ~= nil then
        br_core.level_tracker.visit(player, to_level)
    end
end)
