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

local export = {}

local args = {}
local m_links = require('Module:links')
local lang = require('Module:languages').getByCode('sac')

local gender = 'an'

numbers = {
	'1',
	'1+2',
	'2',
	'3',
	'X'
}
cases = {
	'P', --proximate
	'O', --obviative
	'V', --vocative
	'L', --local
}

possessor_prefixes = {
	['1'] = 'ne',
	['1+2'] = 'ke',
	['2'] = 'ke',
	['3'] = 'o',
	['X'] = 'o',
}
number_suffixes_sg = {
	['1'] = '',
	['2'] = '',
	['3'] = '',
	['X'] = 'inaw',
}
number_suffixes_pl = {
	['1'] = 'enân',
	['1+2'] = 'enân',
	['2'] = 'wâw',
	['3'] = 'wâw',
}
casesg_an = {
	['P'] = 'a',   
	['O'] = 'ani',
	['V'] = 'e',
	['L'] = 'eki',
}
casepl_an = {
	['P'] = 'aki',
	['O'] = 'ahi',
	['V'] = 'etike',
}
casesg_inan = {
	['P'] = 'i',
	['L'] = 'eki',
}
casepl_inan = {
	['P'] = 'ani',
}

casesg = casesg_an
casepl = casepl_an

function export.show(frame)
	PAGENAME = mw.title.getCurrentTitle().text
	args = require("Module:parameters").process(
		frame:getParent().args,
		{
			[1] = {
				default = mw.ustring.gsub(PAGENAME, "(.*)[ai]$", "%1")
			},
			['noem'] = {
				type = 'boolean'
			},
			['wa'] = {},
			['ye'] = {
				default = 'i',
			},
		}
	)
	local stem = args[1]..'@' -- so we don't contract something that shouldn't be contracted
	if frame.args[1] == 'inan' then
		gender = 'inan'
		casesg = casesg_inan
		casepl = casepl_inan
	end
	
	local forms = generate_forms(stem)
	
	forms = modify_forms(forms)

	return make_table(forms)
end

function generate_forms(stem)
	local forms = {}
	--unpossessed forms
	for _, case in ipairs(cases) do
		if casesg[case] then
			forms[case..'S'] = stem..casesg[case]
		end
		
		if casepl[case] then
			forms[case..'P'] = stem..casepl[case]
		end
	end

	if mw.ustring.match(stem,'^[aeiouâêîôû]') then
		stem = 't'..stem
	end
	
	--possessed forms
	local em = (args['noem'] and '' or 'em')
	for _, possessor in ipairs(numbers) do
		for _, case in ipairs(cases) do
			
			--singular possessive
			if number_suffixes_sg[possessor] then
				if casesg[case] then
					forms[possessor..'S'..case..'S'] = possessor_prefixes[possessor]..stem..em..number_suffixes_sg[possessor]..casesg[case]
				end
				
				if casepl[case] then
					forms[possessor..'S'..case..'P'] = possessor_prefixes[possessor]..stem..em..number_suffixes_sg[possessor]..casepl[case]
				end
			end
		
			--plural possessive
			if number_suffixes_pl[possessor] then
				if casesg[case] then
					forms[possessor..'P'..case..'S'] = possessor_prefixes[possessor]..stem..em..number_suffixes_pl[possessor]..casesg[case]
				end
				
				if casepl[case] then
					forms[possessor..'P'..case..'P'] = possessor_prefixes[possessor]..stem..em..number_suffixes_pl[possessor]..casepl[case]
				end
			end
		end
	end
	return forms
end

cons = '([ptkmncshwy])'

function modify_forms(forms)
	for k,v in pairs(forms) do
		forms[k] = mw.ustring.gsub(forms[k],'R([iîy])','sh%1')
		forms[k] = mw.ustring.gsub(forms[k],'R','n')
		
		forms[k] = mw.ustring.gsub(forms[k],cons..'w@e'..cons,'%1o%2') -- we > o / C_C
		forms[k] = mw.ustring.gsub(forms[k],cons..'w@wâ','%1o@wâ') -- 2pl/3pl, by analogy with the above
		
		if args['wa'] ~= 'wa' then
			forms[k] = mw.ustring.gsub(forms[k],'([ptmncshwy])w@a'..cons,'%1ô%2') -- wa > ô / C_C exc. after /k/
			if args['wa'] == 'ô' then -- wa > ô even after /k/
				forms[k] = mw.ustring.gsub(forms[k],'kw@a'..cons,'kô%1')
			end
		end
		forms[k] = mw.ustring.gsub(forms[k],cons..'y@e'..cons,'%1'..args['ye']..'%2')
		
		forms[k] = mw.ustring.gsub(forms[k],cons..'y@wâ','%1'..args['ye']..'@wâ') -- 2pl/3pl, by analogy with the above
	
		forms[k] = mw.ustring.gsub(forms[k],cons..'y@a'..cons,'%1ê%2')
		
		forms[k] = mw.ustring.gsub(forms[k],'w@inaw','w@enaw')
		
		forms[k] = mw.ustring.gsub(forms[k],'[aâ]w@e','â') -- there is a better way to do this probably but I can't be bothered
		forms[k] = mw.ustring.gsub(forms[k],'[eê]w@e','ê')
		forms[k] = mw.ustring.gsub(forms[k],'[iî]w@e','î')
		forms[k] = mw.ustring.gsub(forms[k],'[oô]w@e','ô')
		forms[k] = mw.ustring.gsub(forms[k],'[uû]w@e','û')
		
		forms[k] = mw.ustring.gsub(forms[k],'[aâ]w@w','âw')
		forms[k] = mw.ustring.gsub(forms[k],'[eê]w@w','êw')
		forms[k] = mw.ustring.gsub(forms[k],'[iî]w@w','îw')
		forms[k] = mw.ustring.gsub(forms[k],'[oô]w@w','ôw')
		forms[k] = mw.ustring.gsub(forms[k],'[uû]w@w','ûw')
		
		forms[k] = mw.ustring.gsub(forms[k],'ay@e','â')
		forms[k] = mw.ustring.gsub(forms[k],'iy@e','î')
		forms[k] = mw.ustring.gsub(forms[k],'iy@i','i')

		forms[k] = mw.ustring.gsub(forms[k],'ay@w','âw')
		forms[k] = mw.ustring.gsub(forms[k],'iy@w','îw')

		forms[k] = mw.ustring.gsub(forms[k],'@','')
	end
	return forms
end

function make_table(forms)
	return [=[<div class="NavFrame">
<div class="NavHead">Inflection of ]=] .. forms['PS'] .. [=[</div>
<div class="NavContent">
{| style="width:100%; background:#F0F0F0; color:#000000; text-align:center;" class="inflection-table" cellspacing="1"
|-
! colspan="2" style="background:#87cefa" | Unpossessed
! colspan="2" style="background:#87cefa" | Singular Noun
! colspan="2" style="background:#87cefa" | Plural Noun
]=] .. make_rows_unpossessed(forms) .. [=[
|-
! colspan="2" rowspan="2" style="background:#87cefa" | Possessed
! colspan="2" style="background:#87cefa" | Singular Noun
! colspan="2" style="background:#87cefa" | Plural Noun
|-
! style="background:#87cefa" | Singular Possessive
! style="background:#87cefa" | Plural Possessive
! style="background:#87cefa" | Singular Possessive
! style="background:#87cefa" | Plural Possessive
]=] .. (gender == 'inan' and make_rows_possessed_inan(forms) or make_rows_possessed(forms)) .. [=[
|}</div></div>]=] .. make_categories()
end

possessor_names = {
	['1'] = 'First person',
	['1+2'] = 'First and second person',
	['2'] = 'Second person',
	['3'] = 'Third person',
	['X'] = 'Indefinite',
}
case_names = {
	['P'] = 'Proximate',
	['O'] = 'Obviative',
	['V'] = 'Vocative',
	['L'] = 'Local',
}

function make_rows_unpossessed(forms)
	local s = ''
	local cases_local = (gender == 'inan' and {'P','L'} or cases)
	for _, case in ipairs(cases_local) do
		s = s .. '|-\n! colspan="2" style="background:#87cefa" | '..case_names[case]..'\n'
		s = s .. link_form(forms[case..'S'],true)
		s = s .. link_form(forms[case..'P'],true)
	end
	return s
end

function make_rows_possessed(forms)
	local s = ''
	for _, possessor in ipairs(numbers) do
		s = s .. '|-\n! rowspan="' .. (possessor == '3' and '3' or '4') .. '" style="background:#87cefa" | '..possessor_names[possessor]..'\n'
		for i, case in ipairs(cases) do
			if (possessor ~= '3') or (case ~= 'P') then --3rd person has no proximate. wish Lua had a continue statement
				if case ~= (possessor == '3' and 'O' or 'P') then s = s .. '|-\n' end
				s = s .. '! style="background:#87cefa" | '..case_names[case]..'\n'
				s = s .. link_form(forms[possessor..'S'..case..'S'])
				s = s .. link_form(forms[possessor..'P'..case..'S'])
				s = s .. link_form(forms[possessor..'S'..case..'P'])
				s = s .. link_form(forms[possessor..'P'..case..'P'])
			end
		end
	end
	return s
end

function make_rows_possessed_inan(forms)
	local s = ''
	for _, possessor in ipairs(numbers) do
		s = s .. '|-\n! rowspan="2" style="background:#87cefa" | '..possessor_names[possessor]..'\n'
		for i, case in ipairs({'P','L'}) do
			if case ~= 'P' then s = s .. '|-\n' end
			s = s .. '! style="background:#87cefa" | '..case_names[case]..'\n'
			s = s .. link_form(forms[possessor..'S'..case..'S'])
			s = s .. link_form(forms[possessor..'P'..case..'S'])
			s = s .. link_form(forms[possessor..'S'..case..'P'])
			s = s .. link_form(forms[possessor..'P'..case..'P'])
		end
	end
	return s
end

function link_form(term, colspan)
	if term then
		if colspan then
			return '| colspan="2" | '..m_links.full_link({lang=lang, term=term})..'\n'
		else
			return '| '..m_links.full_link({lang=lang, term=term})..'\n'
		end
	else
		if colspan then
			return '| style="background:#c0c0c0" colspan="2" | &nbsp;\n'
		else
			return '| style="background:#c0c0c0" | &nbsp;\n'
		end
	end
end

function make_categories()
	if gender == 'inan' then
		return '[[Category:Fox inanimate nouns]]'
	else
		return '[[Category:Fox animate nouns]]'
	end
end

return export