--[[----------------------------------------------------------------------------

WFLuaTestThreadRunnerImp.lua

--------------------------------------------------------------------------------
ADOBE CONFIDENTIAL
------------------
Copyright 2023 Adobe
All Rights Reserved.

NOTICE: All information contained herein is, and remains
the property of Adobe and its suppliers, if any. The intellectual
and technical concepts contained herein are proprietary to Adobe
and its suppliers and are protected by all applicable intellectual
property laws, including trade secret and copyright laws.
Dissemination of this information or reproduction of this material
is strictly forbidden unless prior written permission is obtained
from Adobe.

------------------------------------------------------------------------------]]

	-- Rx
local Rx = require 'Rx'

	-- WF.core.lua.threading
local WFRequestDispatcher = require 'WFRequestDispatcher'

	-- WF.core.self_test
local WFLuaTestRunner = require 'WFLuaTestRunner'

	-- WF.core.utils
local WFArguments = require 'WFArguments'
local WFCloseSupport = require 'WFCloseSupport'

--------------------------------------------------------------------------------

local check = assert( WFArguments.check, "Cannot find WFArguments.check" )

local kClosed = { __closed = "CLOSED" }

--============================================================================--

--------------------------------------------------------------------------------

local WFLuaTestThreadRunnerImp = {

	_testThreadId = false,
	
	WFCloseSupport.addCloseSupportMethods,
	
}

--------------------------------------------------------------------------------
--[[!
	\brief Create a new index store implementation.

	Should only be used by index definition files.

	\param docStorePath (\c string) path to doc store to observe
	\param indexStoreSchema (\c WFRxIndexStoreSchema) index store schema
--]]

function WFLuaTestThreadRunnerImp:__init( testThreadId )

	check( 'WFLuaTestThreadRunnerImp', 'number' )

	self._testThreadId = testThreadId

end

--------------------------------------------------------------------------------

function WFLuaTestThreadRunnerImp:runTestsInSuite( testSuiteName, testNames, coverageDirPath )

	check( 'WFLuaTestThreadRunnerImp', '+string', 'table', '?string' )
	
	if not next( testNames ) then
		return
	end
	
	local testRunner = WFLuaTestRunner.make( testSuiteName )
	
	if coverageDirPath then
		testRunner:setCoveragePath( coverageDirPath )
	end
	
	testRunner:setUpClass()
	
	local testResults = {}
	local successCount = 0
	local failureCount = 0
	local totalExecutionTime = 0
						
	for _, testName in ipairs( testNames ) do
	
		testRunner:setUp()
		
		local success, executionTimeInMilliseconds, logMessage, failureMessage = testRunner:runTest( testName )
		
		testRunner:tearDown()
		
		local executionTime = executionTimeInMilliseconds / 1000
		totalExecutionTime = totalExecutionTime + executionTime
		
		if success then
			
			successCount = successCount + 1
			
			testResults[ testName ] = 
			{
				success = true,
				executionTime = executionTime,
				logMessage = logMessage
			}
			
		else
		
			failureCount = failureCount + 1
			
			testResults[ testName ] = 
			{
				failure = true,
				executionTime = executionTime,
				logMessage = logMessage,
				failureMessage = failureMessage
			}
		
		end
	
	end
	
	testRunner:tearDownClass()
	
	testRunner:close()
							
	return successCount, failureCount, totalExecutionTime, testResults
	
end

--------------------------------------------------------------------------------

WFLuaTestThreadRunnerImp = Rx.Class 'WFLuaTestThreadRunnerImp'( WFLuaTestThreadRunnerImp )

--------------------------------------------------------------------------------

local initMessageProcessor = function( testThreadIdAndStuff )

	local _, _, testThreadId = string.find( testThreadIdAndStuff, "^(%d+)$" )
	local testThreadRunner = WFLuaTestThreadRunnerImp( tonumber( testThreadId ) )

	WFRequestDispatcher.onMessage( 'initTestThreadRunner', function()

		return true
			-- noOp

	end )

	local messageForwarder = setmetatable({}, {
		__index = function( _, methodName )
			return function( self, ... )
				assert( testThreadRunner, 'test thread runner not yet inited' )
				assert( testThreadRunner ~= kClosed, 'test thread runner closed' )
				local method = assert( testThreadRunner[ methodName ], 'No such method on test thread runner' )
				return method( testThreadRunner, ... )
			end
		end,
	})
	
	WFRequestDispatcher.onMessage( 'close', function()

		assert( testThreadRunner, 'test thread runner not yet inited' )
		assert( testThreadRunner ~= kClosed, 'test thread runner closed' )
		local oldTestThreadRunner = testThreadRunner
		testThreadRunner = kClosed
		return oldTestThreadRunner:close()

	end )
	
	WFRequestDispatcher.onMessageDo {
		message = 'runTestsInSuite',
		target = messageForwarder,
	}

end

return {
	initMessageProcessor = initMessageProcessor
}
