Documentation for this module may be created at Modul:katbike/belge

local export = {}
local b = require("Modul:bingeh")


local function splitLabelLang(titleObject)
	local getByCanonicalName = require("Modul:ziman").getByCanonicalName
	local canonicalName
	local lang
	
	-- Progressively add another word to the potential canonical name until it
	-- matches an actual canonical name.
	local words = mw.text.split(titleObject.text, " ")
	for i = #words - 1, 1, -1 do
		canonicalName = table.concat(words, " ", 1, i)
		lang = getByCanonicalName(canonicalName)
		if lang then
			break
		end
	end
	
	local label = lang and titleObject.text:sub(#canonicalName + 2)
		or titleObject.text
	
	return label, lang
end


local function getObj(name, family)
	if not family then
		return require("Modul:ziman").getByCanonicalName(name)
			or require("Module:etymology languages").getByCanonicalName(name)
	else
		return require("Module:families").getByCanonicalName(name)
	end
end


-- List of handler functions that try to match the page name.
-- A handler should return a table of template title plus arguments
-- that is passed to frame:expandTemplate.
-- If a handler does not recognise the page name, it should return nil.
-- Note that the order of functions matters!

local handlers = {}

local function add_handler(func)
	table.insert(handlers, func)
end

add_handler(function(titleObject)
	
	local langName = titleObject.text:match("^(.+)")
	-- Use the entire category name if it doesn't end in "language", to handle
	-- cases where "language" is part of the name, e.g. ASL.
	local ziman = b.lcfirst(langName)
	local lang = require("Module:ziman").getByCanonicalName(ziman) or require("Module:ziman").getByCanonicalName(titleObject.text)
	
	if not lang then
		local lang2 = require("Module:ziman").getByName(langName)
		if lang2 then
			error('"' .. langName .. '" is not a valid canonical name. Use "' .. lang2:getCanonicalName() .. '" instead.')
		end
		
		return nil
	end
	
	return { title = "zimankatbike", args = { lang:getCode() } }
end)

--[[	family cat
		
		Must go after the "derived", "borrowed", and "transliterated" category handlers,
		which sometimes have "languages" at the end, but before poscatboiler,
		or families that have the same names as languages will get intercepted.
]]
add_handler(function(titleObject)
	if not titleObject.text:find("^[zZ]imanên") then
		return nil
	end
	
	local familyName = titleObject.text:match("^[zZ]imanên (.+)$")
	
	local family = require("Module:families").getByCanonicalName(familyName) or
		require("Module:families").getByCanonicalName(mw.ustring.lower(familyName))
	
	if not family then
		return nil
	end
	
	return { title = "malbatkatbike", args = { family:getCode() } }
end)

add_handler(function(titleObject)
	if not titleObject.text:find("^[zZ]imanên kreyolî yan pîdgînî li ser bingeha") then
		return nil
	end
	
	local kreyoliName = titleObject.text:match("^[zZ]imanên kreyolî yan pîdgînî li ser bingeha (.+)$")
	
	local kreyoli = b.ucfirst(kreyoliName)

	return { title = "kreyolîkatbike", args = { kreyoli } }
end)

-- [[Modul:dara kategoriyan/rehkatbike]]
add_handler(function(titleObject)
	local label, lang = splitLabelLang(titleObject)
	
		if label:find("^.+ ji rehê .") then
			local ziman, after = label:match("Peyvên (.+) ji rehê (.+)$")
			if ziman then
				lang = require("Module:ziman").getByCanonicalName(ziman) 
			end
						local term, id
			
			if after:find(". %([^()]+%)$") then
				term, id = after:match("^(.+) %(([^()]+)%)$")
			else
				term = after
			end

			return {title = "rehkatbike", args = {lang:getCode(), term, pos = pos, id = id}}
		end
end)

-- [[Modul:dara kategoriyan/qertafkatbike]]
add_handler(function(titleObject)
	local label, lang = splitLabelLang(titleObject)
	
	for _, affixtype in ipairs({"circumfix", "infix", "navgir", "pêşgir", "paşgir"}) do
		if label:find("^.+ bi " .. affixtype .. "a .") then
			local ziman, after = label:match("Peyvên (.+) bi " .. affixtype .. "a (.+)$")
			if ziman then
				lang = require("Module:ziman").getByCanonicalName(ziman) 
			end
						local term, id
			
			if after:find(". %([^()]+%)$") then
				term, id = after:match("^(.+) %(([^()]+)%)$")
			else
				term = after
			end

			return {title = affixtype .. "katbike", args = {lang:getCode(), term, pos = pos, id = id}}
		end
	end
end)

-- [[Modul:dara kategoriyan/deynkirîkatbike]]
add_handler(function(titleObject)
	local label, lang = splitLabelLang(titleObject)
	
	if not label:find("(.+) deynkirî ji .") then
		return nil
	end
	
	local navewergir, sourcename = label:match("Peyvên (.+) yên deynkirî ji (.+)$")
	local wergir
	local source

	if navewergir then
		wergir = getObj(navewergir)

		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end
	elseif not navewergir then 
		local sourcename = label:match("Peyvên deynkirî ji (.+)$")
		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end		
		
	end	

	if source then
		lang = wergir
		return {title = "deynkirîkatbike", args = {lang and lang:getCode() or nil, source:getCode()}}
	end
end)


-- [[Modul:dara kategoriyan/mîrasmayîkatbike]]
add_handler(function(titleObject)
	local label, lang = splitLabelLang(titleObject)
	
	if not label:find("(.+) mîrasmayî ji .") then
		return nil
	end
	
	local navewergir, sourcename = label:match("Peyvên (.+) yên mîrasmayî ji (.+)$")
	local wergir
	local source

	if navewergir then
		wergir = getObj(navewergir)

		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end
	elseif not navewergir then 
		local sourcename = label:match("Peyvên mîrasmayî ji (.+)$")
		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end		
		
	end	

	if source then
		lang = wergir
		return {title = "mîrasmayîkatbike", args = {lang and lang:getCode() or nil, source:getCode()}}
	end
end)


-- [[Modul:dara kategoriyan/lihevanînkatbike]]
add_handler(function(titleObject)
	local label, lang = splitLabelLang(titleObject)
	
	if not label:find("(.+) lihevanîna dengî wateyî ji .") then
		return nil
	end
	
	local navewergir, sourcename = label:match("Peyvên (.+) yên lihevanîna dengî wateyî ji (.+)$")
	local wergir
	local source

	if navewergir then
		wergir = getObj(navewergir)

		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end
	elseif not navewergir then 
		local sourcename = label:match("Peyvên lihevanîna dengî wateyî ji (.+)$")
		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end		
		
	end	

	if source then
		lang = wergir
		return {title = "lihevanînkatbike", args = {lang and lang:getCode() or nil, source:getCode()}}
	end
end)


-- [[Modul:dara kategoriyan/wergirtinkatbike]]
add_handler(function(titleObject)
	local label, lang = splitLabelLang(titleObject)
	
	if not label:find("(.+) wergirtina wateyê ji .") then
		return nil
	end
	
	local navewergir, sourcename = label:match("Peyvên (.+) yên wergirtina wateyê ji (.+)$")
	local wergir
	local source

	if navewergir then
		wergir = getObj(navewergir)

		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end
	elseif not navewergir then 
		local sourcename = label:match("Peyvên wergirtina wateyê ji (.+)$")
		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end		
		
	end	

	if source then
		lang = wergir
		return {title = "wergirtinkatbike", args = {lang and lang:getCode() or nil, source:getCode()}}
	end
end)


-- [[Modul:dara kategoriyan/yekserkatbike]]
add_handler(function(titleObject)
	local label, lang = splitLabelLang(titleObject)
	
	if not label:find("(.+) wergerandina yekser ji .") then
		return nil
	end
	
	local navewergir, sourcename = label:match("Peyvên (.+) yên wergerandina yekser ji (.+)$")
	local wergir
	local source

	if navewergir then
		wergir = getObj(navewergir)

		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end
	elseif not navewergir then 
		local sourcename = label:match("Peyvên wergerandina yekser ji (.+)$")
		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end		
		
	end	

	if source then
		lang = wergir
		return {title = "yekserkatbike", args = {lang and lang:getCode() or nil, source:getCode()}}
	end
end)


-- [[Modul:dara kategoriyan/jikatbike]]
add_handler(function(titleObject)
	local label, lang = splitLabelLang(titleObject)
	
	if not label:find("(.+) ji .") then
		return nil
	end
	
	local navewergir, sourcename = label:match("Peyvên (.+) ji (.+)$")
	local wergir
	local source

	if navewergir then
		wergir = getObj(navewergir)

		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end
	elseif not sourcename then 
		local sourcename = label:match("Peyvên ji (.+)$")
		if sourcename:find("^zimanên ") then
			sourcename = sourcename:gsub("^zimanên ", "")
			source = getObj(sourcename, true)
		else
			source = getObj(sourcename)
		end		
		
	end	

	if source then
		lang = wergir
		return {title = "jikatbike", args = {lang and lang:getCode() or nil, source:getCode()}}
	end
end)


add_handler(function(titleObject)

	local etiket = titleObject.text:match("^(.+) li gorî zimanan$")

	if etiket then
		local label = etiket
		return {title = "li gorî zimanan", args = {nil, label}}
	end		
end)

-- [[Modul:dara kategoriyan/gelemperkatbike]]
add_handler(function(titleObject)
	local label, lang = splitLabelLang(titleObject)
	
	if not label:find("Peyvên .") then
		return nil
	end
	
	local z, et = label:match("Peyvên (.+) yên (.+)")
	if et then
		label = et
		lang = require("Module:ziman").getByCanonicalName(z) 
	end
	if lang then
		return {title = "gelemperkatbike", args = {lang:getCode(), label}}
	else
		et = label:match("Peyvên (.+)")
		if et then
			label = et
		end
		return {title = "gelemperkatbike", args = {nil, label}}
	end
end)

-- Topical categories
add_handler(function(titleObject)

	local et, kod = titleObject.text:match("^(.+) bi (.*)$")
	local code = require("Module:ziman").getByCanonicalName(kod)
	if code then
		local label = et
		return {title = "ferhengokkatbike", args = {code:getCode(), label}}
	else
		return {title = "ferhengokkatbike", args = {nil, titleObject.text}}
	end
end)


local topic_cat_with_lang = handlers[#handlers]

function export.show(frame)
	local args = require("Module:parameters").process(frame:getParent().args, {
		nopos = { type = "boolean" },
	})
	local titleObject = mw.title.getCurrentTitle()
	
	if titleObject.nsText == "Şablon" then
		return "(Vê şablonê di rûpelên Kategorî: de bi kar bîne.)"
	elseif titleObject.nsText ~= "Kategorî" then
		error("Ev şablon/modul tenê di rûpelên Kategorî: de tên bikaranîn.")
	end

	local first_error_cattext

	-- Go through each handler in turn. If a handler doesn't recognize the format of the
	-- category, it will return nil, and we will consider the next handler. Otherwise,
	-- it returns a template name and arguments to call it with, but even then, that template
	-- might return an error, and we need to consider the next handler. This happens,
	-- for example, with the category "CAT:Mato Grosso, Brazil", where "Mato" is the name of
	-- a language, so the handler for {{poscatboiler}} fires and tries to find a label
	-- "Grosso, Brazil". This throws an error, and previously, this blocked fruther handler
	-- consideration, but now we check for the error and continue checking handlers;
	-- eventually, {{topic cat}} will fire and correctly handle the category.
	--
	-- FIXME: Will the topic_cat handlers correctly handle "letter names" categories?
	for _, handler in ipairs(args.nopos and { topic_cat_with_lang, topic_cat_without_lang } or handlers) do
		local templateObject = handler(titleObject)
		
		if templateObject then
			require("Module:debug").track("auto cat/" .. templateObject.title)
			local cattext = frame:expandTemplate(templateObject)
			-- FIXME! We check for specific text found in most or all error messages generated
			-- by category tree templates (in particular, the second piece of text below should be
			-- in all error messages generated when a given module doesn't recognize a category name).
			-- If this text ever changes in the source modules (e.g. [[Module:category tree]],
			-- it needs to be changed here as well.)
			if cattext:find("Kategorî:Categories with invalid label") or
				cattext:find("The automatically%-generated contents of this category has errors") then
				if not first_error_cattext then
					first_error_cattext = cattext
				end
			else
				return cattext
			end
		end
	end
	
	if first_error_cattext then
		return first_error_cattext
	end
	error("{{ş|katbike}} ji formata navê kategoriyê tiştek fêm nekir.")
end

-- test function for injecting title string
function export.test(title)
	if type(title) == "table" then
		title = title:getParent().args[1]
	end
	
	local titleObject = {}
	titleObject.text = title
	
	for _, handler in ipairs(handlers) do
		local t = handler(titleObject)
		
		if t then
			return t.title
		end
	end	
end

return export

-- For Vim, so we get 4-space tabs
-- vim: set ts=4 sw=4 noet: