Powers {{kum-decl-noun}}.


local export = {}

local Kumyk = require "Module:languages".getByCode("kum")

local harmonic_types = {
	["и"] = "front_unrounded",
	["е"] = "front_unrounded", ["э"] = "front_unrounded",
	["ә"] = "front_unrounded",
	["уь"] = "front_rounded", ["оь"] = "front_rounded",
	["ы"] = "back_unrounded",
	
	["у"] = "back_rounded", ["о"] = "back_rounded",
	["ю"] = "rounded", -- ü, yü, yu
	["ё"] = "rounded", -- ö, yö, yo
	
	["а"] = "back_unrounded", ["я"] = "back_unrounded",
}

local function last_harmonic_type_and_vowel(word)
	local harmonic_type, last_vowel
	for pos, vowel_digraph, vowel_letter in mw.ustring.gmatch(mw.ustring.lower(word), "()(([иеэәуыоаяёю])ь?)") do
		if harmonic_types[vowel_digraph] then
			last_vowel = vowel_digraph
			harmonic_type = harmonic_types[vowel_digraph]
		else
			last_vowel = vowel_letter
			harmonic_type = harmonic_types[vowel_letter]
		end
	end
	return harmonic_type, last_vowel
end

local function split_vowel_dimensions(harmonic_type)
	local parts = mw.text.split(harmonic_type, "_")
	assert(#parts == 1 or #parts == 2)
	local roundedness = parts[#parts]
	local backness = #parts == 2 and parts[1] or nil
	return backness, roundedness
end

-- Assumes that the only vowels in the ending are е or и.
local function harmonize(stem, ending, is_back)
	local harmonic_type, last_vowel = last_harmonic_type_and_vowel(stem)
	if not harmonic_type then
		error("No last harmonic type for " .. tostring(stem))
	end
	if (last_vowel == "ю" or last_vowel == "ё") and is_back then
		harmonic_type = harmonic_types["у"]
	end
	local backness, roundedness = split_vowel_dimensions(harmonic_type)
	
	return (mw.ustring.gsub(ending, "[геи]",
		function(letter)
			local result
			if letter == "е" then
				if not backness or backness == "front" then
					result = "е"
				else result = "а" end
			elseif letter == "и" then
				if not backness or backness == "front" then
					if not roundedness or roundedness == "unrounded" then
						result = "и"
					else result = "ю" end
				else
					if not roundedness or roundedness == "unrounded" then
						result = "ы"
					else result = "у" end
				end
			elseif letter == "г" then
				if not backness or backness == "front" then
					result = "г"
				else
					result = "гъ"
				end
			local prevention = {"нгъ", "нг"}
            end
			
			local harmonic_type = last_harmonic_type_and_vowel(result)
			if harmonic_type then
				backness, roundedness = split_vowel_dimensions(harmonic_type)
			end
			
			return result
		end))
end

function export.generate_forms(stem, stem_translit, is_back)
	assert(type(stem) == "string")
	assert(stem_translit == nil or type(stem_translit) == "string")
	
	local forms = {}
	
	local function make_form(key, ending)
		ending = harmonize(stem, ending, is_back)
		forms[key] = stem .. ending
		if stem_translit then
			-- Transliterating a transliterated stem plus Cyrillic ending does
			-- not work in all cases, but should work with these noun endings.
			forms[key .. "_tr"] = (Kumyk:transliterate(stem_translit .. ending))
		end
	end
	
	-- vowels given in front unrounded forms
	make_form("nom_sg", "")
	make_form("acc_sg", "ни")
	make_form("dat_sg", "ге")
	make_form("loc_sg", "де")
	make_form("abl_sg", "ден")
	make_form("gen_sg", "ни")
	
	make_form("nom_pl", "лер")
	make_form("acc_pl", "лени")
	make_form("dat_pl", "леге")
	make_form("loc_pl", "лерде")
	make_form("abl_pl", "лерден")
	make_form("gen_pl", "лени")

    make_form("nom_sg_1sg", "им")
	make_form("acc_sg_1sg", "имни")
	make_form("dat_sg_1sg", "имге")
	make_form("loc_sg_1sg", "имде")
	make_form("abl_sg_1sg", "имден")
	make_form("gen_sg_1sg", "имни")
	
	make_form("nom_pl_1sg", "лерим")
	make_form("acc_pl_1sg", "леримни")
	make_form("dat_pl_1sg", "лериме")
	make_form("loc_pl_1sg", "леримде")
	make_form("abl_pl_1sg", "леримден")
	make_form("gen_pl_1sg", "леримни")

    make_form("nom_sg_1pl", "ибиз")
	make_form("acc_sg_1pl", "ибизни")
	make_form("dat_sg_1pl", "ибизге")
	make_form("loc_sg_1pl", "ибизде")
	make_form("abl_sg_1pl", "ибизден")
	make_form("gen_sg_1pl", "ибизни")
	
	make_form("nom_pl_1pl", "лерибиз")
	make_form("acc_pl_1pl", "лерибизни")
	make_form("dat_pl_1pl", "лерибизге")
	make_form("loc_pl_1pl", "лерибизде")
	make_form("abl_pl_1pl", "лерибизден")
	make_form("gen_pl_1pl", "лерибизни")

    make_form("nom_sg_2sg", "инг")
	make_form("acc_sg_2sg", "ингни")
	make_form("dat_sg_2sg", "инге")
	make_form("loc_sg_2sg", "ингде")
	make_form("abl_sg_2sg", "ингден")
	make_form("gen_sg_2sg", "ингни")
	
	make_form("nom_pl_2sg", "леринг")
	make_form("acc_pl_2sg", "лерингни")
	make_form("dat_pl_2sg", "леринге")
	make_form("loc_pl_2sg", "лерингде")
	make_form("abl_pl_2sg", "лерингден")
	make_form("gen_pl_2sg", "лерингни")

    make_form("nom_sg_2pl", "игиз")
	make_form("acc_sg_2pl", "игизни")
	make_form("dat_sg_2pl", "игизге")
	make_form("loc_sg_2pl", "игизде")
	make_form("abl_sg_2pl", "игизден")
	make_form("gen_sg_2pl", "игизни")
	
	make_form("nom_pl_2pl", "леригиз")
	make_form("acc_pl_2pl", "леригизни")
	make_form("dat_pl_2pl", "леригизге")
	make_form("loc_pl_2pl", "леригизде")
	make_form("abl_pl_2pl", "лерибизден")
	make_form("gen_pl_2pl", "леригизни")

    make_form("nom_sg_3", "и")
	make_form("acc_sg_3", "ин")
	make_form("dat_sg_3", "ине")
	make_form("loc_sg_3", "инде")
	make_form("abl_sg_3", "инден")
	make_form("gen_sg_3", "ини")
	
	make_form("nom_pl_3", "лери")
	make_form("acc_pl_3", "лерин")
	make_form("dat_pl_3", "лерине")
	make_form("loc_pl_3", "леринде")
	make_form("abl_pl_3", "леринден")
	make_form("gen_pl_3", "лерини")
	
	return forms
end

local full_link = require "Module:links".full_link
local function link(term, tr)
	return full_link({ term = term, lang = Kumyk, tr = tr })
end

local function add_forms(text, forms)
	return (text
		:gsub(
			"{{{(.-)}}}",
			function(code)
				local form = forms[code]
				local tr = forms[code .. "_tr"]
				if not form then return end
				if code == "testcase" then
					return form
				else
					return link(form, tr)
				end
			end))
end

local function make_testcase(forms)
	local number_abbrs = { "sg", "pl" }
	local case_abbrs = { "nom", "acc", "dat", "loc", "abl", "gen" }
	local rows = {}
	for _, number in ipairs(number_abbrs) do
		local row = {}
		for _, case in ipairs(case_abbrs) do
			table.insert(row, forms[case .. "_" .. number])
		end
		table.insert(rows, table.concat(row, " "))
	end
	return table.concat(rows, "\n")
end

function export.noun(frame)
	local args = frame:getParent().args
	local stem = args[1] or frame.args[1]
	local tr = args.tr or frame.args.tr
	local is_back = require "Module:yesno"(args.back or frame.args.back, false)
	if stem then
		stem = mw.text.trim(stem)
	end
	if stem == "" then
		stem = nil
	end
	if not stem then
		local title = mw.title.getCurrentTitle()
		local namespace = title.nsText
		if namespace == "" then
			stem = title.text
		else
			error("Parameter 1 (stem) is required.")
		end
	end
	
	local template = [[
<div class="NavFrame"><div class="NavHead">Declension of {{{nom_sg}}}</div><div class="NavContent">
{| class="wikitable"
! 
! Singular
! Plural
|-
! nominative
| {{{nom_sg}}}
| {{{nom_pl}}}
|-
! accusative
| {{{acc_sg}}}
| {{{acc_pl}}}
|-
! dative
| {{{dat_sg}}}
| {{{dat_pl}}}
|-
! locative
| {{{loc_sg}}}
| {{{loc_pl}}}
|-
! ablative
| {{{abl_sg}}}
| {{{abl_pl}}}
|-
! genitive
| {{{gen_sg}}}
| {{{gen_pl}}}
|}</div></div>

<div class="NavFrame"><div class="NavHead">Possessive forms of {{{nom_sg}}}</div><div class="NavContent">
{| class="wikitable"
! 1sg
! Singular
! Plural
|-
! nominative
| {{{nom_sg_1sg}}}
| {{{nom_pl_1sg}}}
|-
! accusative
| {{{acc_sg_1sg}}}
| {{{acc_pl_1sg}}}
|-
! dative
| {{{dat_sg_1sg}}}
| {{{dat_pl_1sg}}}
|-
! locative
| {{{loc_sg_1sg}}}
| {{{loc_pl_1sg}}}
|-
! ablative
| {{{abl_sg_1sg}}}
| {{{abl_pl_1sg}}}
|-
! genitive
| {{{gen_sg_1sg}}}
| {{{gen_pl_1sg}}}
|-
! 1pl
! Singular
! Plural
|-
! nominative
| {{{nom_sg_1pl}}}
| {{{nom_pl_1pl}}}
|-
! accusative
| {{{acc_sg_1pl}}}
| {{{acc_pl_1pl}}}
|-
! dative
| {{{dat_sg_1pl}}}
| {{{dat_pl_1pl}}}
|-
! locative
| {{{loc_sg_1pl}}}
| {{{loc_pl_1pl}}}
|-
! ablative
| {{{abl_sg_1pl}}}
| {{{abl_pl_1pl}}}
|-
! genitive
| {{{gen_sg_1pl}}}
| {{{gen_pl_1pl}}}
|-
! 2sg
! Singular
! Plural
|-
! nominative
| {{{nom_sg_2sg}}}
| {{{nom_pl_2sg}}}
|-
! accusative
| {{{acc_sg_2sg}}}
| {{{acc_pl_2sg}}}
|-
! dative
| {{{dat_sg_2sg}}}
| {{{dat_pl_2sg}}}
|-
! locative
| {{{loc_sg_2sg}}}
| {{{loc_pl_2sg}}}
|-
! ablative
| {{{abl_sg_2sg}}}
| {{{abl_pl_2sg}}}
|-
! genitive
| {{{gen_sg_2sg}}}
| {{{gen_pl_2sg}}}
|-
! 2pl
! Singular
! Plural
|-
! nominative
| {{{nom_sg_2pl}}}
| {{{nom_pl_2pl}}}
|-
! accusative
| {{{acc_sg_2pl}}}
| {{{acc_pl_2pl}}}
|-
! dative
| {{{dat_sg_2pl}}}
| {{{dat_pl_2pl}}}
|-
! locative
| {{{loc_sg_2pl}}}
| {{{loc_pl_2pl}}}
|-
! ablative
| {{{abl_sg_2pl}}}
| {{{abl_pl_2pl}}}
|-
! genitive
| {{{gen_sg_2pl}}}
| {{{gen_pl_2pl}}}
|-
! 3
! Singular
! Plural
|-
! nominative
| {{{nom_sg_3}}}
| {{{nom_pl_3}}}
|-
! accusative
| {{{acc_sg_3}}}
| {{{acc_pl_3}}}
|-
! dative
| {{{dat_sg_3}}}
| {{{dat_pl_3}}}
|-
! locative
| {{{loc_sg_3}}}
| {{{loc_pl_3}}}
|-
! ablative
| {{{abl_sg_3}}}
| {{{abl_pl_3}}}
|-
! genitive
| {{{gen_sg_3}}}
| {{{gen_pl_3}}}
|}</div></div>]]
	local forms = export.generate_forms(stem, tr, is_back)
	mw.log(make_testcase(forms))
	return add_forms(template, forms)
end

return export