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

-- namespace
br_core.achievements = {}
br_core.achievements.def = {}

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

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

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

function br_core.achievements.get_achievement_image(photo)
    return "[combine:128x160:0,0=br_achieve_bg.png"..
        ":0,0="..(photo)
end

function br_core.achievements.register_achievement(def)
    if not def.order then def.order = 200 end
    br_core.achievements.def[def.name] = def
end

function br_core.achievements.show(player, defname)
    local def = br_core.achievements.def[defname]
    if not def then
        minetest.log("warning", "ERROR, NO DEF FOR "..defname)
        return
    end
    minetest.sound_play(("br_photo_click_cc0_JamesMontour"), {
        gain = (br_sounds.master or 1) * 1,
        to_player = player:get_player_name(),
        pitch = 1
    })
    check_player(player)
    local pli = pl[player]
    local newdef = table.copy(def)
    newdef.time = 10
    newdef.hud = player:hud_add({
        hud_elem_type = "image",
        text = def.photo,
        scale = {x=1,y=1},
        alignment = {x=1,y=-1},
        position = {x = 0, y = 1},
        offset = {x = 8, y = -8},
        z_index = 200 - #pli,
    })
    pli[#pli+1] = newdef
end

-- give all basic photos silently to the player when starting
minetest.register_on_joinplayer(function(player, last_login)
    for i, level in pairs(br_core.level_for_index) do
        local leveldef = br_core.level[level]
        if leveldef and not leveldef.secret then
            br_core.achievements.achieve(player, "level "..level.." visit", nil, true)
        end
    end
end)

-- show the photo of the level you visit
function br_core.achievements.visit_callback(player, level)
    br_core.achievements.achieve(player, "level "..level.." visit", 3)
end

function br_core.achievements.register_default(level)
    br_core.register_on_visit_level(level, br_core.achievements.visit_callback)
    br_core.achievements.register_achievement({
        name = "level "..level.." visit",
        order = level,
        photo = br_core.achievements.get_achievement_image("br_achievement_visit_"..level..".png"),
        show_image = true,
        on_achieve = function(player, achieve_name) end,
    })
end

function br_core.achievements.achieve(player, achievement_name, delay, silent)
    local pli = pl_achievements[player:get_player_name()]
    if (not pli) or pli[achievement_name] then return false end
    local def = br_core.achievements.def[achievement_name]
    if def then
        if def.on_achieve and not def.on_achieve(player, achievement_name) then
            pli[achievement_name] = true
            world_storage:set_key("br_core:achievements", pl_achievements)
            if def.show_image and not silent then
                if delay then
                    minetest.after(delay, function()
                        br_core.achievements.show(player, achievement_name)
                    end)
                else
                    br_core.achievements.show(player, achievement_name)
                end
            end
        else
            pli[achievement_name] = nil
        end
    end
end

function br_core.achievements.has(player, achievement_name)
    local pli = pl_achievements[player:get_player_name()]
    if pli and pli[achievement_name] then return true
    else return false end
end

function br_core.achievements.get_sorted(player)
    local achieved = pl_achievements[player:get_player_name()]
    local sorted_names = {}
    for name, b in pairs(achieved) do
        local def = br_core.achievements.def[name]
        sorted_names[#sorted_names+1] = {name=name, order=def.order}
    end
    table.sort(sorted_names, function(a,b) return a.order < b.order end)
    return sorted_names
end

function br_core.achievements.get_all(player)
    local pli = pl_achievements[player:get_player_name()]
    if pli then return pli
    else return false end
end

minetest.register_globalstep(function(dtime)
    for i, player in pairs(minetest.get_connected_players()) do
        for k, def in pairs(pl[player]) do
            if def.time > 0 then
                if k == 1 then
                    def.time = def.time - dtime
                end
            else
                player:hud_remove(def.hud)
                table.remove(pl[player], k)
            end
        end
    end
end)

