local checkType = require('libraryUtil').checkType

local p = {}

-- Name: p.name
-- Purpose: Find a template invocation name from a page name or a
-- mw.title object.
-- Description: This function detects whether a string or a mw.title
-- object has been passed in, and uses that to find a
-- template name as it is used in template invocations.
-- Parameters: title - full page name or mw.title object for the
-- template (string or mw.title object)
-- Returns: String

function p.name(title)
	if type(title) == 'string' then
		title = mw.title.new(title)
		if not title then
			error
		end
	elseif type(title) ~= 'table' or type(title.getContent) ~= 'function' then
		error
	end
	if title.namespace == 10 then
		return title.text
	elseif title.namespace == 0 then
		return ':' .. title.prefixedText
	else
		return title.prefixedText
	end
end

-- Name: p.invocation
-- Purpose: Construct a MediaWiki template invocation.
-- Description: This function makes a template invocation from the
-- name and the arguments given. Note that it isn't
-- perfect: we have no way of knowing what whitespace was
-- in the original invocation, the named parameters will be
-- alphabetically sorted, and any parameters with duplicate keys
-- will be removed.
-- Parameters: name - the template name, formatted as it will appear
-- in the invocation. (string)
-- args - a table of template arguments. (table)
-- format - formatting options. 
-- Set to "nowiki" to escape, curly braces, pipes and
-- equals signs with their HTML entities. The default
-- is unescaped.
-- Returns: String

function p.invocation
	checkType
	checkType
	checkType

	-- Validate the args table and make a copy to work from. We need to
	-- make a copy of the table rather than just using the original, as
	-- some of the values may be erased when building the invocation.
	local invArgs = {}
	for k, v in pairs(args) do
		local typek = type(k)
		local typev = type(v)
		if typek ~= 'string' and typek ~= 'number'
			or typev ~= 'string' and typev ~= 'number'
		then
			error("invalid arguments table in parameter #2 of " ..
			"'invocation' (keys and values must be strings or numbers)", 2)
		end
		invArgs[k] = v
	end

	-- Get the separators to use.
	local seps = {
		openb = '',
		pipe = '|',
		equals = '='
	if format == 'nowiki' then
		for k, v in pairs(seps) do
			seps[k] = mw.text.nowiki(v)
		end
	end

	-- Build the invocation body with numbered args first, then named.
	local ret = {}
	ret[#ret + 1] = seps.openb
	ret[#ret + 1] = name
	for k, v in ipairs(invArgs) do
		if type(v) == 'string' and v:find then
			-- Likely something like 1=foo=bar which needs to be displayed as a named arg.
		else
			ret[#ret + 1] = seps.pipe
			ret[#ret + 1] = v
			invArgs[k] = nil -- Erase the key so that we don't add the value twice
		end
	end
	local keys = {} -- sort parameter list; better than arbitrary order
	for k, _ in pairs(invArgs) do
		keys[#keys + 1] = k
	end
	table.sort(keys, function 
			-- Sort with keys of type number first, then string.
			if type(a) == type(b) then
				return a < b
			elseif type(a) == 'number' then
				return true
			end
		end)
	for _, v in ipairs(keys) do -- Add named args based on sorted parameter list
		ret[#ret + 1] = seps.pipe
		ret[#ret + 1] = tostring(v)
		ret[#ret + 1] = seps.equals
		ret[#ret + 1] = invArgs[v]
	end
	ret[#ret + 1] = seps.closeb

	return table.concat(ret)
end