--[[

Menu setting module

* about

This module allows user to customize menu with add on library.

* example

do
    local options = {
        {},
        {"Set Default Engine", "luamacros(search.SetSearch)"},
        {},
        {"Open results in current page", "luamacros(search.SetOpen(0))"},
        {"Open results in new page", "luamacros(search.SetOpen(1))"},
        {"Open results in background", "luamacros(search.SetOpen(2))"},
    }
    -- scan registred search engines and append menu
    local k, v
    for k, v in pairs(search.engines) do
        table.insert(options, 1, {
            v.name or k, "luamacros(search.Search(" .. k .. "))",
        })
    end
    -- add menu
    setmenu.define("Main", -3, "&Lua", {
        {"Copy As Link", "luamacros(CopyAsLink)"},
        {"Search", "luamacros(search.Search)"},
        {"Search Option", options},
        {"Proxy", {
            {"No Proxy", "luamacros(proxy.change(no))"},
            {"Default Proxy", "luamacros(proxy.change(gateway))"},
            {"Local Proxy", "luamacros(proxy.change(local))"},
        }},
        {"Page Links", "luamacros(ViewLinks)"},
        {"List Links", "luamacros(ListLinks)"},
    })
end


]]


require "kmplus"
require "hook"

setmenu = {}

local function append_item(hmenu, pos, item, label, modify)
	if modify then
		hmenu:ModifyMenu(pos, w32mnu.MF_BYPOSITION + w32mnu.MF_STRING,
		                 item, label)
	else
		hmenu:InsertMenu(pos, w32mnu.MF_BYPOSITION + w32mnu.MF_STRING,
		                 item, label)
	end
end

local function append_separator(hmenu, pos, modify)
	if modify then
		hmenu:ModifyMenu(pos, w32mnu.MF_BYPOSITION +
		                 w32mnu.MF_SEPARATOR, 0, "")
	else
		hmenu:InsertMenu(pos, w32mnu.MF_BYPOSITION +
		                 w32mnu.MF_SEPARATOR, 0, "")
	end
end

local function append_string(hmenu, pos, item, label, modify)
	local id  = km.GetID(item)
	if id > 0 then
		append_item(hmenu, pos, id, label, modify)
	end
end

local function append(hmenu, pos, label, item, modify)
	if not item then
		append_separator(hmenu, pos, modify)
		return
	end
	local t = type(item)
	if type(label) ~= "string" then
		return
	end
	if t == "number" then
		append_item(hmenu, pos, item, label, modify)
	elseif t == "string" then
		append_string(hmenu, pos, item, label, modify)
	elseif t == "table" then
		local h = w32mnu.CreatePopupMenu()
		if h then
			local k, v
			for k, v in ipairs(item) do
				append(h, k, v[1], v[2], false)
			end
			if modify then
				hmenu:ModifyMenu(pos, w32mnu.MF_BYPOSITION +
				                 w32mnu.MF_STRING +
				                 w32mnu.MF_POPUP,
				                 h, label)
			else
				hmenu:InsertMenu(pos,
				                 w32mnu.MF_BYPOSITION +
				                 w32mnu.MF_STRING +
				                 w32mnu.MF_POPUP,
				                 h, label)
			end
		end
	end
end

function setmenu.append(name, pos, label, item)
	local hmenu = w32mnu.AttachMenu(km.GetMenu(name))
	if hmenu then
		local c = hmenu:GetMenuItemCount()
		while pos < -1 do
			pos = c + pos + 1
		end
		append(hmenu, pos, label, item, false)
		if name == "Main" and km.hwnd ~= 0 then
			w32mnu.DrawMenuBar(km.hwnd)
		end
	end
end

function setmenu.modify(name, pos, label, item)
	local hmenu = w32mnu.AttachMenu(km.GetMenu(name))
	if hmenu then
		local c = hmenu:GetMenuItemCount()
		while pos < -1 do
			pos = c + pos + 1
		end
		append(hmenu, pos, label, item, true)
		if name == "Main" and km.hwnd ~= 0 then
			w32mnu.DrawMenuBar(km.hwnd)
		end
	end
end

function setmenu.rename(name, item, label)
	local hmenu = w32mnu.AttachMenu(km.GetMenu(name))
	if not hmenu then
		return
	end
	local id = km.GetID(name)
	--if not id > 0 then
	--	return
	--end
	hmenu:ModifyMenu(id, w32mnu.MF_BYCOMMAND + w32mnu.MF_STRING,
	                 id, label)
	if name == "Main" and km.hwnd ~= 0 then
		w32mnu.DrawMenuBar(km.hwnd)
	end
end

--
-- defime menu
--

local defined_menu = {}

function setmenu.define(name, pos, label, item)
	table.insert(defined_menu, {name, pos, label, item})
end

if hook then
	hook.add(SetupHook, function ()
		i, j  = next(defined_menu, nil)
		while i do
			setmenu.append(j[1], j[2], j[3], j[4])
			i, j = next(defined_menu, i)
		end
		-- purge
		defined_menu = nil
	end)
end
