Module:Resolve category redirect

local p = {}

local function cleanup( rtarget )
	rtarget = mw.text.trim( rtarget )
	rtarget = mw.ustring.gsub( rtarget, '^1%s*=%s*', '' )
	rtarget = string.gsub( rtarget, '^[Cc]ategory:', '' )
	return rtarget
end

--Returns the target of {{Category redirect}}, if it exists, else returns the original cat.
function p.rtarget( cat, frame )
	cat = string.gsub( cat, '^[Cc]ategory:', '' ) --"!" in cat not recognized by mw.title.makeTitle() otherwise
	if string.match( cat, '[|]' ) then
		return cat	
	end
	local catcontent = mw.title.makeTitle( 'Category', cat or '' ):getContent() --makeTitle() allows ':' in cat names
	if string.match( catcontent or '', '{{ *[Cc]at' ) then --regex common to all possible calls
		catcontent = mw.ustring.gsub( catcontent, '|%s*keep%s*=%s*[yY]?[eE]?[sS]?%s*', '' ) --remove other params
		local getRegex = require('Module:Template redirect regex').main
		local tregex = getRegex('Category redirect')
		for _, v in pairs (tregex) do
			local found = mw.ustring.match( catcontent, v..'%s*|' )
			if found then --refine
				local rtarget = mw.ustring.match( catcontent, v..'%s*|%s*([^{|}]+)}}' ) or --{{Category redirect|...}} (most common)
								mw.ustring.match( catcontent, v..'%s*|%s*([^{|}]+)|' )     --{{Category redirect|...|...}} (2nd most common)
				if rtarget then --normal, plain text target
					return cleanup(rtarget)
				else
					local ty_regex = '%s*|%s*([^{|}]*{{([^#][^{|}]+)}}[^{|}]*)' --$1 nests $2
					local rtarget_ty, ty = mw.ustring.match( catcontent, v..ty_regex )
					if rtarget_ty then --{{Category redirect|...{{Title year}}... (less common)
						local ty_eval = frame:expandTemplate{ title = ty, args = { page = cat } } --frame:newChild doesn't work, use 'page' param instead
						local rtarget_ty_eval = mw.ustring.gsub( rtarget_ty, '{{%s*'..ty..'%s*}}', ty_eval )
						return cleanup(rtarget_ty_eval)
					else --resolve basic parser functions: e.g. {{#time:j F Y}} on Proposed deletion as of today (very uncommon)
						local pf_regex = '%s*|%s*([^{|}]*{{%s*(#[^{|}#:]+):([^{|}#:]+)}}[^{|}]*)' --$1 nests $2 & $3
						local rtarget_pf, pf, arg = mw.ustring.match( catcontent, v..pf_regex )
						if rtarget_pf then
							local pf_eval = frame:callParserFunction{ name = pf, args = { arg } }
							local rtarget_pf_eval = mw.ustring.gsub( rtarget_pf, '{{%s*'..pf..'%s*:%s*'..arg..'%s*}}', pf_eval )
							return cleanup(rtarget_pf_eval)
						else --potential TODO: 1) +loop for multiple templates, 2) allow sub-parameters
							return cat
						end
	end	end	end	end	end
	return cat
end

function p.main( frame )
	local args = frame:getParent().args
	local cat  = mw.text.trim( args[1] or '' )
	if (cat == '') or (cat == nil) then
		return ''
	end
	return p.rtarget( cat, frame )
end

return p