local p = {}

-- Forma femenina d'un mot
local function forma_fem(mot, exc_fem)
	local exc = exc_fem[mot]
	if exc then return exc end
	
	local fem = mot
	fem = mw.ustring.gsub(fem, "à$", "ana")
	if string.find(mot, "e$") and not string.find(mot, "ble$") then
		fem = string.gsub(fem, "gue$", "ga")
		fem = string.gsub(fem, "e$", "a")
	end
	fem = mw.ustring.gsub(fem, "[èé]$", "ena")
	fem = mw.ustring.gsub(fem, "([^gq][aeou])í$", "%1ïna")
	fem = mw.ustring.gsub(fem, "í$", "ina")
	fem = mw.ustring.gsub(fem, "a(%l)i$", "à%1ia")
	fem = mw.ustring.gsub(fem, "i(%l)i$", "í%1ia")
	fem = string.gsub(fem, "o$", "a")
	fem = mw.ustring.gsub(fem, "[òó]$", "ona")
	fem = string.gsub(fem, "([aio])u$", "%1va")
	fem = string.gsub(fem, "eu$", "ea")
	fem = mw.ustring.gsub(fem, "ú$", "una")
	fem = string.gsub(fem, "leg$", "loga")
	fem = string.gsub(fem, "oig$", "oja")
	fem = string.gsub(fem, "ogen$", "ògena")
	fem = mw.ustring.gsub(fem, "[aà]s$", "assa")
	fem = mw.ustring.gsub(fem, "ès$", "esa")
	fem = mw.ustring.gsub(fem, "és$", "essa")
	fem = mw.ustring.gsub(fem, "ís$", "issa")
	fem = mw.ustring.gsub(fem, "[oò]s$", "ossa")
	fem = mw.ustring.gsub(fem, "ós$", "osa")
	fem = mw.ustring.gsub(fem, "ús$", "usa")
	fem = mw.ustring.gsub(fem, "([aiïu])t$", "%1da")
    if fem == mot then
		local no_fem = false
		if string.find(mot, "a$") then
			no_fem = true
		elseif string.find(mot, "ble$") then
			no_fem = true
		elseif string.find(mot, "ei$") then
			no_fem = true
			if mot == "rei" or mot == "virrei" then
				fem = mot .. "na"
			end
		elseif string.find(mot, "[cinsv][ai]l$")  and mot ~= "col·legial" and mot ~= "oficial" then
			no_fem = true
		elseif string.find(mot, "del$") then
			no_fem = true
		elseif string.find(mot, "mim$") then
			no_fem = true
		elseif string.find(mot, "ar$") then
			no_fem = true
		elseif string.find(mot, "es$") then
			no_fem = true
		elseif string.find(mot, "%a[ceptx]ant$") and mot ~= "bastant" and mot ~= "marxant" then
			no_fem = true
		elseif string.find(mot, "gent$") and mot ~= "sergent" then
			no_fem = true
		elseif string.find(mot, "ilot$") then
			no_fem = true
		end
		if no_fem == false then
			fem = mot .. "a"
		end
    end
    return fem
end

-- Forma femenina d'una locució
function p.fem(lema)
	if type(lema) == "table" then lema = lema.args[1] end -- des de plantilles via invoke o des de mòduls via require
	local exc_fem = mw.loadData("Modul:Ca-flexió/femení")
	if lema:find("[^ ]+ [^ ]+") then
		local exc = exc_fem[lema]
		if exc then return exc end
		local preposicions = {" a ", " al ", " amb ", " contra ", " de ", " d'", " del ", " dels ", " des ", " dintre ",
				" en ", " endavant", " enrere", " entre ",
				" fora ", " per ", " pel ", " pels ", " que ", " sense ", " sobre ", " sota "}
		for i, prep in ipairs(preposicions) do
			offset = mw.ustring.find(lema, prep, 1, true)
			if offset then
				local part1 = mw.ustring.sub(lema, 1, offset-1)
				local part2 = mw.ustring.sub(lema, offset)
				return p.fem(part1) .. part2 -- expressament recursiu per a locucions complexes
			end
		end
		local femenins = {}
		for part in mw.text.gsplit(lema, " ", true) do
			if string.find(part, "al$") and #femenins > 0 then -- adjectius en -al invariables
				table.insert(femenins, part)
			else
				table.insert(femenins, forma_fem(part, exc_fem))
			end
		end
		return table.concat(femenins, " ")
	else
		return forma_fem(lema, exc_fem)
	end
end

-- Plural d'un mot
local function forma_plural(mot, exc_plural)
	return mot
end

-- Forma plural d'una locució
function p.plural(lema)
	if type(lema) == "table" then lema = lema.args[1] end -- des de plantilles via invoke o des de mòduls via require
	local exc_plural = mw.loadData("Modul:Ca-flexió/plural")
	if lema:find("[^ ]+ [^ ]+") then
		local exc = exc_plural[lema]
		if exc then return exc end
		local preposicions = {" a ", " al ", " amb ", " contra ", " de ", " d'", " del ", " dels ", " des ", " dintre ",
				" en ", " endavant", " enrere", " entre ",
				" fora ", " per ", " pel ", " pels ", " sense ", " sobre ", " sota "}
		for i, prep in ipairs(preposicions) do
			offset = mw.ustring.find(lema, prep, 1, true)
			if offset then
				local part1 = mw.ustring.sub(lema, 1, offset-1)
				local part2 = mw.ustring.sub(lema, offset)
				return p.plural(part1) .. part2
			end
		end
		local plurals = {}
		for part in mw.text.gsplit(lema, " ", true) do
			table.insert(plurals, forma_plural(part, exc_plural))
		end
		return table.concat(plurals, " ")
	else
		return forma_plural(lema, exc_plural)
	end
end

-- Funció auxiliar per l’apostrofació de l’article masculí, retorna true o false
-- Limitacions: vegeu plantilla:deod'
local function sapostrofa(text)
	local apostrofa = {
		["her "]=false, ["his "]=false, -- paraules amb angles que provoquen falsos apostrofs 
		["hakk"]=false, -- h consonant (hakka)
    	["hawa"]=false, -- h consonant (hawaià)
    	["hia"]=false, ["hie"]=false, ["hio"]=false, ["hui"]=false, -- vocal consonant
    	["uix"]=true, -- excepció per u vocal
    	["ha"]=true, ["he"]=true, ["hi"]=true, ["hí"]=true, ["ho"]=true, ["hu"]=true, ["hy"]=true, -- excepte anteriors
    	["ia"]=false, ["ià"]=false, ["ie"]=false, ["io"]=false, ["iu"]=false, -- i consonant
    	["ua"]=false, ["ue"]=false, ["ui"]=false, ["uí"]=false, ["uï"]=false, ["uo"]=false, -- u consonant
    	["ya"]=false, ["ye"]=false, ["yi"]=false, ["yo"]=false, ["yu"]=false, -- y consonant
    	["a"]=true, ["à"]=true, ["e"]=true, ["è"]=true, ["é"]=true,
    	["i"]=true, ["í"]=true, ["ï"]=true, ["y"]=true,
    	["o"]=true, ["ò"]=true, ["ó"]=true, ["u"]=true, ["ú"]=true, ["ü"]=true, -- excepte anteriors
    	["1 "]=true, ["11 "]=true -- dates amb "1 de" o "11 de "
    	}

    local elText = mw.ustring.lower(require('Modul:Delink')._delink({text}))
    for i = 4, 1, -1 do
        lletres = mw.ustring.sub(elText, 1, i)
        apo = apostrofa[lletres]
        if apo ~= nil then
            return apo
        end
    end
    return false
end

function p.apostrofar(frame)
	args = frame:getParent().args
	local text = args[2] or ""
	local ret = (args[1] or "") .. " " .. text
	if sapostrofa(text) then
		local article = mw.language.getContentLanguage():lcfirst(args[1])
		if article == "el" then
			ret = "l'" .. text
		elseif article == "al" then
			ret = "a l'" .. text
		elseif article == "del" then
			ret = "de l'" .. text
		elseif article == "pel" then
			ret = "per l'" .. text
		elseif article == "cal" then
			ret = "ca l'" .. text
		elseif article == "can" then
			ret = "ca n'" .. text
		end
		if article ~= args[1] then
			ret = mw.language.getContentLanguage():ucfirst(ret)
		end
	end
	return ret
end

return p