For use in {{sw-conj}}.


local m_links = require("Module:links")
local m_utils = require("Module:utilities")
local lang = require("Module:languages").getByCode("sw")

local export = {}

local irreg_kw_inf = {
	['isha'] = true,
	['enda'] = true,
	['anza'] = true,
}

local irreg_imp_s = {
	["enda"] = "nenda",
	["ja"] = "njoo",
	["leta"] = "lete",
}

local irreg_imp_p = {
	["enda"] = "nendeni",
	["ja"] = "njooni",
}

local obligatory_obj = {
	['ita'] = true,
	['pa'] = true,
	['ambia'] = true,
}

local subjects = {
	["p"] = {
		["1s"] = "ni",
		["2s"] = "u",
		["3s"] = "a",["1c"] = "a",
		["1p"] = "tu",
		["2p"] = "m",
		["3p"] = "wa",["2c"] = "wa",
		["3c"] = "u",
		["4c"] = "i",
		["5c"] = "li",
		["6c"] = "ya",
		["7c"] = "ki",
		["8c"] = "vi",
		["9c"] = "i",
		["10c"] = "zi",
		["11c"] = "u",
		["15c"] = "ku",
		["16c"] = "pa",
		["18c"] = "mu",
	},
	["n"] = {
		["1s"] = "si",
		["2s"] = "hu",
		["3s"] = "ha",["1c"] = "ha",
		["1p"] = "hatu",
		["2p"] = "ham",
		["3p"] = "hawa",["2c"] = "hawa",
		["3c"] = "hau",
		["4c"] = "hai",
		["5c"] = "hali",
		["6c"] = "haya",
		["7c"] = "haki",
		["8c"] = "havi",
		["9c"] = "hai",
		["10c"] = "hazi",
		["11c"] = "hau",
		["15c"] = "haku",
		["16c"] = "hapa",
		["18c"] = "hamu",
	},
	["cont"] = {
		["1s"] = "n",
		["2s"] = "w",
		["3s"] = "",["1c"] = "",
		["1p"] = "tw",
		["2p"] = "mw",
		["3p"] = "w",["2c"] = "w",
		["3c"] = "w",
		["4c"] = "y",
		["5c"] = "l",
		["6c"] = "y",
		["7c"] = "ch",
		["8c"] = "vy",
		["9c"] = "y",
		["10c"] = "z",
		["11c"] = "w",
		["15c"] = "kw",
		["16c"] = "p",
		["18c"] = "mw",
	},
}

local objects = {
	["1s"] = "ni",
	["2s"] = "ku",
	["3s"] = "m",
	["1c"] = "m",
	["1p"] = "tu",
	["2p"] = "wa",
	["3p"] = "wa",
	["2c"] = "wa",
	["3c"] = "u",
	["4c"] = "i",
	["5c"] = "li",
	["6c"] = "ya",
	["7c"] = "ki",
	["8c"] = "vi",
	["9c"] = "i",
	["10c"] = "zi",
	["11c"] = "u",
	["15c"] = "ku",
	["16c"] = "pa",
	["18c"] = "mu",
	["refl"] = "ji",
}

local oref = {
	["1s"] = "ye",
	["2s"] = "ye",
	["3s"] = "ye",
	["1c"] = "ye",
	["1p"] = "o",
	["2p"] = "o",
	["3p"] = "o",
	["2c"] = "o",
	["3c"] = "o",
	["4c"] = "yo",
	["5c"] = "lo",
	["6c"] = "yo",
	["7c"] = "cho",
	["8c"] = "vyo",
	["9c"] = "yo",
	["10c"] = "zo",
	["11c"] = "o",
	["15c"] = "ko",
	["16c"] = "po",
	["18c"] = "mo",
}

local ind_tami = {
	["past_n"] = "ku",
	["gnom"] = "a",
	["ny"] = "ja",
	["ifw"] = "ki",
	["cons_i"] = "ka",
}

local inf_tami = {
	["past_p"] = "li",
	["pres_p"] = "na",
	["fut_p"] = "ta",
	["fut_n"] = "ta",
	["cond_pres_p"] = "nge",
	["cond_pres_n"] = "singe",
	["cond_past_p"] = "ngali",
	["cond_past_n"] = "singali",
	["perf"] = "me",
	["alr"] = "mesha",
	["ifn"] = "sipo",
}

local subj_tami = {
	["subj_n"] = "si",
	["cons_s"] = "ka",
}

function tablelength(T)
	local count = 0
	for _ in pairs(T) do count = count + 1 end
	return count
end -- needed?

local function get_stem(lemma, args)
	if not mw.ustring.match(lemma, "a$") then
		-- Arabic verb
		return lemma, true, false, { "Swahili verbs in the Arabic conjugation" }
	elseif mw.ustring.match(lemma, "^[^aeiou]+a$") or args.mono ~= nil then
		-- Monosyllabic
		return mw.ustring.gsub(lemma, "^(.*)a$", "%1"), false, true, { "Swahili verbs in the monosyllabic conjugation" }
	else
		-- Normal verbs
		return mw.ustring.gsub(lemma, "^(.*)a$", "%1"), false, false, {}
	end
end

local function link(term, accel_optional)
	if accel_optional then
		return m_links.full_link({ lang = lang, term = term, allowSelfLink = false, accel = { form = accel_optional } })
	else
		return m_links.full_link({ lang = lang, term = term, allowSelfLink = false })
	end
end

local function user_specified(text)
	if text == '-' then
		return '—'
	else
		local temp = {}
		for i, term in ipairs(mw.text.split(text, '/')) do
			table.insert(temp, link(term))
		end
		return table.concat(temp, '<br/>')
	end
end

local function setDefault(t, d)
	local mt = { __index = function() return d end }
	setmetatable(t, mt)
end

local output_subj_accel = {
	["3c"] = "m-mi|singular",
	["4c"] = "m-mi|plural",
	["5c"] = "ji-ma|singular",
	["6c"] = "ji-ma|plural",
	["7c"] = "ki-vi|singular",
	["8c"] = "ki-vi|plural",
	["9c"] = "n-n|singular",
	["10c"] = "n-n|plural",
	["11c"] = "u-n|singular",
	["15c"] = "ku",
	["16c"] = "pa",
	["18c"] = "mu",
}
setDefault(output_subj_accel, "")

local addition_accel = {
	["3s"] = "m-wa|singular",
	["3p"] = "m-wa|plural",
	["10c"] = "u-n|plural",
	["15c"] = "ku-loc",
}
setDefault(addition_accel, "")

local tampol_accel = {
	["pres-p"] = "|present",
	["pres-n"] = "|present|negative",
	["perf-p"] = "|perfect",
	["gnom-p"] = "|gnomic",
	["subj-p"] = "|subjunctive",
	["subj-n"] = "|subjunctive|negative",
	["past-p"] = "|past",
	["past-n"] = "|past|negative",
	["fut-p"] = "|future",
	["fut-n"] = "|future|negative",
	["cons-p"] = "|consecutive",
	["cond_pres-p"] = "|conditional",
	["ifw-p"] = "|situational",
}
setDefault(tampol_accel, "")

local function make_accel(subj_name, tam, pol)
	output_subj = output_subj_accel[subj_name]
	output_subj = output_subj ~= "" and output_subj or subj_name
	addition = addition_accel[subj_name]
	tampol = tampol_accel[tam .. "-" .. pol]
	accel_keywords = nil
	if tampol ~= "" then
		accel_keywords = "verb:|" .. output_subj .. tampol
		if addition ~= "" then
			accel_keywords = accel_keywords .. "|;|" .. addition .. tampol
		end
	end
	return accel_keywords
end

local function get_subj(args, lemma, arabic)
	if args.subj then
		return user_specified(args.subj)
	elseif arabic then
		return lemma
	elseif lemma == "wako" or lemma == "wapo" or lemma == "wamo" then
		return "we"
	elseif lemma == "wa na" then
		return "we na"
	else
		return table.concat { get_stem(lemma, args), 'e' }
	end
end -- some

local function get_neg(args, lemma, arabic)
	if args.neg then
		return user_specified(args.neg)
	elseif arabic then
		return lemma
	else
		return table.concat { get_stem(lemma, args), 'i' }
	end
end -- somi

local function modfix_before_stem(affix, stem)
	if string.match(string.sub(affix, -1), "m") and string.match(string.sub(stem, 1, 1), "[aeio]") then
		affix = affix .. "w"
	end
	if string.match(string.sub(affix, -1), "m") and string.match(string.sub(stem, 1, 1), "[uw]") then
		affix = affix .. "u"
	end
	return affix
end -- subject or object prefix in case it goes right in front of the stem etc.

local function get_inf_stem(lemma, monosyllabic)
	if monosyllabic then
		return "ku" .. lemma
	elseif irreg_kw_inf[lemma] then
		return "kw" .. lemma
	else
		return lemma
	end
end -- soma / kula

local function make_forms(args, lemma, stem, arabic, monosyllabic)
	local forms = {}
	local loc_suf = ""
	local is_loc = false

	if lemma == "wa" or lemma == "wako" or lemma == "wapo" or lemma == "wamo" then
		args.intr = "yes"
	end
	if lemma == "wako" or lemma == "wapo" or lemma == "wamo" then
		loc_suf = mw.text.truncate(lemma, -2, "")
		is_loc = true
	end

	forms.ip = lemma -- soma

	forms.subj = "-" .. link(get_subj(args, lemma, arabic) .. loc_suf) -- -some
	if lemma == "wa na" then
		forms.subj = "-" .. link("we") .. " na"
	end

	forms.neg = "-" .. link(get_neg(args, lemma, arabic)) -- -somi
	if is_loc then
		forms.neg = "-" .. link(loc_suf)
	end
	if lemma == "wa na" then
		forms.neg = "-" .. link("na")
	end

	for person, infix in pairs(objects) do
		term = "-" .. infix .. "-"
		actualfix = modfix_before_stem(infix, lemma)
		forms["obj_" .. person] = m_links.full_link({ lang = lang, term = term, alt = actualfix, allowSelfLink = false })
	end -- -ki- etc.

	for person, infix in pairs(objects) do
		term = "-" .. infix .. "-"
		actualfix = modfix_before_stem(infix, lemma)
		eniform = get_subj(args, lemma, arabic) .. "ni"
		forms["obj_" .. person .. "_ip"] = "-" ..
			m_links.full_link({ lang = lang, term = term, alt = actualfix, allowSelfLink = false }) .. lemma
		if person == "2p" then
			forms.obj_2p_ip = forms.obj_2p_ip ..
				"/" ..
				"-" ..
				m_links.full_link({ lang = lang, term = "-ku-", alt = "ku", allowSelfLink = false }) ..
				eniform ..
				"/" ..
				"-" .. m_links.full_link({ lang = lang, term = term, alt = actualfix, allowSelfLink = false }) .. eniform
		end
	end -- -kisoma etc.
	if lemma == "wa na" then
		for person, suffix in pairs(oref) do
			local na_obj = "na" .. suffix
			forms["obj_" .. person .. "_ip"] = link(na_obj)
		end
		forms.obj_1s_ip = link("nami") .. "/na " .. link("mimi")
		forms.obj_2s_ip = link("nawe") .. "/na " .. link("wewe")
		forms.obj_3s_ip = link("naye") .. "/na " .. link("yeye")
		forms.obj_1p_ip = link("nasi") .. "/na " .. link("sisi")
		forms.obj_2p_ip = link("nanyi") .. "/na " .. link("ninyi")
		forms.obj_3p_ip = link("nao") .. "/na " .. link("wao")
	end

	for person, infix in pairs(objects) do
		term = "-" .. infix .. "-"
		actualfix = modfix_before_stem(infix, lemma)
		forms["obj_" .. person .. "_subj"] = "-" ..
			m_links.full_link({ lang = lang, term = term, alt = actualfix, allowSelfLink = false }) ..
			get_subj(args, lemma, arabic)
	end -- -kisome etc.

	for person, infix in pairs(objects) do
		term = "-" .. infix .. "-"
		actualfix = modfix_before_stem(infix, lemma)
		forms["obj_" .. person .. "_neg"] = "-" ..
			m_links.full_link({ lang = lang, term = term, alt = actualfix, allowSelfLink = false }) ..
			get_neg(args, lemma, arabic)
	end -- -kisomi etc.

	if lemma == "wa" or lemma == "wako" or lemma == "wapo" or lemma == "wamo" or lemma == "wa na" then
		oref_gen_stem = "li"
	else
		oref_gen_stem = lemma
	end
	if lemma == "wa na" then
		for class, suffix in pairs(oref) do
			term = "-" .. suffix
			forms["oref_gen_" .. class] = "-" ..
				oref_gen_stem ..
				m_links.full_link({ lang = lang, term = term, alt = suffix, allowSelfLink = false }) .. " na"
		end
	else
		for class, suffix in pairs(oref) do
			term = "-" .. suffix
			forms["oref_gen_" .. class] = "-" ..
				oref_gen_stem ..
				m_links.full_link({ lang = lang, term = term, alt = suffix, allowSelfLink = false }) .. loc_suf
		end -- -soma[[cho]] etc.
	end

	if lemma == "wa" or lemma == "wako" or lemma == "wapo" or lemma == "wamo" then
		for person, prefix in pairs(subjects.p) do
			suffix = oref[person]
			sufterm = "-" .. suffix
			forms["oref_n_" .. person] = "-" ..
				"si" .. m_links.full_link({ lang = lang, term = sufterm, alt = suffix, allowSelfLink = false }) ..
				loc_suf
		end -- si[[ye]] etc.
	end
	if lemma == "wa na" then
		for person, prefix in pairs(subjects.p) do
			suffix = oref[person]
			sufterm = "-" .. suffix
			forms["oref_n_" .. person] = "-" ..
				"si" .. m_links.full_link({ lang = lang, term = sufterm, alt = suffix, allowSelfLink = false }) ..
				" na"
		end
	end

	if is_loc then
		forms.oref_other_stem = get_inf_stem(lemma, true) .. "/-kuwa"
	else
		forms.oref_other_stem = get_inf_stem(lemma, monosyllabic)
	end

	for class, infix in pairs(oref) do
		term = "-" .. infix .. "-"
		if is_loc then
			forms["oref_other_" .. class] = "-" ..
				m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) ..
				get_inf_stem(lemma, true) ..
				"/-" .. m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) .. "kuwa"
		else
			forms["oref_other_" .. class] = "-" ..
				m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) ..
				get_inf_stem(lemma, monosyllabic)
		end
	end -- -[[cho]]soma etc.

	local inf, inf_stem = table.concat { 'ku', lemma }, table.concat { 'ku', stem }
	if args.inf then
		forms.inf = user_specified(args.inf)
	elseif irreg_kw_inf[lemma] then
		inf, inf_stem = table.concat { 'kw', lemma }, table.concat { 'kw', stem }
		forms.inf = link(inf)
	elseif lemma == "wa na" then
		forms.inf = link("kuwa") .. " na"
	else
		forms.inf = link(inf)
	end -- kusoma

	if args.inf_n then
		forms.inf_n = user_specified(args.inf_n)
	elseif monosyllabic or irreg_kw_inf[lemma] then
		forms.inf_n = link(table.concat { 'kuto', inf })
	elseif lemma == "wa na" then
		forms.inf_n = link(kutokuwa) .. " na"
	else
		forms.inf_n = link(table.concat { 'kuto', lemma })
	end -- kutosoma

	if args.hab then
		forms.hab = user_specified(args.hab)
	elseif is_loc then
		forms.hab = link("hu" .. lemma) .. "/" .. link("huwa")
	elseif lemma == "wa na" then
		forms.hab = link("huwa") .. " na"
	else
		forms.hab = link(table.concat { 'hu', lemma })
	end -- husoma

	if args.imp_s then
		forms.imp_s = user_specified(args.imp_s)
	elseif lemma == "wa na" then
		forms.imp_s = link("kuwa") .. " na"
	elseif irreg_imp_s[lemma] ~= nil then
		forms.imp_s = link(irreg_imp_s[lemma])
	elseif arabic then
		forms.imp_s = link(lemma)
	elseif monosyllabic or irreg_kw_inf[lemma] then
		forms.imp_s = link(inf)
	else
		forms.imp_s = link(lemma)
	end -- soma

	if args.imp_p then
		forms.imp_p = user_specified(args.imp_p)
	elseif lemma == "wa na" then
		forms.imp_p = link("kuweni") .. " na"
	elseif irreg_imp_p[lemma] ~= nil then
		forms.imp_p = link(irreg_imp_p[lemma])
	elseif arabic then
		forms.imp_p = link(table.concat { lemma, 'ni' })
	elseif monosyllabic or irreg_kw_inf[lemma] then
		forms.imp_p = link(table.concat { inf_stem, 'eni' })
	else
		forms.imp_p = link(table.concat { stem, 'eni' })
	end -- someni

	forms.title = table.concat { "''-", lemma, "''" } -- ''-soma''

	if is_loc then
		forms.tele = link("ka" .. lemma) .. "/" .. link("kawa")
	elseif lemma == "wa na" then
		forms.tele = link("kawa") .. " na"
	else
		forms.tele = link(table.concat { 'ka', lemma }) -- kasoma
	end

	for tam, infix in pairs(ind_tami) do
		term = "-" .. infix .. "-"
		if is_loc then
			forms[tam] = "-" ..
				m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) ..
				lemma ..
				"/-" .. m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) .. "wa"
		else
			forms[tam] = "-" ..
				m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) .. lemma
		end
	end -- -[[ku]]soma etc.

	for tam, infix in pairs(inf_tami) do
		term = "-" .. infix .. "-"
		if is_loc then
			forms[tam] = "-" ..
				m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) ..
				get_inf_stem(lemma, true) ..
				"/-" .. m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) .. "kuwa"
		else
			forms[tam] = "-" ..
				m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) ..
				get_inf_stem(lemma, monosyllabic)
		end
	end -- -[[na]]soma etc.
	if is_loc then
		forms.pres_p = "-" .. link(loc_suf)
	end
	if lemma == "wa na" then
		forms.pres_p = "-" .. link("na")
	end

	for tam, infix in pairs(subj_tami) do
		term = "-" .. infix .. "-"
		forms[tam] = "-" ..
			m_links.full_link({ lang = lang, term = term, alt = infix, allowSelfLink = false }) ..
			get_subj(args, lemma, arabic) .. loc_suf
	end -- -[[si]]some etc.

	if is_loc then
		for person, prefix in pairs(subjects.p) do
			if prefix == "a" then prefix = "yu" end
			term = prefix .. "-"
			forms["pres_p_" .. person] = m_links.full_link({
					lang = lang,
					term = term,
					alt = prefix,
					allowSelfLink = false
				}) .. loc_suf
		end
	elseif lemma == "wa na" then
		for person, prefix in pairs(subjects.p) do
			term = prefix .. "na"
			forms["pres_p_" .. person] = link(term)
		end
	else
		for person, prefix in pairs(subjects.p) do
			term = prefix .. "-"
			forms["pres_p_" .. person] = m_links.full_link({
					lang = lang,
					term = term,
					alt = prefix,
					allowSelfLink = false
				}) .. "na" .. get_inf_stem(lemma, monosyllabic)
			if person == "1s" then
				forms["pres_p_1s"] = forms["pres_p_1s"] ..
					"/" ..
					m_links.full_link({ lang = lang, term = "na-", alt = "na", allowSelfLink = false }) ..
					get_inf_stem(lemma, monosyllabic)
			end
		end
	end -- [[ni]]nasoma etc.

	if is_loc then
		for person, prefix in pairs(subjects.n) do
			if prefix == "ha" then prefix = "hayu" end
			term = prefix .. "-"
			forms["pres_n_" .. person] = m_links.full_link({
					lang = lang,
					term = term,
					alt = prefix,
					allowSelfLink = false
				}) .. loc_suf
		end
	elseif lemma == "wa na" then
		for person, prefix in pairs(subjects.n) do
			term = prefix .. "na"
			forms["pres_n_" .. person] = link(term)
		end
	else
		for person, prefix in pairs(subjects.n) do
			term = prefix .. "-"
			actualprefix = modfix_before_stem(prefix, lemma)
			forms["pres_n_" .. person] = m_links.full_link({
					lang = lang,
					term = term,
					alt = actualprefix,
					allowSelfLink = false
				}) .. get_neg(args, lemma, arabic)
		end -- [[si]]somi etc.
	end

	for person, prefix in pairs(subjects.p) do
		term = prefix .. "-"
		actualprefix = modfix_before_stem(prefix, lemma)
		forms["subj_p_" .. person] = m_links.full_link({
				lang = lang,
				term = term,
				alt = actualprefix,
				allowSelfLink = false
			}) .. get_subj(args, lemma, arabic) .. loc_suf
	end -- [[ni]]some etc.
	if lemma == "enda" then
		forms["subj_p_1p"] = m_links.full_link({ lang = lang, term = "tu-", alt = "tw", allowSelfLink = false }) ..
			"ende/" .. forms["subj_p_1p"]
	end

	for person, sprefix in pairs(subjects.cont) do
		actualprefix = sprefix .. "a"
		term = sprefix .. "a-"
		forms["gnom_" .. person] = m_links.full_link({
				lang = lang,
				term = term,
				alt = actualprefix,
				allowSelfLink = false
			}) .. lemma
	end -- [[twa]]soma etc.

	return forms
end

function export.show(frame)
	if
		mw.title.getCurrentTitle().nsText == "Template" and
		tablelength(frame:getParent().args) == 0
	then
		return frame:expandTemplate { title = 'Template:sw-conj/table-trans', args = {} }
	end

	local args = frame:getParent().args or {}

	local lemma = args[1] or mw.title.getCurrentTitle().text or ''
	local stem, arabic, monosyllabic, cat = get_stem(lemma, args)

	if obligatory_obj[lemma] then
		return frame:expandTemplate {
				title = 'Template:sw-conj/table-oblobj',
				args = make_forms(args, lemma, stem, arabic, monosyllabic)
			} .. m_utils.format_categories(cat, lang)
	elseif lemma == "wa" then
		return frame:expandTemplate {
				title = 'Template:sw-conj/table-wa',
				args = make_forms(args, lemma, stem, false, true)
			} .. m_utils.format_categories(cat, lang)
	elseif lemma == "wa na" then
		return frame:expandTemplate {
				title = 'Template:sw-conj/table-wa-na',
				args = make_forms(args, lemma, "wa", false, true)
			} .. m_utils.format_categories(cat, lang)
	elseif lemma == "wako" or lemma == "wapo" or lemma == "wamo" then
		return frame:expandTemplate {
				title = 'Template:sw-conj/table-loc',
				args = make_forms(args, lemma, "wa", false, true)
			} .. m_utils.format_categories(cat, lang)
	elseif args["intr"] then
		return frame:expandTemplate {
				title = 'Template:sw-conj/table-intrans',
				args = make_forms(args, lemma, stem, arabic, monosyllabic)
			} .. m_utils.format_categories(cat, lang)
	else
		return frame:expandTemplate {
				title = 'Template:sw-conj/table-trans',
				args = make_forms(args, lemma, stem, arabic, monosyllabic)
			} .. m_utils.format_categories(cat, lang)
	end
end

return export