local m_links = require("Module:links")
local m_scriptutils = require("Module:script utilities")

local lang = require("Module:languages").getByCode("nl")

local export = {}

-- Functions that do the actual inflecting by creating the forms of a basic term.
local inflections = {}
local irregular = {}

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
	local infl_type = frame.args[1] or "adjective"
	
	if not inflections[infl_type] then
		error("Unknown inflection type '" .. infl_type .. "'")
	end
	
	local data = {forms = {}, comparable = true}
	local args = require("Module:parameters").process(frame:getParent().args, inflections[infl_type].params)
	
	-- Generate the forms
	inflections[infl_type].func(args, data)
	
	return make_table(data)
end

inflections["adjective"] = {
	params = {
		[1] = {},
		[2] = {},
		[3] = {},
		["pred"] = {},
		["part"] = {},
		},
	func = function(args, data)
		-- Get parameters
		local pred_pos = args["pred"]
		local infl_pos = args[1]
		local part_pos = args["part"]
		local comp = args[2]
		local sup = args[3]
		
		if comp == "-" then
			data.comparable = false
		end
		
		local base = mw.title.getCurrentTitle().nsText == "Template" and "-" or mw.title.getCurrentTitle().text
		
		-- Positive degree
		if pred_pos == "-" then
			pred_pos = nil
		else
			pred_pos = pred_pos or base
		end
		
		infl_pos = infl_pos or export.make_inflected(base)
		
		if part_pos == "-" then
			part_pos = nil
		else
			part_pos = part_pos or export.make_partitive(base)
		end
		
		data.forms["pred_pos"] = {pred_pos}
		data.forms["mfsg_pos"] = {infl_pos}
		data.forms["nsg_pos"] = {base}
		data.forms["pl_pos"] = {infl_pos}
		data.forms["def_pos"] = {infl_pos}
		data.forms["part_pos"] = {part_pos}
		
		-- Participles never have comparative and superlative forms.
		-- If they do, then they're probably really adjectives.
		if data.comparable then
			-- Comparative degree
			comp = comp or export.make_comparative(base, infl_pos)
			local infl_comp = export.make_inflected(comp); if base:find("[^eio]en$") or base:find("[aeou]ien$") then infl_comp = comp end
			local part_comp = export.make_partitive(comp)
			
			data.forms["pred_comp"] = {comp}
			data.forms["mfsg_comp"] = {infl_comp}
			data.forms["nsg_comp"] = {comp}
			data.forms["pl_comp"] = {infl_comp}
			data.forms["def_comp"] = {infl_comp}
			data.forms["part_comp"] = {part_comp}
			
			-- Superlative degree
			sup = sup or export.make_superlative(base, part_pos)
			local infl_sup = export.make_inflected(sup)
			
			data.forms["pred_sup"] = {"het [[" .. sup .. "]]", "het [[" .. infl_sup .. "]]"}
			data.forms["mfsg_sup"] = {infl_sup}
			data.forms["nsg_sup"] = {infl_sup}
			data.forms["pl_sup"] = {infl_sup}
			data.forms["def_sup"] = {infl_sup}
			data.forms["part_sup"] = nil
		end
	end
}

inflections["pres-ptc"] = {
	params = {
		[1] = {},
		},
	func = function(args, data)
		data.comparable = false
		inflections["adjective"].func(args, data)
		
		-- The predicative form of the present participle can have -e too,
		-- in sentences like "Hij is stervende".
		table.insert(data.forms["pred_pos"], data.forms["mfsg_pos"][1])
	end
}

inflections["past-ptc"] = {
	params = {
		[1] = {},
		},
	func = function(args, data)
		data.comparable = false
		inflections["adjective"].func(args, data)
	end
}

inflections["irregular"] = {
	params = {
		[1] = {},
		},
	func = function(args, data)
		local base = args[1] or (mw.title.getCurrentTitle().nsText == "Template" and "veel" or mw.title.getCurrentTitle().text)
		
		if irregular[base] then
			irregular[base](data)
		else
			error("Unknown irregular adjective '" .. base .. "'.")
		end
	end
}

irregular["veel"] = function(data)
	data.forms["pred_pos"] = {"veel"}
	data.forms["mfsg_pos"] = {"veel"}
	data.forms["nsg_pos"] = {"veel"}
	data.forms["pl_pos"] = {"veel"}
	data.forms["def_pos"] = {"vele"}
	data.forms["part_pos"] = nil
	
	data.forms["pred_comp"] = {"meer"}
	data.forms["mfsg_comp"] = {"meer"}
	data.forms["nsg_comp"] = {"meer"}
	data.forms["pl_comp"] = {"meer"}
	data.forms["def_comp"] = nil
	data.forms["part_comp"] = nil
	
	data.forms["pred_sup"] = {"het [[meest]]", "het [[meeste]]"}
	data.forms["mfsg_sup"] = nil
	data.forms["nsg_sup"] = nil
	data.forms["pl_sup"] = nil
	data.forms["def_sup"] = {"meeste"}
	data.forms["part_sup"] = nil
end

irregular["weinig"] = function(data)
	data.forms["pred_pos"] = {"weinig"}
	data.forms["mfsg_pos"] = {"weinig"}
	data.forms["nsg_pos"] = {"weinig"}
	data.forms["pl_pos"] = {"weinig"}
	data.forms["def_pos"] = {"weinige"}
	data.forms["part_pos"] = nil
	
	data.forms["pred_comp"] = {"minder"}
	data.forms["mfsg_comp"] = {"minder"}
	data.forms["nsg_comp"] = {"minder"}
	data.forms["pl_comp"] = {"minder"}
	data.forms["def_comp"] = nil
	data.forms["part_comp"] = nil
	
	data.forms["pred_sup"] = {"het [[minst]]", "het [[minste]]"}
	data.forms["mfsg_sup"] = {"minste"}
	data.forms["nsg_sup"] = {"minste"}
	data.forms["pl_sup"] = {"minste"}
	data.forms["def_sup"] = {"minste"}
	data.forms["part_sup"] = nil
end

-- Four functions to create various forms.
-- These are exported, because Module:nl-headword also uses them to create
-- comparative and superlative forms.

function export.make_inflected(base)
	-- Adjectives ending in unstressed -en or -e get no extra -e.
	if base:find("[^eio]en$") or base:find("[aeou]ien$") or base:find("[^eio]e$") then
		return base
	-- Adjectives ending in certain digraphs get a diaeresis
	elseif base:find("[eio]e$") then
		return base .. "ë"
	else
		return base .. "e"
	end
end

function export.make_partitive(base)
	-- Adjectives ending in a sibilant do not get an extra -s
	if base:find("s$") or base:find("sch$") or base:find("x$") or base:find("sj$") or base:find("sh$") then
		return base
	-- Adjectives ending in a long vowel get an apostrophe before the -s
	elseif base:find("[^aeiou][aiouy]$") then
		return base .. "'s"
	else
		return base .. "s"
	end
end

function export.make_comparative(base, inflected)
	if not inflected then
		inflected = export.make_inflected(base)
	end
	
	-- Adjectives ending in -r get an extra -d- in the comparative,
	-- disregarding the inflected form
	if base:find("r$") then
		return base .. "der"
	-- If the inflected form does not end in -e, add it
	elseif not inflected:find("[eë]$") then
		return inflected .. "er"
	else
		return inflected .. "r"
	end
end

function export.make_superlative(base, partitive)
	if not partitive then
		partitive = export.make_partitive(base)
	end
	
	-- Adjectives in -ide have a superlative -iedst
	if base:find("[iï]de$") then
		return base:gsub("([iï])de$", "%1ed") .. "st"
	elseif partitive then
		return partitive .. "t"
	else
		return base .. "st"
	end
end


-- Make the table
function make_table(data)
	local function show_form(form)
		if not form then
			return "—"
		elseif type(form) ~= "table" then
			error("a non-table value was given in the list of inflected forms.")
		elseif #form == 0 then
			return "—"
		end
		
		local ret = {}
		
		for key, subform in ipairs(form) do
			table.insert(ret, m_links.full_link({lang = lang, term = subform}))
		end
		
		return table.concat(ret, "<br/>")
	end
	
	local function repl(param)
		if param == "lemma" then
			return m_links.full_link({lang = lang, alt = mw.title.getCurrentTitle().text}, "term")
		elseif param == "info" then
			return data.title and " (" .. data.title .. ")" or ""
		else
			return show_form(data.forms[param])
		end
	end
	
	local wikicode = [=[
{| style="border: 1px solid #CCCCFF; text-align: center; line-height: 125%;" class="inflection-table vsSwitcher vsToggleCategory-inflection" cellspacing="1" cellpadding="3"
|- style="background: #CCCCFF;"
! colspan="5" class="vsToggleElement" style="text-align: left" | การผันรูปของ {{{lemma}}}{{{info}}}
|- class="vsShow" style="background: #F2F2FF;"
! style="background: #CCCCFF;" | uninflected
| style="min-width: 12em;" | {{{nsg_pos}}}
|- class="vsShow" style="background: #F2F2FF;"
! style="background: #CCCCFF;" | inflected
| {{{mfsg_pos}}}
|- class="vsShow" style="background: #F2F2FF;"
! style="background: #CCCCFF;" | comparative
| {{{nsg_comp}}}
|- class="vsHide" style="background: #CCCCFF;"
| colspan="2" style="background: #E6E6FF;" |
! style="min-width: 12em;" | [[positive degree|positive]]]=] .. (data.comparable and [=[

! style="min-width: 12em;" | [[comparative degree|comparative]]
! style="min-width: 12em;" | [[superlative degree|superlative]]]=] or "") .. [=[

|- class="vsHide" style="background: #F2F2FF;"
! style="background: #CCCCFF;" colspan="2" | [[predicative]]/[[adverbial]]
| {{{pred_pos}}}]=] .. (data.comparable and " || {{{pred_comp}}} || {{{pred_sup}}}" or "") .. [=[

|- class="vsHide" style="background: #F2F2FF;"
! style="background: #CCCCFF;" rowspan="3" | [[indefinite]]
! style="background: #CCCCFF;" | [[masculine|m.]]/[[feminine|f.]]&nbsp;[[singular|sing.]]
| {{{mfsg_pos}}}]=] .. (data.comparable and " || {{{mfsg_comp}}} || {{{mfsg_sup}}}" or "") .. [=[

|- class="vsHide" style="background: #F2F2FF;"
! style="background: #CCCCFF;" | [[neuter|n.]]&nbsp;[[singular|sing.]]
| {{{nsg_pos}}}]=] .. (data.comparable and " || {{{nsg_comp}}} || {{{nsg_sup}}}" or "") .. [=[

|- class="vsHide" style="background: #F2F2FF;"
! style="background:#CCCCFF;" | [[plural]]
| {{{pl_pos}}}]=] .. (data.comparable and " || {{{pl_comp}}} || {{{pl_sup}}}" or "") .. [=[

|- class="vsHide" style="background: #F2F2FF;"
! style="background: #CCCCFF;" colspan="2" | [[definite]]
| {{{def_pos}}}]=] .. (data.comparable and " || {{{def_comp}}} || {{{def_sup}}}" or "") .. [=[

|- class="vsHide" style="background: #F2F2FF;"
! style="background: #CCCCFF;" colspan="2" | [[partitive]]
| {{{part_pos}}}]=] .. (data.comparable and " || {{{part_comp}}} || {{{part_sup}}}" or "") .. [=[

|}]=]
	
	return (mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl))
end

return export