local m_com = require("Module:ca-common")

local export = {}
local pos_functions = {}

local lang = require("Module:languages").getByCode("ca")
local PAGENAME = mw.title.getCurrentTitle().text

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
	local poscat = frame.args[1] or error("Part of speech has not been specified. Please pass parameter 1 to the module invocation.")
	-- หมวดหมู่เป็นภาษาไทย
	local poscat_th = require("Module:utilities").translate_term(poscat)

	local params = {
		["head"] = {list = true},
		["suff"] = {type = "boolean"},
	}
	
	if pos_functions[poscat_th] then
		for key, val in pairs(pos_functions[poscat_th].params) do
			params[key] = val
		end
	end
	
	local args = require("Module:parameters").process(frame:getParent().args, params)
	local data = {lang = lang, pos_category = poscat_th, categories = {}, heads = args["head"], genders = {}, inflections = {}, categories = {}}
	
	if args["suff"] then
		data.pos_category = "ปัจจัย"
		
		if poscat_th == "คำคุณศัพท์" then
			table.insert(data.categories, "ปัจจัยผันคำคุณศัพท์ภาษากาตาลา")
		elseif poscat_th == "คำกริยาวิเศษณ์" then
			table.insert(data.categories, "ปัจจัยผันคำกริยาวิเศษณ์ภาษากาตาลา")
		elseif poscat_th == "คำนาม" then
			table.insert(data.categories, "ปัจจัยผันคำนามภาษากาตาลา")
		elseif poscat_th == "คำกริยา" then
			table.insert(data.categories, "ปัจจัยผันคำกริยาภาษากาตาลา")
		else
			error("No category exists for suffixes forming " .. poscat_th .. ".")
		end
	end
	
	if pos_functions[poscat_th] then
		pos_functions[poscat_th].func(args, data)
	end
	
	return require("Module:headword").full_headword(data)
end

local function make_feminine(base)
	-- final vowel -> -a
	if base:find("a$") then return base end
	if base:find("o$") then return (base:gsub("o$", "a")) end	
	if base:find("e$") then return m_com.front_to_back(base:gsub("e$", "")) .. "a" end
	
	-- -u -> -va
	if base:find("[aeiou]u$") then return (base:gsub("u$", "v") .. "a") end
	
	-- accented vowel -> -na
	if mw.ustring.find(base, "[àèéíòóú]$") then return m_com.remove_accents(base) .. "na" end
	
	-- accented vowel + -s -> -sa
	if mw.ustring.find(base, "[àèéíòóú]s$") then return m_com.remove_accents(base) .. "a" end
	
	return base .. "a"
end

local function make_plural(base, gender)
	-- a -> es
	if base:find("a$") then return m_com.back_to_front(base:gsub("a$", "")) .. "es", nil end
	
	-- accented vowel -> -ns
	if mw.ustring.find(base, "[àèéíòóú]$") then
		return m_com.remove_accents(base) .. "ns", nil
	end
	
	if gender == "m" then
		if mw.ustring.find(base, "[àèéíòóú]s$") then
			return m_com.remove_accents(base) .. "os", nil
		end
		
		if base:find("s$") or base:find("ç$") or base:find("x$") or base:find("z$") then
			return base .. "os", nil
		end
		
		if base:find("sc$") or base:find("st$") or base:find("xt$") then
			return base .. "s", base .. "os"
		end
	end
	
	if gender == "f" then
		if base:find("s$") then return base end
		if base:find("sc$") or base:find("st$") or base:find("xt$") then return base .. "s", base .. "es" end
	end
	
	return base .. "s", nil
end

-- Display additional inflection information for an adjective
pos_functions["คำคุณศัพท์"] = {
	params = {
		[1] = {},
		["pl"] = {},
		["pl2"] = {},
		},
	func = function(args, data)
		local feminine = args[1]
		local masculine_plural
		local masculine_plural2
		local feminine_plural
		
		-- Indeclinable/invariable adjectives
		if feminine == "ind" or feminine == "inv" then
			table.insert(data.categories, "Catalan indeclinable adjectives")
			table.insert(data.inflections, {label = "indeclinable"})
		else
			-- Adjectives with identical forms in the masculine and feminine singular
			if feminine == "mf" then
				feminine = PAGENAME
				table.insert(data.categories, "Catalan epicene adjectives")
				
				-- Adjectives ending in -ç or -x behave as mf-type in the singular, but
				-- regular type in the plural.
				if PAGENAME:find("[çx]$") then
					masculine_plural = make_plural(PAGENAME, "m")
					feminine_plural = make_plural(PAGENAME .. "a", "f")
				else
					masculine_plural = make_plural(PAGENAME, "m")
					feminine_plural = masculine_plural
				end
				
				-- Has anyone provided forms to override the defaults?
				masculine_plural = args["pl"] or masculine_plural
				feminine_plural = args["pl"] or feminine_plural
				masculine_plural2 = args["pl2"] or masculine_plural2
			-- Adjectives with distinct masculine and feminine singular forms
			-- (the majority)
			else
				feminine = feminine or make_feminine(PAGENAME)
				feminine_plural = make_plural(feminine, "f")
				
				-- If the feminine ends in -ssa, assume that the -ss- is also in the
				-- masculine plural form
				if feminine:find("ssa$") then
					masculine_plural = feminine:gsub("a$", "os")
				elseif feminine == PAGENAME .. "na" then
					masculine_plural = PAGENAME .. "ns"
				-- Adjectives in -ig have two masculine plural forms, one derived from
				-- the m.sg. and the other derived from the f.sg.
				elseif PAGENAME:find("ig$") then
					masculine_plural = PAGENAME .. "s"
					masculine_plural2 = feminine:gsub("ja$", "jos")
				else
					masculine_plural, masculine_plural2 = make_plural(PAGENAME, "m")
				end
				
				-- Has anyone provided forms to override the defaults?
				masculine_plural = args["pl"] or masculine_plural
				masculine_plural2 = args["pl2"] or masculine_plural2
			end
			
			-- Display the forms.
			-- If masculine and feminine are identical, show m,f as the gender and
			-- leave out the feminine.
			if feminine ~= PAGENAME then
				table.insert(data.inflections, {label = "เพศหญิง", accel = {form = "f|s"}, feminine})
			end
			
			-- If the plurals are identical, show only one form as well.
			if masculine_plural == feminine_plural then
				local infl_parts = {label = "เพศชายและเพศหญิงพหูพจน์", accel = {form = "p"}}
				table.insert(infl_parts, masculine_plural)
				
				if masculine_plural2 then
					table.insert(infl_parts, masculine_plural2)
				end
				
				table.insert(data.inflections, infl_parts)
			else
				local infl_parts = {label = "เพศชายพหูพจน์", accel = {form = "m|p"}}
				table.insert(infl_parts, masculine_plural)
				
				if masculine_plural2 then
					table.insert(infl_parts, masculine_plural2)
				end
				
				table.insert(data.inflections, infl_parts)
				table.insert(data.inflections, {label = "เพศหญิงพหูพจน์", accel = {form = "f|p"}, feminine_plural})
			end
			
			-- Check for missing forms
			if feminine and not mw.title.new(feminine).exists or
				masculine_plural and not mw.title.new(masculine_plural).exists or
				masculine_plural2 and not mw.title.new(masculine_plural2).exists or
				feminine_plural and not mw.title.new(feminine_plural).exists then
				table.insert(data.categories, "Catalan adjectives with red links in their headword lines")
			end
		end
	end
}

pos_functions["คำลักษณนาม"] = pos_functions["คำคุณศัพท์"]
pos_functions["คำสรรพนาม"] = pos_functions["คำคุณศัพท์"]

-- Display information for a noun's gender
-- This is separate so that it can also be used for proper nouns
local function noun_gender(args, data)
	local gender = args[1]
	
	table.insert(data.genders, gender)

	if #data.genders == 0 then
		table.insert(data.genders, "?")
	end
	
	-- Is this a noun with an unexpected ending (for its gender)?
	-- Only check if the term is one word (there are no spaces in the term).
	if not PAGENAME:find(" ") then
		if PAGENAME:find("a$") and (data.genders[1] == "m") then
			table.insert(data.categories, "คำนามเพศชายภาษากาตาลาที่ลงท้ายด้วย -a")
		elseif not (PAGENAME:find("a$") or PAGENAME:find("ió$") or PAGENAME:find("tat$") or PAGENAME:find("tud$") or PAGENAME:find("[dt]riu$")) and data.genders[1] == "f" then
			table.insert(data.categories, "คำนามเพศหญิงภาษากาตาลาที่ไม่ลงท้ายด้วยเพศหญิง")
		end
	end
end

pos_functions["คำวิสามานยนาม"] = {
	params = {
		[1] = {},
		["g2"] = {},
		},
	func = function(args, data)
		noun_gender(args, data)
	end
}

-- Display additional inflection information for a noun
pos_functions["คำนาม"] = {
	params = {
		[1] = {},
		[2] = {},
		["pl2"] = {},
		["f"] = {},
		["m"] = {},
		},
	func = function(args, data)
		noun_gender(args, data)
		
		-- Plural
		if data.genders[1]:find("%-p$") then
			table.insert(data.inflections, {label = "พหูพจน์เท่านั้น"})
		else
			local plural = args[2]
			
			if plural == "-" then
				table.insert(data.inflections, {label = "นับไม่ได้"})
				table.insert(data.categories, "คำนามนับไม่ได้ภาษากาตาลา")
			else
				local infl_parts = {label = "พหูพจน์", accel = {form = "p"}}
				local plural2 = args["pl2"]
				
				if not plural then
					local p, p2 = make_plural(PAGENAME, data.genders[1])
					plural = p
					plural2 = plural2 or p2
				end
				
				table.insert(infl_parts, plural)
				
				if plural2 then
					table.insert(infl_parts, plural2)
					if not mw.title.new(plural2).exists then
						table.insert(data.categories, "คำนามภาษากาตาลาที่ขาดพหูพจน์")
					end
				end
				if plural and not mw.title.new(plural).exists then
					table.insert(data.categories, "คำนามภาษากาตาลาที่ขาดพหูพจน์")
				end
				table.insert(data.inflections, infl_parts)
			end
		end
		
		-- Gendered forms
		local feminine = args["f"]
		local masculine = args["m"]
		
		if feminine then
			table.insert(data.inflections, {label = "เพศหญิง", feminine})
		end
		
		if masculine then
			table.insert(data.inflections, {label = "เพศชาย", masculine})
		end
	end
}

-- Display additional inflection information for a verb
pos_functions["คำกริยา"] = {
	params = {
		["pres_1_sg"] = {},
		["past_part"] = {},
		},
	func = function(args, data)
		-- Does this verb end in a recognised verb ending (possibly reflexive)?
		if not PAGENAME:find(" ") and (PAGENAME:find("re?$") or PAGENAME:find("r%-se$") or PAGENAME:find("re's$")) then
			local base = PAGENAME:gsub("r%-se$", "r"):gsub("re's$", "re")
			local pres_1_sg
			local past_part
			
			-- Generate inflected forms.
			-- The 2nd conjugation is generally irregular
			-- so generate nothing for that, explicit parameters are required.
			
			-- 1st conjugation
			if base:find("ar$") then
				local stem = base:gsub("ar$", "")
				pres_1_sg = stem .. "o"
				past_part = stem .. "at"
			-- 3rd conjugation (except -tenir/-venir)
			elseif base:find("ir$") and not base:find("[tv]enir$") then
				local stem = base:gsub("ir$", "")
				pres_1_sg = stem .. "eixo"
				
				if stem:find("[aeiou]$") and not stem:find("[gq]u$") then
					past_part = stem .. "ït"
				else
					past_part = stem .. "it"
				end
			end
			
			-- Overridden forms
			pres_1_sg = {label = "first-person singular present", request = true, args["pres_1_sg"] or pres_1_sg}
			past_part = {label = "past participle", request = true, args["past_part"] or past_part}
			
			table.insert(data.inflections, pres_1_sg)
			table.insert(data.inflections, past_part)
		end
	end
}

-- Display additional inflection information for a numeral
pos_functions["เลข"] = {
	params = {
		[1] = {},
		[2] = {},
		},
	func = function(args, data)
		local feminine = args[1]
		local noun_form = args[2]
		
		if feminine then
			table.insert(data.genders, "m")
			table.insert(data.inflections, {label = "เพศหญิง", feminine})
			
			if noun_form then
				table.insert(data.inflections, {label = "รูปผันคำนาม", noun_form})
			end
		else
			table.insert(data.genders, "m")
			table.insert(data.genders, "f")
		end
	end
}

return export