Implements code for Template:fi-adv-poss and Template:fi-word-poss.


-- handles possessives for particles (adverbs, postpositions, etc.)
-- used to implement {{fi-adv-poss}} and {{fi-word-poss}}

local m_links = require("Module:links")
local m_sc = require("Module:script utilities")
local lang = require("Module:languages").getByCode("fi")

local export = {}

export.poss_table = function(frame)
	local title = mw.title.getCurrentTitle().text
	local args = frame:getParent().args
	local word = args["title"] or title
	local xsuffix = args["suffix"] or ""
	local tableheader = args["header"] or "possessor"
	local glosses = {}
	
	local vh = args[1]
	local allow_alt_form = nil
	local nosuf = true
	if vh ~= "a" and vh ~= "ä" then
		error("You must supply 'a' or 'ä' as a parameter to this template.")
	end
	if (args["an"] or args["alt"]) ~= nil then
		local val = args["an"] or args["alt"]
		allow_alt_form = not (not val or val == "" or val == "0" or val == "no" or val == "n" or val == "false")
	end
	
	if mw.ustring.match(xsuffix, "^_") then
		xsuffix = " " .. xsuffix:sub(2)	
	end

	if args["poss"] then
		-- already has possessive suffix. we lemmatize entries under 3rd
		-- person singular, so the entry name must then end in -nsA, -An or -en
		if mw.ustring.match(word, "an$") or mw.ustring.match(word, "en$") then
			word = word:sub(1, #word - 2)
			allow_alt_form = true
		elseif mw.ustring.match(word, "än$") then
			word = word:sub(1, #word - #"än") -- Lua + Unicode is messy
			allow_alt_form = true
		elseif mw.ustring.match(word, "nsa$") then
			word = word:sub(1, #word - 3)
			allow_alt_form = false
		elseif mw.ustring.match(word, "nsä$") then
			word = word:sub(1, #word - #"nsä") -- Lua + Unicode is messy
			allow_alt_form = false
		else
			error("Unrecognized possessive form. Is this under the correct lemma (3rd person possessive)?")
		end
		nosuf = false
	end

	data = generate_possessive_forms(word, args["stem"] or word, vh, allow_alt_form, nosuf, xsuffix)
	
	if args["n"] == "sg" then
		data["1p"] = nil
		data["2p"] = nil	
	elseif args["n"] == "pl" then
		data["1s"] = nil
		data["2s"] = nil	
	end
	
	for key, value in pairs(data) do
		glosses[key] = args["t" .. key]
	end

	return "" .. make_possessive_table_internal(data, true, tableheader, glosses)
end

export.word_poss_table = function(frame)
	local title = mw.title.getCurrentTitle().text
	local args = frame:getParent().args
	local word = args[1] or error("You must supply the stem as a parameter to this template.")
	local xsuffix = args["suffix"] or ""
	local tableheader = args["header"] or "possessor"
	local glosses = {}
	
	local vh = args[2]
	local allow_alt_form = nil
	if vh ~= "a" and vh ~= "ä" then
		error("You must supply 'a' or 'ä' as a parameter to this template.")
	end
	if (args["an"] or args["alt"]) ~= nil then
		local val = args["an"] or args["alt"]
		allow_alt_form = not (not val or val == "" or val == "0" or val == "no" or val == "n" or val == "false")
	end
	
	if mw.ustring.match(xsuffix, "^_") then
		xsuffix = " " .. xsuffix:sub(2)	
	end

	data = generate_possessive_forms(word, args["stem"] or word, vh, allow_alt_form, false, xsuffix)
	
	if args["n"] == "sg" then
		data["1p"] = nil
		data["2p"] = nil	
	elseif args["n"] == "pl" then
		data["1s"] = nil
		data["2s"] = nil	
	end
	
	for key, value in pairs(data) do
		glosses[key] = args["t" .. key]
	end

	return "" .. make_possessive_table_internal(data, false, tableheader, glosses)
end

function generate_possessive_forms(word, stem, vh, allow_alt_form, nosuf, xsuffix)
	local result = {}
	
	if nosuf then
		result["np"] = word
	end
	
	if stem:match("n$") then
		stem = stem:sub(1, #stem - 1)
	end
	if stem:match("ksi$") then -- translative
		stem = stem:sub(1, #stem - 3) .. "kse"
	end

	if allow_alt_form == nil then
		allow_alt_form = not (mw.ustring.match(stem, "aa$") or mw.ustring.match(stem, "ää$") or mw.ustring.match(stem, "ee$"))
	end

	local thirdperson = { stem .. "ns" .. vh .. xsuffix }
	if allow_alt_form then
		local alt_form = stem
		if mw.ustring.match(stem, "e$") then
			alt_form = alt_form .. "en"
		elseif mw.ustring.match(stem, "[aä]$") then
			alt_form = alt_form .. vh .. "n"
		else
			allow_alt_form = false
		end
		if allow_alt_form then
			table.insert(thirdperson, 1, alt_form .. xsuffix)
		end
	end
	
	result["1s"] = { stem .. "ni" .. xsuffix }
	result["2s"] = { stem .. "si" .. xsuffix }
	result["1p"] = { stem .. "mme" .. xsuffix }
	result["2p"] = { stem .. "nne" .. xsuffix }
	result["3"] = thirdperson
	
	return result
end

function make_possessive_table_internal(data, show_np, tableheader, glosses)
	local link_words = show_np

	local function show_form(forms, code, no_rare)
		local form = forms[code]
		if not form or #form < 1 then
			return "&mdash;"
		end
		
		local ret = {}
		
		for key, subform in ipairs(form) do
			if link_words then
				table.insert(ret, m_links.full_link({
					lang = lang,
					term = subform,
					gloss = glosses[code],
					accel = {
						form = "part-possessive|" .. code
					},
				}))
			else
				table.insert(ret, m_sc.tag_text(subform, lang, lang:findBestScript(subform), nil))
			end
		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 == "tableheader" then
			return tableheader
		elseif param == "npheader" then
			return "no possessor"
		elseif param == "np" then
			if data["np"] then
				return m_sc.tag_text(data["np"], lang, lang:findBestScript(data["np"]), "bold")
			else
				return "&mdash;"
			end
		else
			return show_form(data, param)
		end
	end
	
	local wikicode = ""
	if show_np then
		wikicode = [=[
{| class="inflection-table vsSwitcher" data-toggle-category="inflection" style="color: rgb(0%,0%,30%); border: solid 1px rgb(80%,80%,100%); text-align: center;" cellspacing="1" cellpadding="2"
|- style="background: #e2f6e2;"
! class="vsToggleElement" style="min-width: 30em; text-align: left;" colspan="3" | Personal/[[Appendix:Finnish possessive suffixes|possessive forms]] of {{{lemma}}}
|- class="vsHide"
! style="background:#e2f6e2" | {{{npheader}}}
| colspan="2" | {{{np}}}
|- class="vsHide"
! style="min-width: 11em; background:#c0e4c0" | {{{tableheader}}}
! style="min-width: 10em; background:#c0e4c0" | singular
! style="min-width: 10em; background:#c0e4c0" | plural
|- class="vsHide" style="background:rgb(95%,95%,100%)"
! style="background:#e2f6e2" | 1st person
| {{{1s}}}
| {{{1p}}}
|- class="vsHide" style="background:rgb(95%,95%,100%)"
! style="background:#e2f6e2" | 2nd person
| {{{2s}}}
| {{{2p}}}
|- class="vsHide" style="background:rgb(95%,95%,100%)"
! style="background:#e2f6e2" | 3rd person
| colspan="2" | {{{3}}}
|}]=]
	else
		wikicode = [=[
{| style="border: solid 1px; text-align: center;" cellspacing="1" cellpadding="2"
|-
! style="border: solid 1px; min-width: 11em" | {{{tableheader}}}
! style="border: solid 1px; min-width: 10em" | singular
! style="border: solid 1px; min-width: 10em" | plural
|-
! style="border: solid 1px;" | 1st person
| style="border: solid 1px;" | {{{1s}}}
| style="border: solid 1px;" | {{{1p}}}
|- 
! style="border: solid 1px;" | 2nd person
| style="border: solid 1px;" | {{{2s}}}
| style="border: solid 1px;" | {{{2p}}}
|-
! style="border: solid 1px;" | 3rd person
| colspan="2" style="border: solid 1px;" | {{{3}}}
|}]=]
	end
	return mw.ustring.gsub(wikicode, "{{{([a-z0-9_:]+)}}}", repl)
end

return export