local LuaCoverage = require "LuaCoverage"

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

local function fileWriter( filename, optAppend )
	local fh, message = io.open( filename, optAppend and "a" or "w" )
	
	if fh then
		local function printLine( text )
			return fh:write( text ) and fh:write( "\n" )
		end
		
		local function close()
			return fh:close()
		end
		
		return printLine, close
	else
		return nil, message or string.format( "unknown error opening: %s", filename )
	end
end

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

local function printLineCoverageData( data, printLine )
	local lastChunk = nil
	for chunk, lines in pairs( data ) do
		for line, _ in pairs( lines ) do
			if chunk == lastChunk then
				chunk = ""
			else
				lastChunk = chunk
			end
			printLine( string.format( "%s:%d", chunk, line ) )
		end
	end
end

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

local function writeCoverageLog( logFilename, data )
	local printLine, closeOrMessage = fileWriter( logFilename )
	printLineCoverageData( data, printLine )
	closeOrMessage()
end

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

local function printCoverageData( data, printFn, optMode )
	local mode = optMode or LuaCoverage.mode( data )
    if mode == "instruction" then
        LuaCoverage.iterateInstructionCoverageData( data, function( hash, base, pc )
            printFn( string.format( "%d:%d+%d", hash, base, pc ) )
        end )
    elseif mode == "line" then
        local convertedData = LuaCoverage.transformCoverageLines( data, function() end )
        printLineCoverageData( convertedData, printFn )
    end
end

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

local function updateCoverageLog( data, logFilename, optMarkerLine, optLogFn )
    local mode = LuaCoverage.mode( data )
	optLogFn = optLogFn or print

    if mode then
        optLogFn( "Start flushing coverage data to lcr files.")
        local printLine, closeOrMessage = fileWriter( logFilename, true )
        if printLine then
			if optMarkerLine then
            	printLine( optMarkerLine )
			end
			printCoverageData( data, printLine, mode )
            closeOrMessage()
            optLogFn( "Done flushing coverage." )
        else
            optLogFn( "Error opening scan file: ", closeOrMessage )
        end
    end
end

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

return {
	fileWriter = fileWriter,
	printLineCoverageData = printLineCoverageData,
	updateCoverageLog = updateCoverageLog,
	writeCoverageLog = writeCoverageLog
}
