local checkType = require('libraryUtil').checkType
local p = {}

--Global strings and forms
local defaults = {
	badCatListFormat = "Bad category list format (key: %s, value: %s)",
	categoryForm = "[[Category:%s]]",
	keyedCategoryForm = "[[Category:%s|%s]]",
	missingNameMsg = "Missing category name"
}

--Adds a category to the provided category list; sortKey is optional
function p.addCategory(catList, name, sortKey)
	--Check and normalize parameters
	checkType('addCategory', 1, catList, 'table')
	checkType('addCategory', 2, name, 'string')
	name = mw.text.trim(name)
	checkType('addCategory', 3, sortKey, 'string', true)
	if #name == 0 then error(defaults.missingNameMsg, 2) end
	if sortKey == nil or #sortKey == 0 then sortKey = nil end

	--Add category to category list
	catList[name] = sortKey or true
end

--Removes a category from the provided category list
function p.removeCategory(catList, name)
	--Check and normalize parameters
	checkType('removeCategory', 1, catList, 'table')
	checkType('removeCategory', 2, name, 'string')
	name = mw.text.trim(name)
	if #name == 0 then error(defaults.missingNameMsg, 2) end

	--Remove category from category list
	catList[name] = nil
end

--Converts a category list to a string containing its categories as wikitext
function p.writeCategoryList(catList, nullify)
	checkType('removeCategory', 1, catList, 'table')
	checkType('removeCategory', 2, name, 'boolean', true)

	if nullify then return "" end
	
	local constructedList = {}
	for k, v in pairs(catList) do
		if (
			type(k) ~= "string" or
			(
				(type(v) ~= "boolean" or v == false) and
				(type(v) ~= "string")
			)
		) then
			error(
				string.format(
					defaults.badCatListFormat,
					mw.dumpObject(k),
					mw.dumpObject(v)
				),
				2
			)	
		end
		table.insert(
			constructedList,
			(v == true) and
				string.format(defaults.categoryForm, k) or
				string.format(defaults.keyedCategoryForm, k, v)
		)
	end
	return table.concat(constructedList)
end

return p