呢個模組嘅解說可以喺模組:category tree/topic cat/doc度開

local export = {}

local labels = require("Module:category tree/topic cat/data")

-- Category object

local Category = {}
Category.__index = Category


function Category.new_main(frame)
	local self = setmetatable({}, Category)
	
	local params = {
		[1] = {},
		[2] = {required = true},
		["sc"] = {},
	}
	
	args = require("Module:parameters").process(frame:getParent().args, params)
	self._info = {code = args[1], label = args[2]}
	
	self:initCommon()
	
	if not self._data then
		return nil
	end
	
	return self
end

function Category.new(info)
	for key, val in pairs(info) do
		if not (key == "code" or key == "label") then
			error("The parameter \"" .. key .. "\" was not recognized.")
		end
	end
	
	local self = setmetatable({}, Category)
	self._info = info
	
	if not self._info.label then
		error("No label was specified.")
	end
	
	self:initCommon()
	
	if not self._data then
		error("The label \"" .. self._info.label .. "\" does not exist.")
	end
	
	return self
end

export.new = Category.new
export.new_main = Category.new_main


function Category:initCommon()
	if self._info.code then
		self._lang = require("Module:languages").getByCode(self._info.code) or
			error("語言代碼「" .. self._info.code .. "」無效。")
	end
	
	-- Convert label to lowercase if possible
	local lowercase_label = mw.getContentLanguage():lcfirst(self._info.label)
	
	if labels[lowercase_label] then
		self._info.label = lowercase_label
	end
	
	self._data = labels[self._info.label]
end


function Category:getInfo()
	return self._info
end


function Category:getBreadcrumbName()
	return self._info.label
end


function Category:getDataModule()
	return self._data["edit"]
end


function Category:canBeEmpty()
	if self._lang then
		return false
	else
		return true
	end
end


function Category:isHidden()
	return false
end


function Category:getCategoryName()
	if self._lang then
		return self._lang:getCode() .. ":" .. mw.getContentLanguage():ucfirst(self._info.label)
	else
		return mw.getContentLanguage():ucfirst(self._info.label)
	end
end


function Category:getDescription()
	if self._lang then
		local ret = self._data["description"]
		
		-- TODO: Should probably find a better way to do this
		descriptionFormats = {
			["default"]					= "同{{{label_lc}}}有關嘅{{{langname}}}辭條。",
			["default with capital"]	= "同{{{label_uc}}}有關嘅{{{langname}}}辭條。",
			["default with the"]		= "{{{langname}}} terms related to the {{{label_uc}}}.",
			["default with the lower"]	= "{{{langname}}} terms related to the {{{label_lc}}}.",
			["default with topic"]		= "{{{langname}}} terms related to {{{label_lc}}} topics.",
			["default-set"]				= "{{{langname}}} terms for various {{{label_lc}}}.",
		}
		
		ret = descriptionFormats[ret] or ret
		
		if ret then
			ret = ret:gsub("{{{langname}}}", self._lang:getCanonicalName())
			ret = ret:gsub("{{{langcode}}}", self._lang:getCode())
			ret = ret:gsub("{{{langcat}}}", self._lang:getCategoryName())
			
			if ret:find("{{{label_uc}}}") then
				local label_entry_name = mw.getContentLanguage():ucfirst(self._info.label)
				local label_entry = mw.title.new(label_entry_name)
				
				if label_entry.exists then
					ret = ret:gsub("{{{label_uc}}}", "[[" .. label_entry_name .. "]]")
				else
					ret = ret:gsub("{{{label_uc}}}", label_entry_name)
				end
			end
			
			if ret:find("{{{label_lc}}}") then
				local label_entry_name = mw.getContentLanguage():lcfirst(self._info.label)
				local label_entry = mw.title.new(label_entry_name)
				
				if label_entry.exists then
					ret = ret:gsub("{{{label_lc}}}", "[[" .. label_entry_name .. "]]")
				else
					ret = ret:gsub("{{{label_lc}}}", label_entry_name)
				end
			end
		end
		
		return ret
	else
		if not self._lang and ( self._info.label == "all topics" or self._info.label == "all sets" ) then
			return "This category applies to content and not to meta material about the Wiki."
		end
		
		local eninfo = mw.clone(self._info)
		eninfo.code = "en"
		local en = Category.new(eninfo)
		
		return
			"呢個分類淨係包含其他分類,而唔包含任何辭條。Its subcategories are on the topic: " .. self._info.label .. ". They may be of two sorts:\n\n" ..
			"* Subcategories named like \"aa:" .. self._info.label .. "\" (with a prefixed language code) are categories of terms in specific languages. " ..
			"You may be interested especially in [[:Category:" .. yue:getCategoryName() .. "]], for Cantonese terms.\n" ..
			"* Subcategories of this one named without the prefixed language code are further categories just like this one, but devoted to finer topics."
	end
end


function Category:getParents()
	local parents = self._data["parents"]
	
	if not self._lang and ( self._info.label == "all topics" or self._info.label == "all sets" ) then
		return {{ name = "Category:Fundamental", sort = self._info.label:gsub("all ", "") }}
	end
	
	if not parents or #parents == 0 then
		return nil
	end
	
	local ret = {}
	local is_set = false
	
	if self._info.label == "all sets" then
		is_set = true
	end
	
	for key, parent in ipairs(parents) do
		parent = mw.clone(parent)
		
		if type(parent) ~= "table" then
			parent = {name = parent}
		end
		
		if not parent.sort then
			parent.sort = self._info.label
		end
		
		if self._lang then
			parent.sort = parent.sort:gsub("{{{langname}}}", self._lang:getCanonicalName())
			parent.sort = parent.sort:gsub("{{{langcat}}}", self._lang:getCategoryName())
		elseif parent.sort:find("{{{langname}}}") or parent.sort:find("{{{langcat}}}") or parent.template == "langcatboiler" then
			return nil
		end
		
		if not self._lang then
			parent.sort = " " .. parent.sort
		end
		
		if parent.name and parent.name:find("^Category:") then
			if self._lang then
				parent.name = parent.name:gsub("{{{langname}}}", self._lang:getCanonicalName())
				parent.name = parent.name:gsub("{{{langcat}}}", self._lang:getCategoryName())
			elseif parent.name:find("{{{langname}}}") or parent.name:find("{{{langcat}}}") or parent.template == "langcatboiler" then
				return nil
			end
		else
			if parent.name == "list of sets" then
				is_set = true
			end
			
			local pinfo = mw.clone(self._info)
			pinfo.label = parent.name
			
			if parent.template then
				parent.name = require("Module:category tree/" .. parent.template).new(pinfo)
			else
				parent.name = Category.new(pinfo)
			end
		end
		
		table.insert(ret, parent)
	end
	
	if not is_set and self._info.label ~= "list of topics" and self._info.label ~= "list of sets" then
		local pinfo = mw.clone(self._info)
		pinfo.label = "list of topics"
		table.insert(ret, {name = Category.new(pinfo), sort = (not self._lang and " " or "") .. self._info.label})
	end
	
	return ret
end


function Category:getChildren()
	return nil
end


function Category:getUmbrella()
	if not self._lang then
		return nil
	end
	
	local uinfo = mw.clone(self._info)
	uinfo.code = nil
	return Category.new(uinfo)
end


return export