-- Tests whether a module has a test API, and if so, runs these tests

local p = {}

function p.run(titleCurrentPage)
	local title = titleCurrentPage
	local titlesplit = mw.text.split(title, '/', true)
	if titlesplit[1]:find('Module:', 1, true) ~= 1 then return '' end
	if titlesplit[#titlesplit] == 'doc' then
		table.remove(titlesplit)
	end
	title = table.concat(titlesplit, '/')
	
	-- Load the module
	local m = require(title)
	local testType = 'public-member'
	local testFunction = ( (type(m) == 'table') and (getmetatable(m) and getmetatable(m).quickTests or m['runTests']) )
	local testFunctionType = type(testFunction)
	if ( (type(m) == 'table') and (getmetatable(m) and getmetatable(m).quickTests) ) then
		testType = 'meta-table'
	end
	if ( testFunctionType ~= 'function' and not ( testFunctionType == 'table' and getmetatable(testFunction).__call ) ) then
		return '', title, testType
	end
	
	-- Execute the test function
	local ok, result = pcall(testFunction)
	if ok then
		return result, title, testType
	else
		return 'error', title, testType
	end
end

function cat(title, titleCurrentPage, cat)
	if titleCurrentPage == title then return cat end
	return ''
end

function p.testModule(frame)
	local titleCurrentPage =  ( frame.args and frame.args.title ) or ( frame and frame:preprocess('{{FULLPAGENAME}}') ) or 'Frame not defined.'
	local testResult, title, testType = p.run(titleCurrentPage)
	local testCode = '=p.runTests()'

	if testResult == true then
		return '[[File:Octicons-check.svg|16px|alt=Quick tests passed|Quick tests passed|link=COM:LUA/T#auto]]' .. cat(title, titleCurrentPage, '[[Category:Scribunto modules with tests passed]]')
	elseif testResult == false then
		if testType == 'meta-table' then
			testCode = '=getmetatable(p).quickTests()'
		end
		return '[[File:Octicons-bug.svg|16px|alt=Bug executing tests|Bug executing tests|link=COM:LUA/T#auto]] Run <code>' .. testCode .. '</code> in the LUA console on [[' .. title .. ']] for more details.' .. cat(title, titleCurrentPage, '[[Category:Scribunto modules with tests failed]]')
	elseif testResult == 'error' then
		return '[[File:Octicons-issue-opened.svg|16px|alt=Error|link=COM:LUA/T#auto]] Error executing tests.' .. cat(title, titleCurrentPage, '[[Category:Scribunto modules with errors executing tests]]')
	else
		return '[[File:Octicons-megaphone.svg|16px|alt=No test API|link=COM:LUA/T#auto-howto]] '.. testResult .. cat(title, titleCurrentPage, '[[Category:Scribunto modules without test API]]')
	end
end

function p.injectResult(frame)
	local result = p.testModule(frame)
	if result == '' then return '' end
	
	return ( frame.args['pattern']:gsub('%%result%%', result) )
end


local mt = {
	quickTests = function ()
		return 'function' == type( p.injectResult )
	end
}
setmetatable(p, mt)

return p