-- This widget generates menus but synchronously
-- This is done to avoid crashes when generating menus using polymenu
local menu_utils = require("menubar.utils")
local menu_gen = require("menubar.menu_gen")
local beautiful = require("beautiful")
menu_utils.wm_name = ""
local desktop_dirs = {
    "/usr/local/share/applications",
    "/usr/share/applications",
    os.getenv("HOME").."/.local/share/applications"
}

local app_type_map = {
    Other = {
        name = "Other",
        icon = "applications-other"
    },
    Wine = {
        name = "Wine",
        icon = "wine"
    }
}
for k,v in pairs(menu_gen.all_categories) do
    app_type_map[v.app_type] = v
end

local function get_files(dirs,filter)
    local files = {}
    for _,dir in pairs(dirs) do
        local temp = io.popen("find "..tostring(dir),r)
        if temp then
            temp:read("*a"):gsub("[^\n]+",function(path) 
                if ((not filter) or filter(path)) then
                    files[#files+1] = path 
                end
            end)
        end
    end
    return files
end

return function(args)
    local menu = {}
    local category_index = {}
    for _,entry in ipairs(args.before or {}) do
        table.insert(menu,entry)
    end
    local filter = function(t)
        return t:match(".*%.desktop$")
    end
    for _,file in pairs(get_files(desktop_dirs,filter)) do
        local desktop_data = menu_utils.parse_desktop_file(file)
        local category 
        for k,v in pairs(desktop_data.Categories or {"Other"}) do
            if app_type_map[v] then
                category = v
                break
            end
        end
        category = category or "Other"
        local exec = (desktop_data.Exec or ""):gsub("(%s+)%%.(%s*)","%1%2")
        --Make applications that require a terminal open in terminal
        if desktop_data.Terminal then
            exec = (args.terminal or global.terminal).." -e "..exec
        end
        --Special case for wine apps, all thanks to their inconsistency
        if exec and exec:find(" wine ") then
            category = "Wine"
        end
        local icon = desktop_data.Icon
        local name = desktop_data.Name
        local category_name = app_type_map[category].name
        --Another speical case just for wine
        if category_name:match("^Wine") then
            category = "Wine"
        end
        if not desktop_data.NoDisplay then
            if not category_index[category] then
                category_index[category] = {
                    category_name,
                    {}
                }
                table.insert(menu,category_index[category])
            end
            table.insert(category_index[category][2],{
                name,
                exec,
                (icon and menu_utils.lookup_icon(icon))
            })
        end
    end
    for _,entry in ipairs(args.after or {}) do
        table.insert(menu,entry)
    end
    return menu
end
