local strutils = require("Module:string utilities")
local com = require("Module:yi-common")
local links = require("Module:links")

local export = {}

local lang = require("Module:languages").getByCode("yi")

local form_names_and_suffixes = {
	["pred"] = true,
	["er"] = true,
	["n"] = true,
	["e"] = true,
	["s"] = true,
}

local function make_link_form(text, tr)
	return (
		links.full_link({lang = lang, term = text, tr = "-"}) ..
		"<br/><small>" .. tr .. "</small>"
	)
end

local function process_forms(forms)
	for n, _ in pairs(form_names_and_suffixes) do
		if forms[n] == "-" then
			forms[n] = "—"
		else
			forms[n] = make_link_form(
				"[[" .. forms[n].text .. "]]",
				com.translit(forms[n])
			)
		end
	end
end

local function generate_forms(args, hint, SUBPAGENAME)
	local forms = {}

	local pred = com.form(SUBPAGENAME, args["tr"])

	local schwa = args[1] == "*" and com.ends_in(pred, "e")

	local stem = nil
	if schwa then
		stem = com.form(mw.ustring.gsub(SUBPAGENAME, "ע$", ""), args["stemtr"] or args["tr"] and mw.ustring.gsub(args["tr"], "e$", ""))
	elseif args[1] == "*" and (com.ends_in(pred, "n") or com.ends_in(pred, "l")) then
		stem = com.form(mw.ustring.gsub(SUBPAGENAME, "([לנן])$", "ע%1"), args["stemtr"] or args["tr"] and mw.ustring.gsub(args["tr"], "([ln])$", "e%1"))
	else
		stem = com.form(args[1] or SUBPAGENAME, args["stemtr"] or args["tr"])
	end

	forms["pred"] = pred

	if args["er"] then
		forms["er"] = com.form(args["er"], args["ertr"])
	elseif schwa then
		forms["er"] = com.suffix(pred, "ר")
	else
		forms["er"] = com.suffix(stem, "ער")
	end

	if args["n"] then
		forms["n"] = com.form(args["n"], args["ntr"])
	elseif schwa then
		forms["n"] = com.suffix(com.ends_nasal(stem) and pred or stem, "ן")
	elseif com.ends_in(stem, "n") then
		forms["n"] = com.suffix(stem, "עם")
	elseif com.ends_in(stem, "m") or com.ends_vowel(stem) then
		forms["n"] = com.suffix(stem, "ען")
	else
		forms["n"] = com.suffix(stem, "ן")
	end

	if args["e"] then
		forms["e"] = com.form(args["e"], args["etr"])
	elseif schwa then
		forms["e"] = pred
	else
		forms["e"] = com.suffix(stem, "ע")
	end

	if args["s"] then
		forms["s"] = com.form(args["s"], args["str"])
	elseif com.ends_in(pred, "s") then
		forms["s"] = pred
	elseif (not schwa) and com.ends_vowel(pred) then
		forms["s"] = com.suffix(pred, "ס") -- should this be "עס"?
	else
		forms["s"] = com.suffix(pred, "ס")
	end

	return forms
end

local template = {}

local function do_generate_forms(frame)
	local args = {}
	for k, v in pairs(frame:getParent().args) do
		if v ~= "" then
			args[k] = v
		end
	end

	local decltype = frame.args[1] or args["decltype"] or "adjective"
	if not template[decltype] then
		error("Invalid or missing declension type '" .. decltype .. "' in module invocation.")
	end

	local hint = args["hint"] or frame.args["hint"]
	local SUBPAGENAME = frame.args["pagename"] or args[""] or args["head"] or mw.title.getCurrentTitle().subpageText

	local forms = generate_forms(args, hint, SUBPAGENAME)
	return decltype, args, forms, SUBPAGENAME
end

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.decline(frame)
	local decltype, args, forms, SUBPAGENAME = do_generate_forms(frame)

	process_forms(forms)

	forms["title"] = args["title"] or (
		"變格:" ..
		links.full_link({lang = lang, alt = SUBPAGENAME, tr = "-"})
	)
	return strutils.format(template[decltype], forms)
end

-- The entry point for 'yi-generate-adj-forms' to generate all adjective forms.
function export.generate_forms(frame)
	local decltype, args, forms, SUBPAGENAME = do_generate_forms(frame)
	local ins_text = {}
	for n, _ in pairs(form_names_and_suffixes) do
		if forms[n] == "-" then
			table.insert(ins_text, n .. "=-")
		elseif forms[n].tr then
			table.insert(ins_text, n .. "=" .. forms[n].text .. "//" .. forms[n].tr)
		else
			table.insert(ins_text, n .. "=" .. forms[n].text)
		end
	end
	table.insert(ins_text, "decltype=" .. decltype)
	return table.concat(ins_text, "|")
end

template["adjective"] = [===[
<div class="NavFrame" style="display:inline-block; min-width:56em">
<div class="NavHead" style="background:#ccccff">{title}</div>
<div class="NavContent">
{\op}| style="border:1px solid #ccccff; text-align:center; width:100%" class="inflection-table" cellspacing="1" cellpadding="3"
|- style="background:#f2f2ff"
! colspan="5" style="background:#ccccff" | 表語
| colspan="2" | {pred}
|- style="background:#f2f2ff"
! colspan="7" style="background:#ccccff; height:0.25em" |
|- style="background:#f2f2ff"
! rowspan="2" style="background:#ccccff; width:16%" | 格
! rowspan="2" style="background:#ccccff; width:16%" | 陽性
! colspan="3" style="background:#ccccff" | 中性
! rowspan="2" style="background:#ccccff; width:16%" | 陰性
! rowspan="2" style="background:#ccccff; width:16%" | 複數
|- style="background:#f2f2ff"
! style="background:#ccccff; width:12%" | 不定
! style="background:#ccccff; width:12%" | 定
! style="background:#ccccff; width:12%" | 後置/名詞化
|- style="background:#f2f2ff"
! style="background:#ccccff" | 主格
| {er}
| rowspan="3" | {pred}
| rowspan="2" | {e}
| rowspan="2" | {s}
| rowspan="2" | {e}
| rowspan="3" | {e}
|- style="background:#f2f2ff"
! style="background:#ccccff" | 賓格
| rowspan="2" | {n}
|- style="background:#f2f2ff"
! style="background:#ccccff" | 與格
| colspan="2" | {n}
| {er}
|{\cl}</div></div>]===]

template["possessive"] = [===[
<div class="NavFrame" style="display:inline-block; min-width:48em">
<div class="NavHead" style="background:#ccccff">{title}</div>
<div class="NavContent">
{\op}| style="border:1px solid #ccccff; text-align:center; width:100%" class="inflection-table" cellspacing="1" cellpadding="3"
|- style="background:#f2f2ff"
! colspan="5" style="background:#ccccff" | 前置
|- style="background:#f2f2ff"
! style="background:#ccccff; width:20%" | 格
! style="background:#ccccff; width:20%" | 陽性
! style="background:#ccccff; width:20%" | 中性
! style="background:#ccccff; width:20%" | 陰性
! style="background:#ccccff; width:20%" | 複數
|- style="background:#f2f2ff"
! style="background:#ccccff" | 主格
| rowspan="3" colspan="3" | {pred}
| rowspan="3" | {e}
|- style="background:#f2f2ff"
! style="background:#ccccff" | 賓格
|- style="background:#f2f2ff"
! style="background:#ccccff" | 與格
|- style="background:#f2f2ff"
! colspan="5" style="background:#ccccff; height:0.25em" |
|- style="background:#f2f2ff"
! colspan="5" style="background:#ccccff" | 後置或名詞化
|- style="background:#f2f2ff"
! style="background:#ccccff; width:20%" | 格
! style="background:#ccccff; width:20%" | 陽性
! style="background:#ccccff; width:20%" | 中性
! style="background:#ccccff; width:20%" | 陰性
! style="background:#ccccff; width:20%" | 複數
|- style="background:#f2f2ff"
! style="background:#ccccff" | 主格
| {er}
| rowspan="2" | {s}
| rowspan="2" | {e}
| rowspan="3" | {e}
|- style="background:#f2f2ff"
! style="background:#ccccff" | 賓格
| rowspan="2" | {n}
|- style="background:#f2f2ff"
! style="background:#ccccff" | 與格
| {n}
| {er}
|{\cl}</div></div>]===]

return export