
local me = { name = "netin"}
local mod = thismod
mod[me.name] = me

--[[
NetIn.lua

4 Feb 07.

The NetIn module mediates incoming network messages. Every addon message will start with one word (block of letters only, no spaces or punctuation) that describes what kind of message it is (the "command"). Then there is optionally one space, then arbitrary text (the "data").

Another module can register to be notified of a particular message by defining a <me.mynetmessages> list like so:

	me.mynetmessages = { "t", "clear", "bossevent" }
	
Then define a function <me.onnetmessage> like so:

	me.onnetmessage = function(author, command, data)
		...
	end

<author> will be the name of the person who send the message. <messagetype> will be one of the values in <me.mynetmessages>. <data> will be the rest of the string after the first space, possibly nil.

The <me.onnetmessage> function can optionally return a value describing any error that occured processing the message. A <nil> return value will be assumed to be a successful message. Recommended values for errors are "permission", if someone sends a message that requires them to be the raid leader or assistant but aren't, and "invalid", if a syntax error occurs, but you're welcome to return other or more detailed values. The NetIn module will keep track of the number of error messages and who they come from.

]]

--[[
Key = message type (string), value = list of strings, module names. e.g.

me.messageregister = 
{
	clear = { "combat", "boss", },
	bossevent = { "boss" },
}	
]]
me.messageregister = { }

--[[
mod.netin.registermessagetype(module, messagetype)

This is called by Core.lua in the last phase of loadup, after modules have loaded. This tells us all the net messages that each module wants to be told about.

<module>			string; name of the module, e.g. "combat",
<messagetype>	string; the message type, e.g. "bossevent".
]]
me.registermessagetype = function(module, messagetype)
	
	if me.messageregister[messagetype] == nil then
		me.messageregister[messagetype] = { }
	end
	
	table.insert(me.messageregister[messagetype], module)
	
end

-- Event service (see Core.lua)
me.myevents = {"CHAT_MSG_ADDON" }

-- Special onevent function from Core.lua
me.onevent = function()

	if event == "CHAT_MSG_ADDON" then
		
		-- check the message comes from this addon, and comes from the party or raid
		if (arg1 ~= mod.global.addonmessageprefix) or ((arg3 ~= "PARTY") and (arg3 ~= "RAID")) then
			return 
		end
		
		-- ok
		me.messagein(arg4, arg2, 1)
		
		return
	end

end

--[[ 
me.messagein(author, message, startindex)

Processes a message from the addon message channel. This is usually called from <me.onevent>. However, when we are not in a party or raid, we can't send Addon Messages, therefore we pretend one has come in by calling this method directly.

<author> is the name of the player who sent the message.
<message> is the original string sent.
<startindex> is the 1-based string index where the message starts.
]] 
me.messagein = function(author, message, startindex)
	
	local command, data
	
	--[[
	get the command (first word) and the data (rest)
	
		"(%a+)"	one or more letters in a row
		" ?"		zero or 1 spaces
		"(.*)"	zero or more of any character
	]]
	_, _, command, data = string.find(message, "^(%a+) ?(.*)", startindex)
	
	-- check that the command is valid
	if (command == nil) or (me.messageregister[command] == nil) then
		
		-- log as unknown
		me.logmessage("unknowncommand", author, command, message)
		return
	end
	
	local module, result, output, success
	
	-- send the command to all the interested modules. <result> starts as <nil> indicating success. If the result value of one of the <onnetmessage> handlers is nil, result will become non-nil.
	for _, module in pairs(me.messageregister[command]) do
		
		success, output = pcall(mod[module].onnetmessage, author, command, data)
		
		if success == false then
			mod.error.reporterror(module, "onnetmessage", output, command, data)
			
		else
			result = result or output
		end
		
	end
	
	-- log error / success
	me.logmessage(result, author, command, message)
		
end

--[[
me.logmessage(result, author, command, message)

Makes a note of the success or failure in parsing an incoming network message. 

<result>		string; what happened. <nil> for success, otherwise e.g. "unknowncommand", "syntax", etc,
<author>		string; name of the person who send the message,
<command>	string; addon command sent, possibly nil
<message>	string; the complete original message
]]
me.logmessage = function(result, author, command, message)

	-- Well... this kinda needs some work, hey!

	-- DEBUG
	if result then
		-- mod.print(string.format("net error; result = %s, author = %s, message = %s.", result, author, message))
	end
	
end