
-- module setup
local me = { name = "trace"}
local mod = thismod
mod[me.name] = me

--[[ 
Trace.lua.
		This module controls debug printing. This is a printout that assists with debugging, which you might not want most users to see. The module provides methods to determine which debug prints should be displayed. 
		Since it is often computationally expensive to format a string for printing, it is desirable to have a method to query the trace module before the printout is computed. A debug print that never actually prints anything to the console but is constantly calculating the string to print can cause an unneccesary slowdown.
		Here is as example of using the trace module:
		
	if mod.trace.check("warning", me, "talents") then 
		mod.trace.print(string.format(<long stuff here>))
	end
		
		The <trace.check()> method returns true if the message should be printed with the current settings, and the <trace.print> method prints the message as well as a header saying where the message came from (module and section).
		There are three levels of message, "error" then "warning" then "info". "error" is considered the most important, then "warning", then "info". A more important message is more likely to be printed out.
		The structure <me.default> gives the global printout setting. If <me.default.warning> is <true>, then all warning messages will be printed.
		Additionally, it is possible to specify whether messages from individual modules will be printed out or not. To override <me.default> for a module "class" say, you could run the method
		
	mod.trace.setprintstatus("class", nil, "warning", false)
		
		Then with the above settings, warnings would be printed out coming from all modules except the "class" module.

]]

--[[ 
--------------------------------------------------------------------------
			Trace Printing for Debugging or Extra Information
--------------------------------------------------------------------------

	The idea of this section is to provide a detailed method to evaluate whether a specific trace message should be printed. We have a few data structures that are print options of the form "if the print is <x>, do / dont print it".
	The more specific a print option is, the higher the priority it has. So the defaults, which just say "always print on <error>" or "never print on <info>" are the least specific and will be overridden by <me.setprintstatus>.
	For a release version, it is sufficient to set "error" = true, and the rest = "false", but for a debug version, you might only want to focus on specific sections of code for trace prints.

]]

-- These are default printing options. For a release version, error only. For a debug version, maybe warnings too.
me.default = 
{
	info = false,
	warning = false,
	error = true,
}

me.onfileload = function()

	-- optional debug specification
	me.setprintstatus("save", "override", "info", true)

end

--[[  
Suppose the following method calls were made:
	me.setprintstatus("boss", nil, "warning", true)
	me.setprintstatus("boss", "event", "info", true)
	
Then me.override would look like
me.override = 
{
	boss = 
	{
		warning = true
		error = true
		sections = 
		{
			event = 
			{
				info = true
				warning = true
				error = true
			}
		}
	}
}

See <me.setprintstatus> for more information
]]
me.override = {  }

--[[ 
me.setprintstatus(modulename, sectionname, messagetype, value)
		Overrides the default print option for a specific trace print.
<modulename> is a string, the source of the print, e.g. "out" for this module.
<sectionname> is a string, a feature in the source module. e.g. "trace" for this section.
<messagetype> is either "info" or "warning" or "error".
<value> is a boolean, true to enable the print, false to disable it.

<sectionname> is an optional parameter. If it is nil, the override will apply to the whole module, but it is now less specific, so an individual section inside that module may be overriden again.
<messagetype> will automatically cascade. "error" is assumed to be more important than "warning", which is more important than "info". So if you turn "warning" off, it will turn "info off as well"; if you turn "info" on, "warning" and "error" will be turned on too.
]]
me.setprintstatus = function(modulename, sectionname, messagetype, value)

	-- check module exists
	if me.override[modulename] == nil then
		me.override[modulename] = { }
	end
	
	local printdata = me.override[modulename]
	
	-- is this for the whole module, or more specific?
	if sectionname then
		
		-- check whether any sections have been defined for this module
		if printdata.sections == nil then
			printdata.sections = { }
		end
		
		printdata = printdata.sections
		
		-- check whether this section has been defined in the sections list
		if printdata[sectionname] == nil then
			printdata[sectionname] = { }
		end
		
		printdata = printdata[sectionname]
	end
	
	-- set
	printdata[messagetype] = value
	
	-- cascade
	if value == true then
		if messagetype == "info" then
			printdata.warning = true
			messagetype = "warning"
		end
		
		if messagetype == "warning" then
			printdata.error = true
		end
	
	elseif value == false then
		if messagetype == "error" then
			printdata.warning = false
			messagetype = "warning"
		end
		
		if messagetype == "warning" then
			printdata.info = false
		end
	end

end

--[[ 
mod.trace.check(messagetype, module, sectionname)
Checks whether a debug print with the given properties should be printed.
Return: non-nil iff the message should be printed.
<messagetype> must be one of "error", "warning" or "info"
<module> should always be <me> in the calling context; i.e. a table with <.name> property.
<sectionname> is a description of the feature in <module> that the message concerns.
]]
me.check = function(messagetype, module, sectionname)
	
	-- start with default print value
	local value = me.default[messagetype]
	me.printargs.overridelevel = "default"
	
	-- convert module reference to name
	local modulename = module.name or "unknown"
	
	-- are there any overrides for that module?
	local printdata = me.override[modulename]
	
	if printdata then
		if printdata[messagetype] then
			value = printdata[messagetype]
			me.printargs.overridelevel = "module"
		end
		
		-- are there overrides for this section of the module?		
		if printdata.sections and printdata.sections[sectionname] and (printdata.sections[sectionname][messagetype] ~= nil) then
			value = printdata.sections[sectionname][messagetype]
			me.printargs.overridelevel = "section"
		end
	end
	
	-- pre-return: load arguments for me.printtrace
	me.printargs.modulename = modulename
	me.printargs.sectionname = sectionname
	me.printargs.messagetype = messagetype
	
	-- return: nil or non-nil
	if value == true then
		return true
	end
	
end

-- This stores the options supplied to <me.checktrace>, which will slightly affect the printout.
me.printargs = 
{
	messagetype = "",
	modulename = "",
	sectionname = "",
	overridelevel = "",
}

--[[
mod.trace.print(message)
Prints a message that has been OK'd by <me.check>.
]]
me.print = function(message)

	-- setup the colour. Error = red, warning = yellow, info = blue. Lightish colours.
	local header = ""
	
	if me.printargs.messagetype == "info" then
		header = "|cff8888ff"
	
	elseif me.printargs.messagetype == "warning" then
		header = "|cffffff44"
	
	elseif me.printargs.messagetype == "error" then
		header = "|cffff8888"
	end
	
	--	convert |r in the message to the header colouring
	message = string.gsub(message, "|r", header)
	
	-- add the header
	message = string.format("%s<%s.%s> %s", header, me.printargs.modulename, me.printargs.sectionname, message)
		
	-- print!
	mod.print(message)
	
end

me.onfileload()