-- Tiny dialog module
-- Please see dialog.txt

if km then
	require "kmplus"
else
	require "w32dlg"
end

local function set_initial(dlg, ctl, ini)
	local k, v, r, t
	if ini and type(ini) == "table" then
		for k, v in pairs(ini) do
			if ctl[k] then
				t = ctl[k].type
				if t == "button" then
					r = dlg:SetButtonInitial(ctl[k].id, v)
					assert(r, "can't set value: " .. k)
				elseif t == "edit" then
					r = dlg:SetEditInitial(ctl[k].id, v)
					assert(r, "can't set value: " .. k)
				elseif t == "static" then
					r = dlg:SetStaticInitial(ctl[k].id, v)
					assert(r, "can't set value: " .. k)
				elseif t == "listbox" then
					r = dlg:SetListboxInitial(ctl[k].id,
						v[1] or {}, v[2] or {})
					assert(r, "can't set value: " .. k)
				elseif t == "combobox" then
					r = dlg:SetComboboxInitial(ctl[k].id,
						v[1] or "", v[2] or {})
					assert(r, "can't set value: " .. k)
				end
			end
		end
	end
end

local function get_result(dlg, ctl, a)
	local k, v, t, b, i
	b = {}
	for k, v in pairs(ctl) do
		if v.id == a then
			i = k
		end
		t = v.type
		if t == "button" then
			b[k] = dlg:GetButtonResult(v.id)
			assert(b[k], "can't get value: " .. k)
		elseif t == "edit" then
			b[k] = dlg:GetEditResult(v.id)
			assert(b[k], "can't get value: " .. k)
		elseif t == "listbox" then
			b[k] = dlg:GetListboxResult(v.id)
			assert(b[k], "can't get value: " .. k)
		elseif t == "combobox" then
			b[k] = dlg:GetComboboxResult(v.id)
			assert(b[k], "can't get value: " .. k)
		end
	end
	return i, b
end

local function create(t)
	local dlg, k, v, r, id, o
	
	dlg = w32dlg.New(t["style"] or 0, t["exstyle"] or 0,
		t["x"] or 0, t["y"] or 0, t.width, t.height, t["caption"],
		t["font"], t["point"])
	id = 1000
	o = {}
	for k, v in ipairs(t) do
		if type(v) == "table" and type(v.id) == "string" then
			local style, exstyle, caption, ty
			
			style = v["style"] or 0
			exstyle = v["exstyle"] or 0
			caption = v["caption"] or ""
			ty = string.lower(v.type)
			if ty == "button" then
				r = dlg:AddButton(style, exstyle,
				                  v.x, v.y,
				                  v.width, v.height,
				                  id, caption)
				assert(r, "create dialog error: " .. v.id)
				o[v.id] = {type = "button", id = id}
				id = id + 1
			elseif ty == "static" then
				r = dlg:AddStatic(style, exstyle,
				                  v.x, v.y,
				                  v.width, v.height,
				                  id, caption)
				assert(r, "create dialog error: " .. v.id)
				o[v.id] = {type = "static", id = id}
				id = id + 1
			elseif ty == "edit" then
				r = dlg:AddEdit(style, exstyle, v.x, v.y,
				                v.width, v.height,
				                id, caption)
				assert(r, "create dialog error: " .. v.id)
				o[v.id] = {type = "edit", id = id}
				id = id + 1
			elseif ty == "listbox" then
				r = dlg:AddListbox(style, exstyle, v.x, v.y,
				                   v.width, v.height,
				                   id, caption)
				assert(r, "create dialog error: " .. v.id)
				o[v.id] = {type = "listbox", id = id}
				id = id + 1
			elseif ty == "combobox" then
				r = dlg:AddCombobox(style, exstyle, v.x, v.y,
				                    v.width, v.height,
				                    id, caption)
				assert(r, "create dialog error: " .. v.id)
				o[v.id] = {type = "combobox", id = id}
				id = id + 1
			else
				error("create dialog error" ..
				      "unsupported control: " .. ty)
			end
		end
	end
	return dlg, o
end

local function show_dialog(dlg, ctl, cpt, ini)
	local a, b, i
	
	set_initial(dlg, ctl, ini)
	if km then
		a = dlg:ShowModal(cpt, km.hDllInstance, km.hwnd)
	else
		a = dlg:ShowModal(cpt, 0, 0)
	end
	i, b = get_result(dlg, ctl, a)
	dlg:ReleaseResult()
	return i, b
end

local function show_propertysheet(dlg, ctl, cpt, sel, ini)
	local k, v, a, b, i
	
	if ini and type(ini) == "table" then
		for k, v in ipairs(dlg) do
			set_initial(dlg[k], ctl[k], ini[k])
		end
	end
	if km then
		a = w32dlg.PropertySheet(dlg, km.hwnd, km.hDllInstance,
		                         cpt, sel)
	else
		a = w32dlg.PropertySheet(dlg, 0, 0, cpt, sel)
	end
	b = {}
	for k, v in ipairs(dlg) do
		i, b[k] = get_result(v, ctl[k])
		dlg[k]:ReleaseResult()
	end
	return a, b
end

local function dialog_factory(d, c)
	return function (t, o)
		return show_dialog(d, c, t, o)
	end
end

local function propertysheet_factory(d, c)
	return function (t, s, o)
		return show_propertysheet(d, c, t, s, o)
	end
end

function create_dialog(t)
	return dialog_factory(create(t))
end

function create_propertysheet(t)
	local c, d, k, v = {}, {}
	for k, v in ipairs(t) do
		d[k], c[k] = create(v)
	end
	return propertysheet_factory(d, c)
end
