This module needs documentation.
Please document this module by describing its purpose and usage on the documentation page.

local m_utilities = require("Module:utilities")
local m_links = require("Module:links")

local export = {}

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


local function postprocess(args, data)
	if args["n"] then
		if args["n"] == "p" then
			table.insert(data.categories, lang:getCanonicalName() .. " pluralia tantum")
		elseif args["n"] == "d" then
			table.insert(data.categories, lang:getCanonicalName() .. " dualia tantum")
		elseif args["n"] == "s" then
			table.insert(data.categories, lang:getCanonicalName() .. " uncountable nouns")
		end
		
		for key, form in pairs(data.forms) do
			-- Do not show singular or plural forms for nominals that don't have them
			if (not args["n"]:find("s") and key:find("_sg$"))
					or (not args["n"]:find("d") and key:find("_du$"))
					or (not args["n"]:find("p") and key:find("_pl$")) then
				form = "-"
			end
		
			data.forms[key] = form
		end
	end
end


-- Inflection functions

local gender_names = {
	["m"] = "masculine",
	["f"] = "feminine",
	["n"] = "neuter",
	["?"] = "unknown gender",
}

export["manual"] = function(frame)
	local wikicode = mw.getCurrentFrame():expandTemplate{title = "sga-decl-noun-table", args = {}}
	
	local params = {
		["n"] = {},
		["class"] = {list = true},
		}
	
	local form_params = {}
	
	for match in mw.ustring.gmatch(wikicode, "{{{([a-z0-9_]+)}}}") do
		if match ~= "info" then
			params[match] = {
				list = true,
				default = mw.title.getCurrentTitle().nsText == "Template"
					and "{{{" .. match .. "}}}"
					or nil
			}
			table.insert(form_params, match)
		end
	end
	
	local data = {forms = {}, info = {}, categories = {}}
	
	local parent_args = frame:getParent().args
	
	-- Track empty tables: add category if the only parameter is |class=.
	local empty = true
	for k in pairs(parent_args) do
		if k ~= "class" then
			empty = false
			break
		end
	end
	if empty then
		table.insert(data.categories, "Old Irish nouns with empty inflection tables")
	end
	
	local args = require("Module:parameters").process(parent_args, params)
	
	for _, class in ipairs(args["class"]) do
		local stem, gender = mw.ustring.match(class, "^(.-)%-([mfn?])$")
		
		if not stem or not gender then
			error("Unrecognised inflection class \"" .. class .. "\".")
		end
		
		local class_name
		if stem == "irreg" then
			class_name = "irregular"
		elseif stem == "indecl" then
			class_name = "indeclinable"
		else
			class_name = stem .. "-stem"
		end
		
		table.insert(data.info, gender_names[gender] .. " " .. class_name)
		
		if stem == "io" or stem == "o" or stem == "u" then
			table.insert(data.categories, lang:getCanonicalName() .. " "
				.. gender_names[gender] .. " " .. class_name .. " nouns")
		elseif stem == "i" or stem == "n" or stem == "nt" then
			if gender == "f" or gender == "m" then
				table.insert(data.categories, lang:getCanonicalName()
					.. " masculine or feminine " .. class_name .. " nouns")
			else
				table.insert(data.categories, lang:getCanonicalName() .. " "
					.. gender_names[gender] .. " " .. class_name .. " nouns")
			end
		else
			table.insert(data.categories, lang:getCanonicalName() .. " "
				.. class_name .. " nouns")
		end
	end
	
	data.info = table.concat(data.info, ", ")
	
	local any = false
	
	for _, p in ipairs(form_params) do
		data.forms[p] = args[p]
		any = true
	end
	
	postprocess(args, data)
	
	return make_table(data, wikicode)
end


-- Make the table
function make_table(data, wikicode)
	local function repl(param)
		if param == "info" then
			return mw.getContentLanguage():ucfirst(data.info or "")
		end
		
		local form = data.forms[param]
		
		if form == "-" then
			return "—"
		elseif not form or #form == 0 then
			return ""
		end
		
		local ret = {}
		
		for key, subform in ipairs(form) do
			local note = mw.ustring.match(subform, "%+([HLN])$")
			subform = mw.ustring.gsub(subform, "%+([HLN])$", "")
			subform = m_links.full_link {lang = lang, term = subform, no_check_redundant_translit = true}
			
			if note then
				subform = subform .. "<sup>" .. note .. "</sup>"
			end
			
			table.insert(ret, subform)
		end
		
		return table.concat(ret, ", ")
	end
	
	local wikicode = wikicode or mw.getCurrentFrame():expandTemplate {
		title = "sga-decl-noun-table",
		args = {},
	}
	
	return wikicode:gsub("{{{([%w_]+)}}}", repl)
		.. m_utilities.format_categories(data.categories, lang)
end

return export