Modul:language-like

local export = {}

-- Implementation of getOtherNames() for languages, etymology languages,
-- families and scripts. If `onlyOtherNames` is passed in, only return
-- the names in the `otherNames` field, otherwise combine `otherNames`,
-- `aliases` and `varieties`.
function export.getOtherNames(self, onlyOtherNames)
	local data
	if self._extraData then
		data = self._extraData
	elseif self._rawData then
		data = self._rawData
	else
		-- Called from [[Module:list of languages]]; fields already available directly.
		data = self
	end
	if onlyOtherNames then
		return data.otherNames or {}
	end
	-- Combine otherNames, aliases and varieties. First try to optimize and not create any
	-- new memory. This is possible if exactly one of the three exist, and if it's `varieties`,
	-- there are no nested lists in `varieties`.
	if data.otherNames and not data.aliases and not data.varieties then
		return data.otherNames
	elseif data.aliases and not data.otherNames and not data.varieties then
		return data.aliases
	elseif data.varieties and not data.otherNames and not data.aliases then
		local saw_table = false
		for _, name in ipairs(data.varieties) do
			if type(name) == "table" then
				saw_table = true
				break
			end
		end
		if not saw_table then
			return data.varieties
		end
	end

	-- Have to do it the "hard way".
	local ret = {}
	if data.otherNames then
		for _, name in ipairs(data.otherNames) do
			table.insert(ret, name)
		end
	end
	if data.aliases then
		for _, name in ipairs(data.aliases) do
			table.insert(ret, name)
		end
	end
	if data.varieties then
		for _, name in ipairs(data.varieties) do
			if type(name) == "table" then
				for _, n in ipairs(name) do
					table.insert(ret, n)
				end
			else
				table.insert(ret, name)
			end
		end
	end
	return ret
end


-- Implementation of getVarieties() for languages, etymology languages,
-- families and scripts. If `flatten` is passed in, flatten down to a
-- list of strings; otherwise, keep the structure.
function export.getVarieties(self, flatten)
	local data
	if self._extraData then
		data = self._extraData
	elseif self._rawData then
		data = self._rawData
	else
		-- Called from [[Module:list of languages]]; fields already available directly.
		data = self
	end
	if data.varieties then
		-- If flattening not requested, just return them.
		if not flatten then
			return data.varieties
		end
		-- Check if no nested table; if so, just return the result.
		local saw_table = false
		for _, name in ipairs(data.varieties) do
			if type(name) == "table" then
				saw_table = true
				break
			end
		end
		if not saw_table then
			return data.varieties
		end
		-- At this point, we need to flatten the varieties.
		local ret = {}
		for _, name in ipairs(data.varieties) do
			if type(name) == "table" then
				for _, n in ipairs(name) do
					table.insert(ret, n)
				end
			else
				table.insert(ret, name)
			end
		end
		return ret
	else
		return {}
	end
end


-- Implementation of template-callable getByCode() function for languages,
-- etymology languages, families and scripts. `item` is the language,
-- family or script in question; `args` is the arguments passed in by the
-- module invocation; `extra_processing`, if specified, is a function of
-- one argument (the requested property) and should return the value to
-- be returned to the caller, or nil if the property isn't recognized.
-- `extra_processing` is called after special-cased properties are handled
-- and before general-purpose processing code that works for all string
-- properties.
function export.templateGetByCode(args, extra_processing)
	-- The item that the caller wanted to look up.
	local item, itemname, list = args[1], args[2]
	if itemname == "getOtherNames" then
		list = item:getOtherNames()
	elseif itemname == "getOnlyOtherNames" then
		list = item:getOtherNames(true)
	elseif itemname == "getAliases" then
		list = item:getAliases()
	elseif itemname == "getVarieties" then
		list = item:getVarieties(true)
	end
	if list then
		local index = args[3]; if index == "" then index = nil end
		index = tonumber(index or error("Numeric index of the desired item in the list (parameter 3) has not been specified."))
		return list[index] or ""
	end

	if itemname == "getFamily" and item.getFamily then
		return item:getFamily():getCode()
	end

	if extra_processing then
		local retval = extra_processing(itemname)
		if retval then
			return retval
		end
	end

	if item[itemname] then
		local ret = item[itemname](item)
		
		if type(ret) == "string" then
			return ret
		else
			error("The function \"" .. itemname .. "\" did not return a string value.")
		end
	end

	error("Requested invalid item name \"" .. itemname .. "\".")
end

do
	local function get_commons_cat_claim(item)
		if not (item and mw.wikibase) then
			return nil
		end
		local entity = mw.wikibase.getEntity(item)
		if not entity then
			return nil
		end
		local claim = entity:getBestStatements("P373")[1]
		return claim and ("Kategori:" .. claim.mainsnak.datavalue.value) or nil
	end
	
	local function get_commons_cat_sitelink(item)
		if not (item and mw.wikibase) then
			return nil
		end
		local sitelink = mw.wikibase.sitelink(item, "commonswiki")
		-- Reject any sitelinks that aren't categories.
		return sitelink and sitelink:match("^Kategori:") and sitelink or nil
	end
	
	-- Implementation of getCommonsCategory() for languages, etymology
	-- languages, families and scripts.
	function export.getCommonsCategory(self)
		local cached_value
		cached_value = self._commons_category
		if cached_value ~= nil then -- including false
			return cached_value or nil
		end
		-- Checks are in decreasing order of likelihood for a useful match.
		-- Get the Commons Category claim from the language's item.
		local lang_item = self:getWikidataItem()
		cached_value = get_commons_cat_claim(lang_item)
		if cached_value == nil then
			-- Otherwise, try the language's category's item.
			local langcat_item = mw.wikibase.getEntityIdForTitle("Kategori:" .. self:getCategoryName())
			cached_value = get_commons_cat_claim(langcat_item)
			if cached_value == nil then
				-- If there's no P373 claim, there might be a sitelink on the language's category's item.
				cached_value = get_commons_cat_sitelink(langcat_item)
				if cached_value == nil then
					-- Otherwise, try for a sitelink on the language's own item.
					cached_value = get_commons_cat_sitelink(lang_item)
					if cached_value == nil then
						cached_value = false
					end
				end
			end
		end
		self._commons_category = cached_value
		return cached_value or nil
	end
end

return export