-----------------------------------------------------------------------------
--
-- EventQueue.lua
--
-- EventQueue is an object queue that also has a dispatching queue.  The
-- idea is to have a system event queue and various listeners that get
-- invoked when new events are added.
--
-- To construct:
--
--	local evq = EventQueue()
--
-- To handle a couple of events thru the dispatcher:
--
--	function myHandler(evt) end
--	local myTable = { timerExpired=myHandler, serialData=myHandler }
--	local myTableIdx = evq.addDispatcher(myTable)
--
-- To unsubscribe:
--
--	evq.clearEntry(myTableIdx)
--
-- To write new events:
--
--	evq.pushBack(Event("timerExpired", { timerName="foo" })
--	evq.pushBack(Event("serialData", { data="12345", otherField=9 })
--
-- To dispatch until queue is empty:
--
--	evq.dispatch()
--
-- To dispatch one event and determine if the queue empty as a result:
--
--	local queueIsEmpty = evq.dispatch(true)
--
-----------------------------------------------------------------------------

require "ObjectQueue"
require "UtilFunc"

function EventQueue()
	local meta = { }
	meta.__index = meta
	meta.__tostring =	function(obj)
					return obj.toString()
				end
	local o = { inDispatcher = false }
	setmetatable(o, meta)
	local self = { q = ObjectQueue(), dt = { } }
	local addDispatcher =	function(dispatchTable)
					table.insert(self.dt, dispatchTable)
					return #self.dt
				end
	local clearEntry =	function(idx)
					self.dt[idx] = nil
				end
	local dispatch =	function(once)
					local item
					if not inDispatcher then
						inDispatcher = true
						repeat
							item = self.q.popFront()
							if item then
								local ename = item.getEventName()
								local v
								for _,v in ipairs(self.dt) do
									if v then
										local match = v[ename]
										if match then match(item) end
									end
								end
							end
						until once or not item
						inDispatcher = false
						return not not item
					else
						return false
					end
				end
	local toString =	function()
					local result = "(EventQueue) "..tostring(q.queueLength()).." items"
					return result
				end
	o.addDispatcher = addDispatcher
	o.clear = self.q.clear
	o.clearEntry = clearEntry
	o.dispatch = dispatch
	o.popFront = self.q.popFront
	o.pushBack = self.q.pushBack
	o.queueLength = self.q.queueLength
	o.toString = toString
	return o
end

