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("cel-pro")


local function postprocess(args, data)
	data.actv = true
	data.pasv = true
	
	if args["v"] == "actv" then
		data.pasv = false
	elseif args["v"] == "pasv" then
		data.actv = false
		data.info = data.info .. ", deponent"
		table.insert(data.categories, lang:getCanonicalName() .. " deponent verbs")
	end
	
	for key, form in pairs(data.forms) do
		-- Do not show singular or plural forms for nominals that don't have them
		if (args["v"] == "actv" and key:find("pasv")) or (args["v"] == "pasv" and key:find("actv")) then
			form = nil
		end
		
		data.forms[key] = form
	end
end


local function present(data, stem)
	if not stem then
		stem = "?"
	end
	local stem2 = stem
	local stem_pl = stem
	
-- Present indicative: default athematic; overridden by stem-class specific rules
	data.forms["actv_pres_indc_1sg"] = {stem .. "mi"}
	data.forms["actv_pres_indc_2sg"] = {stem .. "si"}
	data.forms["actv_pres_indc_3sg"] = {stem .. "ti"}
	data.forms["actv_pres_indc_1pl"] = {stem .. "mosi"}
	data.forms["actv_pres_indc_2pl"] = {stem .. "tesi"}
	data.forms["actv_pres_indc_3pl"] = {stem .. "nti"}

	data.forms["pasv_pres_indc_1sg"] = {stem .. "r"}
	data.forms["pasv_pres_indc_2sg"] = {stem .. "tar"}
	data.forms["pasv_pres_indc_3sg"] = {stem .. "tor"}
	data.forms["pasv_pres_indc_1pl"] = {stem .. "mmor"}
	data.forms["pasv_pres_indc_2pl"] = {stem .. "dwe"}
	data.forms["pasv_pres_indc_3pl"] = {stem .. "ntor"}
	
	-- Imperfect indicative
	data.forms["actv_impf_indc_1sg"] = {stem .. "mam"}
	data.forms["actv_impf_indc_2sg"] = {stem .. "tās"}
	data.forms["actv_impf_indc_3sg"] = {stem .. "to"}
	data.forms["actv_impf_indc_1pl"] = {stem .. "mo"}
	data.forms["actv_impf_indc_2pl"] = {stem .. "stē"}
	data.forms["actv_impf_indc_3pl"] = {stem .. "nto"}
	
	data.forms["pasv_impf_indc_3sg"] = {"?"}
	data.forms["pasv_impf_indc_3pl"] = {"?"}
	
	-- Imperative
	data.forms["actv_impr_2sg"] = {stem}
	data.forms["actv_impr_3sg"] = {stem .. "tou"}
	data.forms["actv_impr_1pl"] = {stem .. "mos"}
	data.forms["actv_impr_2pl"] = {stem .. "te"}
	data.forms["actv_impr_3pl"] = {stem .. "ntou"}
	
-- Present-stem overrides

	if mw.ustring.find(stem, "e$") then
		table.insert(data.info, "thematic present")
		stem2 = string.sub(stem, 1, -2)
		data.forms["actv_pres_indc_1sg"] = {stem2 .. "ū"}
		data.forms["actv_pres_indc_2sg"] = {stem2 .. "esi"}
		data.forms["actv_pres_indc_3sg"] = {stem2 .. "eti"}
		data.forms["actv_pres_indc_1pl"] = {stem2 .. "omosi"}
		data.forms["actv_pres_indc_2pl"] = {stem2 .. "etesi"}
		data.forms["actv_pres_indc_3pl"] = {stem2 .. "onti"}

		data.forms["pasv_pres_indc_1sg"] = {stem2 .. "ūr"}
		data.forms["pasv_pres_indc_2sg"] = {stem2 .. "etar"}
		data.forms["pasv_pres_indc_3sg"] = {stem2 .. "etor"}
		data.forms["pasv_pres_indc_1pl"] = {stem2 .. "ommor"}
		data.forms["pasv_pres_indc_2pl"] = {stem2 .. "edwe"}
		data.forms["pasv_pres_indc_3pl"] = {stem2 .. "ontor"}
		
		data.forms["actv_impr_1pl"] = {stem2 .. "omos"}
		data.forms["actv_impr_2pl"] = {stem2 .. "ete"}
		data.forms["actv_impr_3pl"] = {stem2 .. "ontou"}

	elseif mw.ustring.find(stem, "<h2e>$") then
		table.insert(data.info, "thematic present with a-colouring")
		stem2 = string.sub(stem, 1, -6)
		pref, suf = string.match(stem2, "^(.-)e(.+)$")
		-- for *sistati
		if pref == nil then
			stem_a = stem2
		else stem_a = pref .. "a" .. suf
		end
		
		data.forms["actv_pres_indc_1sg"] = {stem2 .. "ū"}
		data.forms["actv_pres_indc_2sg"] = {stem_a .. "asi"}
		data.forms["actv_pres_indc_3sg"] = {stem_a .. "ati"}
		data.forms["actv_pres_indc_1pl"] = {stem2 .. "omosi"}
		data.forms["actv_pres_indc_2pl"] = {stem_a .. "atesi"}
		data.forms["actv_pres_indc_3pl"] = {stem2 .. "onti"}

		data.forms["pasv_pres_indc_1sg"] = {stem2 .. "ūr"}
		data.forms["pasv_pres_indc_2sg"] = {stem_a .. "atar"}
		data.forms["pasv_pres_indc_3sg"] = {stem_a .. "ator"}
		data.forms["pasv_pres_indc_1pl"] = {stem2 .. "ommor"}
		data.forms["pasv_pres_indc_2pl"] = {stem_a .. "adwe"}
		data.forms["pasv_pres_indc_3pl"] = {stem2 .. "ontor"}
		
		data.forms["actv_impf_indc_1sg"] = {stem_a .. "amam"}
		data.forms["actv_impf_indc_2sg"] = {stem_a .. "atās"}
		data.forms["actv_impf_indc_3sg"] = {stem_a .. "ato"}
		data.forms["actv_impf_indc_1pl"] = {stem_a .. "amo"}
		data.forms["actv_impf_indc_2pl"] = {stem_a .. "astē"}
		data.forms["actv_impf_indc_3pl"] = {stem_a .. "anto"}

		data.forms["actv_impr_2sg"] = {stem_a .. "a"}
		data.forms["actv_impr_3sg"] = {stem_a .. "atou"}
		data.forms["actv_impr_1pl"] = {stem2 .. "omos"}
		data.forms["actv_impr_2pl"] = {stem_a .. "ate"}
		data.forms["actv_impr_3pl"] = {stem2 .. "ontou"}
		
	elseif mw.ustring.find(stem, "a$") then
		table.insert(data.info, "athematic present")

-- Seṭ-root nasal-infixed presents
	elseif mw.ustring.find(stem, "<H>$") then
		table.insert(data.info, "athematic h₂-root nasal-infix present")
		stem2 = string.sub(stem, 1, -4)
		stem_pl = string.sub(stem, 1, -6) .. "a"
		data.forms["actv_pres_indc_1sg"] = {stem2 .. "mi"}
		data.forms["actv_pres_indc_2sg"] = {stem2 .. "si"}
		data.forms["actv_pres_indc_3sg"] = {stem2 .. "ti"}
		data.forms["actv_pres_indc_1pl"] = {stem_pl .. "mosi"}
		data.forms["actv_pres_indc_2pl"] = {stem_pl .. "tesi"}
		data.forms["actv_pres_indc_3pl"] = {stem_pl .. "nti"}
		data.forms["pasv_pres_indc_1sg"] = {stem2 .. "r"}
		data.forms["pasv_pres_indc_2sg"] = {stem2 .. "tar"}
		data.forms["pasv_pres_indc_3sg"] = {stem2 .. "tor"}
		data.forms["pasv_pres_indc_1pl"] = {stem_pl .. "mmor"}
		data.forms["pasv_pres_indc_2pl"] = {stem_pl .. "dwe"}
		data.forms["pasv_pres_indc_3pl"] = {stem_pl .. "ntor"}
		
		data.forms["actv_impf_indc_1sg"] = {stem_pl .. "mam"}
		data.forms["actv_impf_indc_2sg"] = {stem_pl .. "tās"}
		data.forms["actv_impf_indc_3sg"] = {stem_pl .. "to"}
		data.forms["actv_impf_indc_1pl"] = {stem_pl .. "mo"}
		data.forms["actv_impf_indc_2pl"] = {stem_pl .. "stē"}
		data.forms["actv_impf_indc_3pl"] = {stem_pl .. "nto"}

		data.forms["actv_impr_2sg"] = {stem2}
		data.forms["actv_impr_3sg"] = {stem2 .. "tou"}
		data.forms["actv_impr_1pl"] = {stem_pl .. "mos"}
		data.forms["actv_impr_2pl"] = {stem_pl .. "te"}
		data.forms["actv_impr_3pl"] = {stem_pl .. "ntou"}
	elseif mw.ustring.find(stem, "<h1>$") then
		table.insert(data.info, "athematic h₁-root nasal-infix present")
		stem2 = string.sub(stem, 1, -5)
		stem_pl = string.sub(stem, 1, -7) .. "a"
		stem_3pl = string.sub(stem, 1, -7) .."e"
		data.forms["actv_pres_indc_1sg"] = {stem2 .. "mi"}
		data.forms["actv_pres_indc_2sg"] = {stem2 .. "si"}
		data.forms["actv_pres_indc_3sg"] = {stem2 .. "ti"}
		data.forms["actv_pres_indc_1pl"] = {stem_pl .. "mosi"}
		data.forms["actv_pres_indc_2pl"] = {stem_pl .. "tesi"}
		data.forms["actv_pres_indc_3pl"] = {stem_3pl .. "nti"}
		data.forms["pasv_pres_indc_1sg"] = {stem2 .. "r"}
		data.forms["pasv_pres_indc_2sg"] = {stem2 .. "tar"}
		data.forms["pasv_pres_indc_3sg"] = {stem2 .. "tor"}
		data.forms["pasv_pres_indc_1pl"] = {stem_pl .. "mmor"}
		data.forms["pasv_pres_indc_2pl"] = {stem_pl .. "dwe"}
		data.forms["pasv_pres_indc_3pl"] = {stem_3pl .. "ntor"}
		
		data.forms["actv_impf_indc_1sg"] = {stem_pl .. "mam"}
		data.forms["actv_impf_indc_2sg"] = {stem_pl .. "tās"}
		data.forms["actv_impf_indc_3sg"] = {stem_pl .. "to"}
		data.forms["actv_impf_indc_1pl"] = {stem_pl .. "mo"}
		data.forms["actv_impf_indc_2pl"] = {stem_pl .. "stē"}
		data.forms["actv_impf_indc_3pl"] = {stem_pl .. "nto"}

		data.forms["actv_impr_2sg"] = {stem2}
		data.forms["actv_impr_3sg"] = {stem2 .. "tou"}
		data.forms["actv_impr_1pl"] = {stem_pl .. "mos"}
		data.forms["actv_impr_2pl"] = {stem_pl .. "te"}
		data.forms["actv_impr_3pl"] = {stem_3pl .. "ntou"}
	elseif mw.ustring.find(stem, "<h3>$") then
		table.insert(data.info, "athematic h₃-root nasal-infix present")
		stem2 = string.sub(stem, 1, -5)
		stem_pl = string.sub(stem, 1, -7) .. "a"
		stem_3pl = string.sub(stem, 1, -7) .."o"
		data.forms["actv_pres_indc_1sg"] = {stem2 .. "mi"}
		data.forms["actv_pres_indc_2sg"] = {stem2 .. "si"}
		data.forms["actv_pres_indc_3sg"] = {stem2 .. "ti"}
		data.forms["actv_pres_indc_1pl"] = {stem_pl .. "mosi"}
		data.forms["actv_pres_indc_2pl"] = {stem_pl .. "tesi"}
		data.forms["actv_pres_indc_3pl"] = {stem_3pl .. "nti"}
		data.forms["pasv_pres_indc_1sg"] = {stem2 .. "r"}
		data.forms["pasv_pres_indc_2sg"] = {stem2 .. "tar"}
		data.forms["pasv_pres_indc_3sg"] = {stem2 .. "tor"}
		data.forms["pasv_pres_indc_1pl"] = {stem_pl .. "mmor"}
		data.forms["pasv_pres_indc_2pl"] = {stem_pl .. "dwe"}
		data.forms["pasv_pres_indc_3pl"] = {stem_3pl .. "ntor"}
		
		data.forms["actv_impf_indc_1sg"] = {stem_pl .. "mam"}
		data.forms["actv_impf_indc_2sg"] = {stem_pl .. "tās"}
		data.forms["actv_impf_indc_3sg"] = {stem_pl .. "to"}
		data.forms["actv_impf_indc_1pl"] = {stem_pl .. "mo"}
		data.forms["actv_impf_indc_2pl"] = {stem_pl .. "stē"}
		data.forms["actv_impf_indc_3pl"] = {stem_pl .. "nto"}

		data.forms["actv_impr_2sg"] = {stem2}
		data.forms["actv_impr_3sg"] = {stem2 .. "tou"}
		data.forms["actv_impr_1pl"] = {stem_pl .. "mos"}
		data.forms["actv_impr_2pl"] = {stem_pl .. "te"}
		data.forms["actv_impr_3pl"] = {stem_3pl .. "ntou"}
-- Weak presents
	elseif mw.ustring.find(stem, "ā$") then
		table.insert(data.info, "ā-present")
	elseif mw.ustring.find(stem, "ī$") then
		table.insert(data.info, "ī-present")
		stem2   = string.sub(stem, 1, -3) .. "ey"
		data.forms["actv_pres_indc_1sg"] = {stem2 .. "ū"}
		data.forms["actv_pres_indc_2sg"] = {stem .. "si"}
		data.forms["actv_pres_indc_3sg"] = {stem .. "ti"}
		data.forms["actv_pres_indc_1pl"] = {stem2 .. "omosi"}
		data.forms["actv_pres_indc_2pl"] = {stem .. "tesi"}
		data.forms["actv_pres_indc_3pl"] = {stem2 .. "onti"}

		data.forms["pasv_pres_indc_1sg"] = {stem2 .. "ūr"}
		data.forms["pasv_pres_indc_2sg"] = {stem .. "tar"}
		data.forms["pasv_pres_indc_3sg"] = {stem .. "tor"}
		data.forms["pasv_pres_indc_1pl"] = {stem2 .. "ommor"}
		data.forms["pasv_pres_indc_2pl"] = {stem .. "dwe"}
		data.forms["pasv_pres_indc_3pl"] = {stem2 .. "ontor"}
		
		data.forms["actv_impr_1pl"] = {stem2 .. "omos"}
		data.forms["actv_impr_2pl"] = {stem .. "te"}
		data.forms["actv_impr_3pl"] = {stem2 .. "ontou"}
--- Copula
	elseif mw.ustring.find(stem, "esē$") then
		table.insert(data.info, "athematic present")
		data.forms["actv_pres_indc_1sg"] = {"esmi"}
		data.forms["actv_pres_indc_2sg"] = {"esi"}
		data.forms["actv_pres_indc_3sg"] = {"esti"}
		data.forms["actv_pres_indc_1pl"] = {"esmosi"}
		data.forms["actv_pres_indc_2pl"] = {"estesi"}
		data.forms["actv_pres_indc_3pl"] = {"senti"}
		data.forms["actv_impr_2sg"] = {"es"}
		data.forms["actv_impr_3sg"] = {"estou"}	
		data.forms["actv_impr_1pl"] = {"smos"}
		data.forms["actv_impr_2pl"] = {"ste"}
		data.forms["actv_impr_3pl"] = {"sentou"}
--- *essi "to eat"
	elseif mw.ustring.find(stem, "ed$") then
		table.insert(data.info, "athematic present")
		data.forms["actv_pres_indc_2sg"] = {"etsi"}
		data.forms["actv_pres_indc_3sg"] = {"essi"}
		data.forms["actv_pres_indc_2pl"] = {"essesi"}
		data.forms["actv_pres_indc_3pl"] = {"(e)denti"}
		data.forms["actv_impf_indc_1sg"] = {"?"}
		data.forms["actv_impf_indc_2sg"] = {"?"}
		data.forms["actv_impf_indc_3sg"] = {"?"}
		data.forms["actv_impf_indc_1pl"] = {"?"}
		data.forms["actv_impf_indc_2pl"] = {"?"}
		data.forms["actv_impf_indc_3pl"] = {"?"}
		data.forms["actv_impr_2sg"] = {"?"}
		data.forms["actv_impr_3sg"] = {"?"}	
		data.forms["actv_impr_1pl"] = {"?"}
		data.forms["actv_impr_2pl"] = {"?"}
		data.forms["actv_impr_3pl"] = {"?"}
		data.forms["pasv_pres_indc_1sg"] = {"?"}
		data.forms["pasv_pres_indc_2sg"] = {"?"}
		data.forms["pasv_pres_indc_3sg"] = {"?"}
		data.forms["pasv_pres_indc_1pl"] = {"?"}
		data.forms["pasv_pres_indc_2pl"] = {"?"}
		data.forms["pasv_pres_indc_3pl"] = {"?"}
	else
		stem = "?"
	end
	
	-- Non-finite forms, do not use
	data.forms["actv_pres_ptcp"] = {stem .. "nts"}
	data.forms["pasv_pres_ptcp"] = {stem .. "mnos"}
end


local function future(data, stem)
	if not stem then
		stem = "?"
	elseif stem == "-" then
		return
	end
	
	data.forms["actv_futr_indc_1sg"] = {stem .. "sū"}
	data.forms["actv_futr_indc_2sg"] = {stem .. "sesi"}
	data.forms["actv_futr_indc_3sg"] = {stem .. "seti"}
	data.forms["actv_futr_indc_1pl"] = {stem .. "somosi"}
	data.forms["actv_futr_indc_2pl"] = {stem .. "setesi"}
	data.forms["actv_futr_indc_3pl"] = {stem .. "sonti"}
	
	data.forms["pasv_futr_indc_1sg"] = {stem .. "sūr"}
	data.forms["pasv_futr_indc_2sg"] = {stem .. "setar"}
	data.forms["pasv_futr_indc_3sg"] = {stem .. "setor"}
	data.forms["pasv_futr_indc_1pl"] = {stem .. "sommor"}
	data.forms["pasv_futr_indc_2pl"] = {stem .. "sedwe"}
	data.forms["pasv_futr_indc_3pl"] = {stem .. "sontor"}
end


local function preterite_actv(data, stem)
	if not stem then
		stem = "?"
	elseif stem == "-" then
		return
	end
	
-- t-preterite
	if mw.ustring.find(stem, "<t>$") then
		stem_t = string.sub(stem, 1, -4)
		stem_t2 = mw.ustring.gsub(stem_t, "[bgkɸm]$", {["b"] = "x", ["g"] = "x", ["k"] = "x", ["ɸ"] = "x", ["m"] = "n"})
		table.insert(data.info, "t-preterite")
		data.forms["actv_pret_indc_1sg"] = {stem_t .. "am"}
		data.forms["actv_pret_indc_2sg"] = {stem_t2 .. "s" or stem_t .. "s"}
		data.forms["actv_pret_indc_3sg"] = {stem_t2 .. "t" or stem_t .. "t"}
		data.forms["actv_pret_indc_1pl"] = {stem_t .. "me"}
		data.forms["actv_pret_indc_2pl"] = {stem_t2 .. "te"  or stem_t .. "te"}
		data.forms["actv_pret_indc_3pl"] = {stem_t .. "ant"}
-- s-preterite
	elseif mw.ustring.find(stem, "<st>$") then
		stem_s = string.sub(stem, 1, -5)
		table.insert(data.info, "s-preterite")
		data.forms["actv_pret_indc_1sg"] = {stem_s .. "am"}
		data.forms["actv_pret_indc_2sg"] = {stem_s .. "s"}
		data.forms["actv_pret_indc_3sg"] = {stem_s .. "t"}
		data.forms["actv_pret_indc_1pl"] = {stem_s .. "me"}
		data.forms["actv_pret_indc_2pl"] = {stem_s .. "te"}
		data.forms["actv_pret_indc_3pl"] = {stem_s .. "ant"}
--- For *dāti "give"
	elseif mw.ustring.find(stem, "<oh>$") then
		stem_oh = string.sub(stem, 1, -5)
		table.insert(data.info, "suffixless preterite")
		data.forms["actv_pret_indc_1sg"] = {stem_oh .. "ū"}
		data.forms["actv_pret_indc_2sg"] = {stem_oh .. "ūs"}
		data.forms["actv_pret_indc_3sg"] = {stem_oh .. "ū"}
		data.forms["actv_pret_indc_1pl"] = {stem_oh .. "amo"}
		data.forms["actv_pret_indc_2pl"] = {stem_oh .. "ate"}
		data.forms["actv_pret_indc_3pl"] = {stem_oh .. "ar"}
--- For *kerat "fell"
	elseif mw.ustring.find(stem, "<at>$") then
		stem_at = string.sub(stem, 1, -5)
		table.insert(data.info, "root aorist")
		data.forms["actv_pret_indc_1sg"] = {stem_at .. "am"}
		data.forms["actv_pret_indc_2sg"] = {stem_at .. "as"}
		data.forms["actv_pret_indc_3sg"] = {stem_at .. "at"}
		data.forms["actv_pret_indc_1pl"] = {stem_at .. "ame"}
		data.forms["actv_pret_indc_2pl"] = {stem_at .. "ate"}
		data.forms["actv_pret_indc_3pl"] = {stem_at .. "ant"}
--- Stative endings as default
	else
		table.insert(data.info, "suffixless preterite")
		stem_2pl = mw.ustring.gsub(stem, "[bgkɸmtd]$", {["b"] = "xt", ["g"] = "xt", ["k"] = "xt", ["ɸ"] = "xt", ["m"] = "nt", ["t"] = "ss", ["d"] = "ss"})
		data.forms["actv_pret_indc_1sg"] = {stem .. "a"}
		data.forms["actv_pret_indc_2sg"] = {stem .. "as?"}
		data.forms["actv_pret_indc_3sg"] = {stem .. "e"}
		data.forms["actv_pret_indc_1pl"] = {stem .. "mo"}
		data.forms["actv_pret_indc_2pl"] = {stem_2pl .. "e"}
		data.forms["actv_pret_indc_3pl"] = {stem .. "ar"}
	end
end

local function subjunctive(data, stem)
	if not stem then
		stem = "?"
	elseif stem == "-" then
		return
	end
	
	data.forms["actv_pres_subj_1sg"] = {stem .. "ū"}
	data.forms["actv_pres_subj_2sg"] = {stem .. "esi"}
	data.forms["actv_pres_subj_3sg"] = {stem .. "eti"}
	data.forms["actv_pres_subj_1pl"] = {stem .. "omosi"}
	data.forms["actv_pres_subj_2pl"] = {stem .. "etesi"}
	data.forms["actv_pres_subj_3pl"] = {stem .. "onti"}
	
	data.forms["pasv_pres_subj_1sg"] = {stem .. "ūr"}
	data.forms["pasv_pres_subj_2sg"] = {stem .. "etar"}
	data.forms["pasv_pres_subj_3sg"] = {stem .. "etor"}
	data.forms["pasv_pres_subj_1pl"] = {stem .. "ommor"}
	data.forms["pasv_pres_subj_2pl"] = {stem .. "edwe"}
	data.forms["pasv_pres_subj_3pl"] = {stem .. "ontor"}
	
	data.forms["actv_past_subj_1sg"] = {"?"}
	data.forms["actv_past_subj_2sg"] = {"?"}
	data.forms["actv_past_subj_3sg"] = {"?"}
	data.forms["actv_past_subj_1pl"] = {"?"}
	data.forms["actv_past_subj_2pl"] = {"?"}
	data.forms["actv_past_subj_3pl"] = {"?"}
end


-- Inflection functions

export["reg"] = function(frame)
	local params = {
		[1] = {},
		[2] = {},
		[3] = {},
		[4] = {allow_holes = true},
		[5] = {},
		
		["v"] = {},
		}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {forms = {}, info = {}, categories = {}}
	
	present(data, args[1])
	future(data, args[2])
	preterite_actv(data, args[3])
	subjunctive(data, args[5])
	
	data.info = table.concat(data.info, ", ")
	
	postprocess(args, data)
	
	return make_table(data) .. m_utilities.format_categories(data.categories, lang)
end

local names = {
	["actv"] = "Active voice",
	["pasv"] = "Passive voice",
	
	["pres_indc"] = "Present",
	["impf_indc"] = "Imperfect",
	["futr_indc"] = "Future",
	["pret_indc"] = "Preterite",
	["pres_subj"] = "Pres. subjunctive",
	["past_subj"] = "Past subjunctive",
	["impr"] = "Imperative",
	
	["1sg"] = "1st singular",
	["2sg"] = "2nd singular",
	["3sg"] = "3rd singular",
	["1pl"] = "1st plural",
	["2pl"] = "2nd plural",
	["3pl"] = "3rd plural",
}

-- Make the table
function make_table(data)
	local function repl(param)
		if param == "info" then
			return mw.getContentLanguage():ucfirst(data.info or "")
		end
		
		local form = data.forms[param]
		
		if not form or #form == 0 then
			return "&mdash;"
		end
		
		if mw.ustring.find(form[1], "^?") then
			return "?"
		end
		
		local ret = {}
		
		for key, subform in ipairs(form) do
			table.insert(ret, m_links.full_link({lang = lang, alt = "*" .. subform}))
		end
		
		return table.concat(ret, ", ")
	end
	
	local pns = {"1sg", "2sg", "3sg", "1pl", "2pl", "3pl"}
	local rows = {
		{"pres_indc", "impf_indc", "futr_indc", "pret_indc"},
		{"pres_subj", "past_subj", "impr"}}
	local voices = {}
	
	if data.actv then
		table.insert(voices, "actv")
	end
	
	if data.pasv then
		table.insert(voices, "pasv")
	end
	
	local colnum = 0
	
	for _, row in ipairs(rows) do
		colnum = math.max(colnum, #row)
	end
	
	local wikicode = {}
	
	table.insert(wikicode, "{| class=\"inflection-table vsSwitcher\" data-toggle-category=\"inflection\" style=\"background: #FAFAFA; border: 1px solid #d0d0d0; text-align: left;\" cellspacing=\"1\" cellpadding=\"2\"")
	table.insert(wikicode, "|- style=\"background: #CCCCFF;\"\n! class=\"vsToggleElement\" colspan=\"" .. (colnum + 1) .. "\" | {{{info}}}")
	
	for _, voice in ipairs(voices) do
		table.insert(wikicode, "|- class=\"vsHide\" style=\"background: #CCCCFF;\"")
		table.insert(wikicode, "! colspan=\"" .. (colnum + 1) .. "\" style=\"text-align: center;\" | " .. names[voice])
		
		for _, row in ipairs(rows) do
			table.insert(wikicode, "|- class=\"vsHide\" style=\"background: #CCCCFF;\"")
			table.insert(wikicode, "!")
			
			local i = 0
			
			for _, tm in ipairs(row) do
				table.insert(wikicode, "! style=\"min-width: 11em; background: #CCCCFF;\" | " .. names[tm])
				i = i + 1
			end
			
			if i < colnum then
				table.insert(wikicode, "! style=\"min-width: 11em; background: #CCCCFF;\" rowspan=\"" .. (#pns + 1) .. "\" colspan=\"" .. (colnum - i) .. "\" |")
			end
			
			for _, pn in ipairs(pns) do
				table.insert(wikicode, "|- class=\"vsHide\" style=\"background-color: #F2F2FF;\"")
				table.insert(wikicode, "! style=\"min-width: 8em; background-color: #E6E6FF;\" | " .. names[pn])
				
				for _, tm in ipairs(row) do
					table.insert(wikicode, "| {{{" .. voice .. "_" .. tm .. "_" .. pn .. "}}}")
				end
			end
		end
	end
	
	table.insert(wikicode, "|}")
	
	wikicode = table.concat(wikicode, "\n")
	
	return (mw.ustring.gsub(wikicode, "{{{([a-z0-9_]+)}}}", repl))
end

return export