# Module:Unsubst

local checkType = require('libraryUtil').checkType  

local p = {}  

local BODY_PARAM = '$B'  

local specialParams = {  
['$params'] = 'parameter list',  
['$aliases'] = 'parameter aliases',  
['$flags'] = 'flags',  
['$B'] = 'template content',  
['$template-name'] = 'template invocation name override',  
}  

function p.main(, body)  
-- If we are substing, this function returns a template invocation, and if  
-- not, it returns the template body. The template body can be specified in  
-- the body parameter, or in the template parameter defined in the  
-- BODY_PARAM variable. This function can be called from Lua or from  
-- #invoke.  

-- Return the template body if we aren't substing.  
if not mw.isSubsting then  
if body ~= nil then  
return body  
elseif .args[BODY_PARAM] ~= nil then  
return .args[BODY_PARAM]  
else  
error(string.format(  
"no template content specified (use parameter '%s' from #invoke)",  
BODY_PARAM  
), 2)  
end  
end  

-- Sanity check for the object.  
if type ~= 'table'  
or type(.getParent) ~= 'function'  
or not :getParent  
then  
error(  
"argument #1 to 'main' must be a object with a parent " ..  
" available",  
2  
end  

-- Find the invocation name.  
local mTemplateInvocation = require('Module:Template invocation')  
local name  

if .args['$template-name'] and '' ~= .args['$template-name'] then  
name = .args['$template-name'] -- override whatever the template name is with this name  
else  
name = mTemplateInvocation.name(:getParent:getTitle)  
end  

-- Combine passed args with passed defaults  
local args = {}  
if string.find( ','..(.args['$flags'] or '')..',', ',%s*override%s*,' ) then  
for k, v in pairs( :getParent.args ) do  
args[k] = v  
end  
for k, v in pairs( .args ) do  
if not specialParams[k] then  
if v == '__DATE__' then  
v = mw.getContentLanguage:formatDate( 'F Y' )  
end  
args[k] = v  
end  
end  
else  
for k, v in pairs( .args ) do  
if not specialParams[k] then  
if v == '__DATE__' then  
v = mw.getContentLanguage:formatDate( 'F Y' )  
end  
args[k] = v  
end  
end  
for k, v in pairs( :getParent.args ) do  
args[k] = v  
end  
end  

-- Trim parameters, if not specified otherwise  
if not string.find( ','..(.args['$flags'] or '')..',', ',%s*keep%-whitespace%s*,' ) then  
for k, v in pairs( args ) do args[k] = mw.ustring.match(v, '^%s*(.*)%s*$') or '' end  
end  

-- Pull information from parameter aliases  
local aliases = {}  
if .args['$aliases'] then  
local list = mw.text.split( .args['$aliases'], '%s*,%s*' )  
for k, v in ipairs( list ) do  
local tmp = mw.text.split( v, '%s*>%s*' )  
aliases[tonumber(mw.ustring.match(tmp[1], '^[1-9][0-9]*$')) or tmp[1]] = ((tonumber(mw.ustring.match(tmp[2], '^[1-9][0-9]*$'))) or tmp[2])  
end  
end  
for k, v in pairs( aliases ) do  
if args[k] and ( not args[v] or args[v] == '' ) then  
args[v] = args[k]  
end  
args[k] = nil  
end  

-- Remove empty parameters, if specified  
if string.find( ','..(.args['$flags'] or '')..',', ',%s*remove%-empty%s*,' ) then  
local tmp = 0  
for k, v in ipairs( args ) do  
if v ~= * or ( args[k+1] and args[k+1] ~= * ) or ( args[k+2] and args[k+2] ~= '' ) then  
tmp = k  
else  
break  
end  
end  
for k, v in pairs( args ) do  
if v == '' then  
if not (type(k) == 'number' and k < tmp) then args[k] = nil end  
end  
end  
end  

-- Order parameters  
if .args['$params'] then  
local params, tmp = mw.text.split( .args['$params'], '%s*,%s*' ), {}  
for k, v in ipairs(params) do  
v = tonumber(mw.ustring.match(v, '^[1-9][0-9]*$')) or v  
if args[v] then tmp[v], args[v] = args[v], nil end  
end  
for k, v in pairs(args) do tmp[k], args[k] = args[k], nil end  
args = tmp  
end  

return mTemplateInvocation.invocation(name, args)  
end  

p[''] = p.main -- For backwards compatibility  

return p