This module implements {{auto cat}}.


-- Prevent substitution.
if mw.isSubsting() then
	return require("Module:unsubst")
end

local m_category_tree = require("Module:category tree")
local m_str_utils = require("Module:string utilities")

local concat = table.concat
local deepcopy = require("Module:table").deepcopy
local get_current_title = mw.title.getCurrentTitle
local insert = table.insert
local split = m_str_utils.split
local split_lang_label = m_category_tree.split_lang_label
local trim = m_str_utils.trim
local yesno = require("Module:yesno")

local export = {}

-- Used in multiple places; create a variable for ease in testing.
local poscatboiler = "poscatboiler"
local topic_cat = "topic cat"
local ws_topic_cat = "ws topic cat"

--[==[
List of handler functions that try to match the page name. A handler should return the name of a submodule to
[[Module:category tree]] and an info table which is passed as an argument to the submodule. If a handler does not
recognize the page name, it should return nil. Note that the order of handlers matters!
]==]
local handlers = {}


-- ws topic cat
insert(handlers, function(titleObject)
	local code, label = titleObject.text:match("^Thesaurus:(%l[%a-]*%a):(.+)")
	if code then
		return ws_topic_cat, {label = label, code = code}
	end
end)


-- Topical categories
insert(handlers, function(titleObject)
	local code, label = titleObject.text:match("^(%l[%a-]*%a):(.+)")
	if code then
		return topic_cat, {label = label, code = code}
	end
end)


-- Lect categories e.g. for [[:Category:New Zealand English]] or [[:Category:Issime Walser]]
insert(handlers, function(titleObject, args)
	local lect = args.lect or args.dialect
	if lect ~= "" and yesno(dialect, true) then -- Same as boolean in [[Module:parameters]].
		return poscatboiler, {label = titleObject.text, args = args, raw = true}
	end
end)


-- poscatboiler lang-specific
insert(handlers, function(titleObject, args)
	local lang, label = split_lang_label(titleObject)
	if not lang then
		return
	end
	local baseLabel, script = label:match("(.+), (.-) අක්ෂරක්‍රමය භාවිතා කොට ලියන ලද$")
	if script and baseLabel ~= "යෙදුම්" then
		local scriptObj = require("Module:scripts").getByCanonicalName(script)
		if scriptObj then
			return poscatboiler, {label = baseLabel, code = lang:getCode(), sc = scriptObj:getCode(), args = args}
		end
	end
	return poscatboiler, {label = label, code = lang:getCode(), args = args}
end)


-- poscatboiler umbrella category
insert(handlers, function(titleObject, args)
	local label = titleObject.text:match("භාෂාව අනුව (.+)$")
	if label then
		-- The poscatboiler code will appropriately lowercase if needed.
		return poscatboiler, {label = label, args = args}
	end
end)


-- ws topic cat
insert(handlers, function(titleObject)
	local label = titleObject.text:match("^Thesaurus:(.+)")
	if label then
		return ws_topic_cat, {label = label}
	end
end)


-- topic cat
insert(handlers, function(titleObject)
	return topic_cat, {label = titleObject.text}
end)


-- poscatboiler raw handlers
insert(handlers, function(titleObject, args)
	return poscatboiler, {label = titleObject.text, args = args, raw = true}
end)


-- poscatboiler umbrella handlers without 'by language'
insert(handlers, function(titleObject, args)
	return poscatboiler, {label = titleObject.text, args = args}
end)


function export.show(frame)
	local args = {}
	for k, arg in pairs(frame:getParent().args) do
		args[k] = trim(arg)
	end
	
	local namespace = get_current_title().namespace
	
	if namespace == 10 then -- Template
		return "(This template should be used on pages in the [[Help:Namespaces#Category|ප්‍රවර්ගය:]] namespace.)"
	elseif namespace ~= 14 then -- Category
		error("This template/module can only be used on pages in the [[mw:Help:Namespaces#Category|ප්‍රවර්ගය:]] namespace.")
	end

	local function extra_args_error()
		error("Extra arguments to {{((}}auto cat{{))}} are not allowed for this category.")
	end

	local first_fail_args_handled, first_fail_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.
	for _, handler in ipairs(handlers) do
		-- Use a new title object and args table for each handler, to keep them isolated.
		local submodule, info = handler(get_current_title(), deepcopy(args))
		if submodule then
			require("Module:debug").track("auto cat/" .. submodule)
			-- TODO: merge this loop into m_category_tree.main.
			-- `failed` is true if no match was found.
			local cattext, failed = m_category_tree.main(submodule, info)
			if failed then
				if not first_fail_cattext then
					first_fail_cattext = cattext
					first_fail_args_handled = info.args and true or false
				end
			elseif not info.args and next(args) then
				extra_args_error()
			else
				return cattext
			end
		end
	end
	
	-- If there were no matches, throw an error if any arguments were given, or otherwise return the cattext
	-- from the first fail encountered. The final handlers call the boilers unconditionally, so there should
	-- always be something to return.
	if not first_fail_args_handled and next(args) then
		extra_args_error()
	end
	return first_fail_cattext
end

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

return export
"https://si.wiktionary.org/w/index.php?title=Module:auto_cat&oldid=186111" වෙතින් සම්ප්‍රවේශනය කෙරිණි