
menupath = core.settings:get("main_menu_script"):match("(.*/)[^/]+.lua$") or
                    core.get_builtin_path().."/"

default_textures = minetest.get_texturepath_share().."/base/pack/"

version = minetest.get_version()

minetest.async_jobs = {}

local function handle_job(jobid, serialized_retval)
    local retval = minetest.deserialize(serialized_retval)
    assert(type(minetest.async_jobs[jobid]) == "function")
    minetest.async_jobs[jobid](retval)
    minetest.async_jobs[jobid] = nil
end

minetest.async_event_handler = handle_job

function minetest.handle_async(func, parameter, callback)
    -- Serialize parameters
    local serialized_param = minetest.serialize(parameter)

    if serialized_param == nil then
        return false
    end

    local jobid = minetest.do_async_callback(func, serialized_param)

    minetest.async_jobs[jobid] = callback

    return true
end

dofile(menupath.."imfs.lua")
dofile(menupath.."theme.lua")
dofile(menupath.."package.lua")
dofile(menupath.."syntax.lua")


window = minetest.get_window_info()
size = window.max_formspec_size

function pixel_to_formspec(pixel)
    return tonumber(pixel) / 80 * window.real_gui_scaling
end

local style_no_background = {
    bgimg = default_textures.."blank.png",
    bgimg_middle = 0,
    content_offset = "0,0",
    textcolor = theme.styles.text_color,
}
styles_no_background = {
    default = style_no_background,
    hovered = style_no_background,
    pressed = style_no_background,
}

style_borderless =  {
    border = false,
    bgimg = "[fill:1x1:0,0:#ffff",
    bgimg_middle = 0,
    bgcolor = theme.styles.container.bg_color,
}
style_borderless_alt =  {
    border = false,
    bgimg = "[fill:1x1:0,0:#ffff",
    bgimg_middle = 0,
    bgcolor = theme.styles.container.bg_color_alt,
}
style_borderless_hovered = {
    border = false,
    bgimg = "[fill:1x1:0,0:#ffff",
    bgimg_middle = 0,
}

local return_to = "meta"

function file_exists(path)
    local f = io.open(path)
    if f then
        f:close()
        return true
    end
    return false
end

function read_file(path)
    local f = io.open(path)
    if f then
        local data = f:read("a")
        f:close()
        if data == "" then return end
        return data
    end
end

local function format_inline_markdown(str)
    local out = {}
    local i = 1
    while true do
        local code_start, code_end, code = str:find("`(.-)`", i)
        if not code_start then break end
        out[#out + 1] = str:sub(i, code_start - 1)
            :gsub("([_*])%1(.-)%1%1", "<b>%2</b>")
            :gsub("([_*])(.-)%1", "<i>%2</i>")
            :gsub("%[(.-)%]%((.-)%)", "<action name=none>%1</action>")
        out[#out + 1] = "<mono><style color="
        out[#out + 1] = theme.styles.code_color
        out[#out + 1] = ">"
        out[#out + 1] = code
        out[#out + 1] = "</style></mono>"
        i = code_end + 1
    end
    out[#out + 1] = str:sub(i)
        :gsub("([_*])%1(.-)%1%1", "<b>%2</b>")
        :gsub("([_*])(.-)%1", "<i>%2</i>")
        :gsub("%[(.-)%]%((.-)%)", "<action name=none>%1</action>")
    return table.concat(out)
end

function markdown_to_hypertext(md)
    md = core.hypertext_escape(md.."\n")
    
    local out = {}
    local state = "doc"
    for line in md:gmatch("(.-)\n") do
        if state == "code" then
            if line:match("^```") then
                state = "doc"
                local code = table.concat(out, "\n")
                if out.__lang == "lua" then
                    code = syntax_highlight(code)
                else
                    code = "<style color="..theme.styles.code_color..">"..code.."</style>"
                end
                out = out.__parent
                out[#out + 1] = "<mono>"
                out[#out + 1] = code
                out[#out + 1] = "</mono>"
            else
                out[#out + 1] = line
                out[#out + 1] = "\n"
            end
        else
            local level, heading = line:match("^(#+) (.+)")
            if heading then
                out[#out + 1] = "<style size="
                out[#out + 1] = 18 * (1 + 1 / #level)
                out[#out + 1] = " color="
                out[#out + 1] = theme.styles.heading_color
                out[#out + 1] = ">"
                out[#out + 1] = format_inline_markdown(heading)
                out[#out + 1] = "</style>"
                out[#out + 1] = "\n"
            else
                local bullet, item = line:match("^%s-([*-]) (.+)")
                if bullet then
                    out[#out + 1] = " • "
                    out[#out + 1] = format_inline_markdown(item)
                    out[#out + 1] = "\n"
                else
                    local code, lang = line:match("^(```)(%a*)")
                    if code then
                        state = "code"
                        out = {__parent = out, __lang = lang}
                    else
                        out[#out + 1] = format_inline_markdown(line)
                        out[#out + 1] = "\n"
                    end
                end
            end
        end
    end
    
    return table.concat(out)
--    return md:gsub("\n%s*####%s*([^\n]-)\n", "\n<b>%1</b>\n")
--        :gsub("\n%s*###%s*([^\n]-)\n", "\n<big>%1</big>\n")
--        :gsub("([^\n]-)\n%-+\n", "\n<big>%1</big>\n")
--        :gsub("\n%s*##%s*([^\n]-)\n", "\n<bigger>%1</bigger>\n")
--        :gsub("\n%s*#%s*([^\n]-)\n", "\n<style size=48>%1</style>\n")
--        :gsub("%*%*([^`\n]-)%*%*", "<b>%1</b>")
--        :gsub("%*([^`\n]-)%*", "<i>%1</i>")
--        :gsub("__([^`\n]-)__", "<b>%1</b>")
--        :gsub("\n_([^`\n]-)_", "<i>%1</i>")
--        :gsub("%*%s+(.-)\n", "• %1\n")
----        :gsub("```%a-\n(.-)```", "<mono><style color="..theme.code_color..">%1</style></mono>")
----        :gsub("`([^`]-)`", "<mono><style color="..theme.code_color..">%1</style></mono>")
--        -- Since we can't (and shouldn't) display images over HTTPS at all, simply get rid of them.
--        :gsub("%[?!%[[^%]]-%]%([^\n]+%)", "")
end

minetest.set_formspec_prepend("\
    style[*;textcolor=#aaa]\
    style_type[field,pwdfield;border=false]\
    style_type[image_button;border=false]\
    style_type[button;border=false;bgimg="..theme.get_background_image("button")..";bgimg_middle=8,8;textcolor="..theme.styles.button.text_color.."]\
    style_type[button:hovered;border=false;bgimg="..theme.get_background_image("button", "hovered")..";bgimg_middle=8,8]\
    style_type[button:pressed;border=false;bgimg="..theme.get_background_image("button", "active")..";bgimg_middle=8,8]\
    style_type[scrollbar;border=false;bgimg="..theme.get_background_image("scrollbar")..";bgimg_middle=8;padding=0,8;fgimg="..theme.get_image("scrollbar", "thumb")..";size=32]\
    style[nobg,nobg:hovered,nobg:focused,nobg:hovered+focused;border=false;bgimg="..default_textures.."blank.png;bgimg_middle=0;content_offset=0,0]\
")

local meta_menu = dofile(menupath.."views/meta_menu.lua")
local servers_menu = dofile(menupath.."views/servers.lua")
local content_menu = dofile(menupath.."views/content.lua")
local online_content_menu = dofile(menupath.."views/online_content.lua")
local settings_menu = dofile(menupath.."views/settings.lua")
local about_menu = dofile(menupath.."views/about.lua")

function show_meta_menu()
    return_to = "meta"
    local last_game = minetest.settings:get("menu_last_game")
    local last_game_index = 1
    local games = minetest.get_games()
    table.sort(games, function(a, b)
        return (a.title or a.name) < (b.title or b.name)
    end)
    for i, x in ipairs(games) do
        if x.id == last_game then last_game_index = i end
    end
    imfs.show(meta_menu, {
        games = games,
        scroll_pos = imfs.state(last_game_index)
    })
end

function show_servers_menu()
    return_to = "servers"
    imfs.show(servers_menu, {
        scroll_pos = imfs.state(1),
        serverlist = imfs.state(),
        detail = imfs.state(),
        detail_view = imfs.state(),
        joining = imfs.state(),
        join_error = imfs.state(),
        address = imfs.state(),
        port = imfs.state(),
        username = imfs.state(core.settings:get("name")),
        password = imfs.state(""),
        search = ""
    })
end

function show_content_menu()
    imfs.show(content_menu, {
        search = "",
        show_type = imfs.state("all"),
        content_shown = imfs.state(),
        page = imfs.state(1),
        current_package = imfs.state(),
    })
end

function show_online_content_menu(content)
    imfs.show(online_content_menu, {
        search = "",
        show_type = imfs.state("all"),
        content_shown = imfs.state(),
        page = imfs.state(1),
        detail = imfs.state(),
    })
end

function show_settings_menu()
    imfs.show(settings_menu, {
        settings_shown = imfs.state(),
        categories_shown = imfs.state(),
        category = imfs.state("Theme"),
        search = ""
    })
end

function show_about_menu()
    imfs.show(about_menu, {
        search = "",
    })
end

show_meta_menu()
 