This module contains new entry creation rules for Finnish; see WT:ACCEL for an overview, and Module:accel for information on creating new rules.


return {generate = function (params, entry)
	local headparam = {}
	local formparam = {
		['plural-nominative'] = 'case=nominative|pl=plural',
		['singular-genitive'] = 'case=genitive|pl=singular',
		['plural-genitive'] = 'case=genitive|pl=plural',
		['singular-partitive'] = 'case=partitive|pl=singular',
		['plural-partitive'] = 'case=partitive|pl=plural',
		['singular-accusative'] = 'case=accusative|pl=singular',
		['plural-accusative'] = 'case=accusative|pl=plural',
		['singular-inessive'] = 'case=inessive|pl=singular',
		['plural-inessive'] = 'case=inessive|pl=plural',
		['singular-elative'] = 'case=elative|pl=singular',
		['plural-elative'] = 'case=elative|pl=plural',
		['singular-illative'] = 'case=illative|pl=singular',
		['plural-illative'] = 'case=illative|pl=plural',
		['singular-adessive'] = 'case=adessive|pl=singular',
		['plural-adessive'] = 'case=adessive|pl=plural',
		['singular-ablative'] = 'case=ablative|pl=singular',
		['plural-ablative'] = 'case=ablative|pl=plural',
		['singular-allative'] = 'case=allative|pl=singular',
		['plural-allative'] = 'case=allative|pl=plural',
		['singular-essive'] = 'case=essive|pl=singular',
		['plural-essive'] = 'case=essive|pl=plural',
		['singular-translative'] = 'case=translative|pl=singular',
		['plural-translative'] = 'case=translative|pl=plural',
		['plural-instructive'] = 'case=instructive|pl=plural',
		['plural-comitative'] = 'case=comitative|pl=plural', -- needs alt forms
		['singular-abessive'] = 'case=abessive|pl=singular',
		['plural-abessive'] = 'case=abessive|pl=plural'}
	local participle_heads = {
		['pres|actv|part'] = 'present active participle',
		['pres|pasv|part'] = 'present passive participle',
		['past|actv|part'] = 'past active participle',
		['past|pasv|part'] = 'past passive participle',
		['agentpart'] = 'agent participle',
		['neg|part'] = 'negative participle',
	}
	
	local function scan_vowel_harmony(word) 
		for pos = #word, 1, -1 do
			local char = mw.ustring.sub(word, pos, pos)
			if mw.ustring.match(char, "[aou]") then
				return "a"
			elseif mw.ustring.match(char, "[äöy]") then
				return "ä"
			end
		end
		return "ä"
	end
	
	local function lookup_vowel_harmony_for_comp_sup(pagename)
		local page_text = mw.title.new(pagename)
		if not page_text then return nil end
		page_text = page_text:getContent()
		if not page_text then return nil end
		for tname, targs in require("Module:template parser").findTemplates(page_text) do
			if mw.ustring.match(tname, "^fi%-decl%-") and targs.pos == "adj" then
				local vh = targs[#targs]
				if mw.ustring.match(vh, "^[aä]$") then
					return vh
				end
			end
		end
		return nil
	end

	local function generate_participle_declension(word, type)
		local vhua = { ["u"] = "a", ["y"] = "ä" }
		local lword = mw.ustring.len(word)
		if type == "pres|actv|part" then			-- ...vA
			return "{{fi-decl-koira|pos=adj|" .. mw.ustring.sub(word, 1, lword - 1) .. "|||" .. mw.ustring.sub(word, lword, lword) .. "}}"
		elseif type == "pres|pasv|part" then		-- ...(t)tAvA
			return "{{fi-decl-koira|pos=adj|" .. mw.ustring.sub(word, 1, lword - 1) .. "|||" .. mw.ustring.sub(word, lword, lword) .. "}}"
		elseif type == "past|actv|part" then		-- ...(n)Ut
			return "{{fi-decl-kuollut|pos=adj|" .. mw.ustring.sub(word, 1, lword - 2) .. "|" .. vhua[mw.ustring.sub(word, lword - 1, lword - 1)] .. "}}"
		elseif type == "past|pasv|part" then		-- ...tU
			-- this is the most complicated one
			local special = mw.ustring.sub(word, lword - 2, lword - 2)
			local final = mw.ustring.sub(word, lword, lword) -- U
			final = final .. "|" .. vhua[final] -- U|A
			if special == "l" or special == "n" or special == "r" then
				return "{{fi-decl-valo|pos=adj|" .. mw.ustring.sub(word, 1, lword - 3) .. "|" .. special .. "t|" .. special .. special .. "|" .. final .. "}}"
			elseif special == "t" then
				return "{{fi-decl-valo|pos=adj|" .. mw.ustring.sub(word, 1, lword - 3) .. "|tt|t|" .. final .. "}}"
			elseif special == "s" then
				return "{{fi-decl-valo|pos=adj|" .. mw.ustring.sub(word, 1, lword - 1) .. "|||" .. final .. "}}"
			else
				return "{{fi-decl-valo|pos=adj|" .. mw.ustring.sub(word, 1, lword - 2) .. "|t|d|" .. final .. "}}"
			end
		elseif type == "agentpart" then			-- ...mA
			return "{{fi-decl-koira|pos=adj|" .. mw.ustring.sub(word, 1, lword - 1) .. "|||" .. mw.ustring.sub(word, lword, lword) .. "|hideadjnote=1}}"
		elseif type == "neg|part" then			-- ...mAtOn
			return "{{fi-decl-onneton|pos=adj|" .. mw.ustring.sub(word, 1, lword - 3) .. "|" .. mw.ustring.sub(word, lword - 3, lword - 3) .. "}}"
		else
			return nil -- ????
		end
	end
	
	local function common_partition(a, b)
		local i = 0
		while mw.ustring.sub(a, 1, i + 1) == mw.ustring.sub(b, 1, i + 1) do
			i = i + 1
		end
		return mw.ustring.sub(a, 1, i), mw.ustring.sub(a, i + 1), mw.ustring.sub(b, i + 1)
	end
	
	local function get_minen_pronunciation(word, target)
		local page = mw.title.new(word, 0)
		local content = page:getContent()
		if not content then return nil end
		
		local result = nil
		
		-- find fi-p/fi-pronunciation with only one parameter. ignore those that do not have the first parameter ending in *
		local m_templateparser = require("Module:template parser")
		for name, args in m_templateparser.findTemplates(content) do
			if name == "fi-pronunciation" and args[1] and not args[2] then
				if args[1]:sub(#args[1]) == "*" then
					-- multiple options
					if result then return nil end
					result = args[1]
				end
			end
		end
	
		if not result then return nil end
		if result == "*" then result = word .. "*" end
		
		local prefix, origin_suffix, target_suffix = common_partition(word, target)
		if not mw.ustring.match(result, origin_suffix .. "%*$") then return nil end
		result = mw.ustring.sub(result, 1, -mw.ustring.len(origin_suffix) - 2) .. target_suffix
		
		if result == target then return "{{fi-p}}" end
		return "{{fi-p|" + result + "}}"
	end
	
	local was_rare = false
	if params.form:sub(1, 5) == "rare-" then
		was_rare = true
		params.form = params.form:sub(6)
	end

	if params.form:sub(1, 11) == "comparative" then
		if params.pos == "adjective" then
			local form, vh = unpack(mw.text.split(params.form, '|', true))
			local vhfooter
			if not vh then vh = lookup_vowel_harmony_for_comp_sup(params.origin_pagename) end
			if vh == "a" or vh == "ä" then
				vhfooter = vh .. "}}"
			else
				vhfooter = scan_vowel_harmony(params.origin) .. "}} {{attention|fi|verify that vowel harmony is correct}}"
			end
			if mw.ustring.sub(params.target, -3) == "mpi" then
				entry.declension = "{{fi-decl-vanhempi|pos=adj|" .. 
										mw.ustring.sub(params.target, 1, -4) .. "|" .. vhfooter
			elseif mw.ustring.sub(params.target, -4) == "inen" then
				entry.declension = "{{fi-decl-nainen|pos=adj|" .. 
										mw.ustring.sub(params.target, 1, -4) .. "|" .. vhfooter
			else
				entry.declension = "{{rfinfl|fi}}"
			end
		end

	elseif params.form:sub(1, 11) == "superlative" then
		if params.pos == "adjective" then
			local form, vh = unpack(mw.text.split(params.form, '|', true))
			local vhfooter
			if not vh then vh = lookup_vowel_harmony_for_comp_sup(params.origin_pagename) end
			if vh == "a" or vh == "ä" then
				vhfooter = vh .. "}}"
			else
				vhfooter = scan_vowel_harmony(params.origin) .. "}} {{attention|fi|verify that vowel harmony is correct}}"
			end
			entry.declension = "{{fi-decl-sisin|pos=adj|" .. 
									mw.ustring.sub(params.target, 1, -3) .. "|" .. vhfooter
		end

	elseif params.form:sub(1, 15) == "part-possessive" then
		-- possessive form of adverbial
		local form, poss = unpack(mw.text.split(params.form, '|', true))
		-- replace 3s,3p => 3, because 3rd person singular and plural are identical and "third-person" is thus enough
		entry.def = entry.make_def("inflection of", "||" .. poss:gsub("(%d)(%a)", "%1|%2|form"):gsub("3", "3|form"))

	elseif params.form:sub(1, 6) == "vnoun-" or params.form == "inf4" then
		-- verbal nouns; require declension
		entry.def = entry.make_def("verbal noun of")
		entry.head = entry.make_head("noun")
		entry.pos_header = "Noun"
		entry.etymology = "{{af|fi|" .. params.origin .. "|-minen}}"
		entry.pronunc = get_minen_pronunciation(params.origin, params.target) or "{{rfp|fi}} <!-- {{fi-p}} -->"
		entry.declension = "{{fi-decl-nainen|" .. mw.ustring.sub(params.target, 1, -4) .. "|" .. mw.ustring.sub(params.form, -1) .. "}}"

	elseif params.form:sub(1, 11) == "participle-" then
		-- participles; require declension
		local infl = mw.ustring.sub(params.form, #"participle-" + 1)
		local declension = generate_participle_declension(params.target, infl)
		if declension == nil then error("Unsupported participle " .. infl) end
		entry.def = entry.make_def("inflection of", "||" .. infl)
		entry.head = entry.make_head(participle_heads[infl] or "participle")
		entry.pos_header = "Participle"
		entry.declension = declension

	elseif mw.ustring.match(params.form, "|inf") then
		entry.head = entry.make_head("infinitive")
		entry.def = entry.make_def("inflection of", "||" .. params.form)

	elseif params.form:sub(1, 10) == "possessive" then
		error("This form is not supported anymore! If you see this error, please report it to [[User talk:Surjection]] (and include the page you found this from).")
	elseif mw.ustring.match(params.form, "^inf1l-") then
		error("This form is not supported anymore! If you see this error, please report it to [[User talk:Surjection]] (and include the page you found this from).")
	elseif mw.ustring.match(params.form, "^inf5-") then
		error("This form is not supported anymore! If you see this error, please report it to [[User talk:Surjection]] (and include the page you found this from).")
	elseif mw.ustring.match(params.form, "com%-pl%-[aä]") then
		error("This form is not supported anymore! If you see this error, please report it to [[User talk:Surjection]] (and include the page you found this from).")
	elseif formparam[params.form] then
		error("This form is not supported anymore! If you see this error, please report it to [[User talk:Surjection]] (and include the page you found this from).")
	else
		-- needed here because of code below
		entry.def = entry.make_def("inflection of", "||" .. params.form)
	end

	if mw.ustring.find(params.target, "[ _]") then  -- no link
		entry.head = mw.ustring.sub(entry.head, 1, -3) .. "|head=" .. mw.ustring.gsub(params.target, "_", " ") .. mw.ustring.sub(entry.head, -2)
	end
	
	if was_rare then
		entry.def = '{{lb|fi|nocat=1|rare}} ' .. entry.def	
	end
end}