Backend for {{ha-noun}}.


local u = require("Module:string/char")

local export = {}

local lang = require("Module:languages").getByCode("ha")
local GRAVE = u(0x0300)
local ACUTE = u(0x0301)

local vowels = {
	['a'] = true, ['e'] = true, ['i'] = true, ['o'] = true, ['u'] = true,
	['â'] = true, ['ê'] = true, ['î'] = true, ['ô'] = true, ['û'] = true,
	['à'] = true, ['è'] = true, ['ì'] = true, ['ò'] = true, ['ù'] = true,
	['á'] = true, ['é'] = true, ['í'] = true, ['ó'] = true, ['ú'] = true,
	['ā'] = true, ['ē'] = true, ['ī'] = true, ['ō'] = true, ['ū'] = true, ["ḕ"] =true, ["ṑ"] = true
}

local long_vowels = {['ā'] = 'a', ['ē'] = 'e', ['ī'] = 'i', ['ō'] = 'o', ['ū'] = 'u', ["ḕ"] = "è", ["ṑ"] = "ò"}

local allowed_genders = {['m'] = true, ['f'] = true, ['p'] = true}

function replace_last_vowel(term)
	local vowel_index = nil
	local vowel = nil
	for i = 1, mw.ustring.len(term) do
		local char = mw.ustring.sub(term,i,i)
		if vowels[char] then
			vowel_index = i
			vowel = char
		end
	end
	if vowel_index then
		if long_vowels[vowel] then
			return mw.ustring.sub(term, 1, vowel_index-1) .. long_vowels[vowel] .. mw.ustring.sub(term, vowel_index+1, mw.ustring.len(term))
		end
	end
	return term
end

function export.generate_possessed_form(term, gender)
	-- replace last vowel with short vowel
	term = replace_last_vowel(term)
	
	local stripped_term = mw.ustring.gsub(term, ACUTE, '')
	stripped_term = mw.ustring.gsub(stripped_term, GRAVE, '')
	
	local length = mw.ustring.len(stripped_term)
	
	local final_char = mw.ustring.sub(stripped_term,length,length)
	
	-- ends with consonant
	if not vowels[final_char] then return nil end
	
	-- contains space
	if mw.ustring.match(term, '%s') then return nil end
	
	-- feminine and ends with a
	if gender == 'f' and (final_char == 'a' or final_char == 'à') then return mw.ustring.toNFC(term .. 'r̃') end
	
	-- ends in ai or au
	local suffix = mw.ustring.sub(stripped_term,length-1,length-1) .. final_char
	if suffix == 'ai' or suffix == 'au' or suffix == 'àu' or suffix == 'ài' then return mw.ustring.toNFC(mw.ustring.sub(term,1,length-1) .. 'n') end
	
	-- otherwise
	return mw.ustring.toNFC(term .. 'n')
	
end

function export.noun(frame)
	local params = {
		[1] = { required = true }, --gender
		["g2"] = {}, --alternate gender
		
		[2] = { required = true }, --head

		["f"] = {}, --feminine form
		["f2"] = {}, -- second feminine form
		["f3"] = {}, -- third feminine form
		
		[3] = {}, --plural
		["pl2"] = {}, --alternate plural
		["pl3"] = {}, --alternate plural
		
		["pos"] = {} --possessed form
	}
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	
	local data = {lang = lang,
		pos_category = "nouns",
		categories = {},
		heads = {},
		genders = {},
		inflections = {}}
	
	if args[1] then
		if allowed_genders[args[1]] then
			table.insert(data.genders, args[1])
		else
			table.insert(data.categories, "Hausa entries with invalid gender")
		end
		if args["g2"] then
			if allowed_genders[args["g2"]] then
				table.insert(data.genders, args["g2"])
			else
				table.insert(data.categories, "Hausa entries with invalid gender")
			end
		end
	else
		table.insert(data.genders, '?')
	end
	
	if args[2] then
		table.insert(data.heads, args[2])
	else
		table.insert(data.categories, "Hausa entries missing head parameter")
	end
	
	if args["f"] then
		local f_table = {label = "feminine", {term = args["f"]}}
		if args["f2"] then
			table.insert(f_table, {term = args["f2"]})
		end
		if args["f3"] then
			table.insert(f_table, {term = args["f3"]})
		end
		
		table.insert(data.inflections, f_table)
	end
	
	if args[3] then
		local plural_table = {label = "plural", args[3]}
		if args["pl2"] then
			table.insert(plural_table, args["pl2"])
			if args["pl3"] then
				table.insert(plural_table, args["pl3"])
			end
		end
		table.insert(data.inflections, plural_table)
	end
	
	if args["pos"] then
		if args["pos"] ~= "-" then
			table.insert(data.inflections, {label = "possessed form", args["pos"]})
		end
	else
		if args[2] then
			local generated_possessed_form = export.generate_possessed_form(args[2], args[1])
			if generated_possessed_form then
				table.insert(data.inflections, {label = "possessed form", generated_possessed_form})
			end
		end
	end
	
	return require("Module:headword").full_headword(data)
	
end
	
return export