// 8< ---[eventbus.js]---

var eventbus=eventbus||{}
var self=eventbus
eventbus.Applet=extend.Class({
	name:'eventbus.Applet', parent:undefined,
	properties:{
		ui:undefined,
		bus:undefined,
		ACTIONS:undefined
	},
	initialize:function(bus, selector){
		var self=this
		selector = selector === undefined ? '.EventBus' : selector
		self.ACTIONS = []
		self.bus = bus;
		self.ui = $(selector);
		self.bindUI()
	},
	methods:{
		bindUI:function(){
			var self=this
			extend.iterate(self.ACTIONS, function(c){
				actions[c] = $(('.do-' + c), self.ui).click(self.getMethod(c));
			}, self)
			$('.header', self.ui).click(function(){
				$('.events', self.ui).slideToggle()
			})
			self.bus.onEvent(function(e){
				self.addEvent(e)
			})
			self.addEvent({'name':'Bus initialized'})
		},
		addEvent:function(event){
			var self=this
			var view=$('.templates .event', self.ui).clone();
			$('.eventName .value', view).html(event.name)
			$('.events', self.ui).prepend(view)
		}
	}
})
eventbus.EventBus=extend.Class({
	name:'eventbus.EventBus', parent:undefined,
	properties:{
		RETRY_DELAY:undefined,
		RETRY_COUNT:undefined,
		channel:undefined,
		url:undefined,
		handlers:undefined,
		specificHandlers:undefined,
		retryCount:undefined,
		onFailure:undefined,
		onClose:undefined,
		isConnected:undefined,
		isOpen:undefined,
		_currentFuture:undefined
	},
	initialize:function(iteratorURL){
		var self=this
		self.RETRY_DELAY = (5 * 1000)
		self.RETRY_COUNT = -1
		self.channel = new channels.AsyncChannel()
		self.handlers = []
		self.specificHandlers = {}
		self.retryCount = self.RETRY_COUNT
		self.onFailure = function(_){
		}
		self.onClose = function(_){
		}
		self.isConnected = false
		self.isOpen = false
		self._currentFuture = undefined
		self.url = iteratorURL;
	},
	methods:{
		start:function(position){
			var self=this
			position = position === undefined ? undefined : position
			if ( (! self.isOpen) )
			{
				self.isOpen = true;
				self.readFromIterator(position)
			}
		},
		unbind:function(event){
			var self=this
		},
		onEvent:function(handler){
			var self=this
			self.handlers.push(handler)
		},
		on:function(event, handler){
			var self=this
			if ( (self.specificHandlers[event] === undefined) )
			{
				self.specificHandlers[event] = [];
			}
			self.specificHandlers[event].push(handler)
		},
		stop:function(){
			var self=this
			self.isOpen = false;
			self._currentFuture.cancel()
		},
		dispatchEvent:function(event){
			var self=this
			var count=0;
			extend.iterate(self.handlers, function(handler){
				handler(event)
				count = (count + 1);
			}, self)
			if ( (count < self.handlers.length) )
			{
				alert((('Generic message bus handler ' + count) + 'failed'))
			}
			count = 0;
			extend.iterate(self.specificHandlers[event.name], function(handler){
				handler(event)
				count = (count + 1);
			}, self)
			if ( (self.handlers[event.name] && (count < self.handlers[event.name].length)) )
			{
				alert((((('Specific message bus handler ' + event.name) + '/') + count) + 'failed'))
			}
		},
		// Reads data from the reader iterator provided by the discussion service.
		readFromIterator:function(iteratorPosition){
			var self=this
			iteratorPosition = iteratorPosition === undefined ? undefined : iteratorPosition
			self.isConnected = true;
			var bus_url=self.url;
			itaratorPosition = parseInt(iteratorPosition);
			iteratorPosition = Math.max(0, iteratorPosition);
			if ( isNaN(iteratorPosition) )
			{
				iteratorPosition = undefined;
			}
			if ( ((iteratorPosition != undefined) && (('' + iteratorPosition) != '[object]')) )
			{
				bus_url = (bus_url + ('/' + iteratorPosition));
			}
			var future=self.channel.get(bus_url).onSucceed(function(result){
				self.isConnected = true;
				self.retryCount = self.RETRY_COUNT;
				extend.iterate(result.value, function(received_event){
					if ( (received_event == 'EOF') )
					{
						self.isOpen = false;
						self.onClose()
					}
					else if ( true )
					{
						self.dispatchEvent(received_event)
					}
				}, self)
				if ( self.isOpen )
				{
					if ( (result.position === undefined) )
					{
						self.readFromIterator(iteratorPosition)
					}
					else if ( true )
					{
						self.readFromIterator((result.position || iteratorPosition))
					}
				}
			}).onFail(function(){
				self.isConnected = false;
				if ( (self.isOpen && (self.retryCount > 0)) )
				{
					self.retryCount = (self.retryCount - 1);
					window.setTimeout(function(){
						self.readFromIterator((iteratorPosition || 0))
					}, self.RETRY_DELAY)
				}
				else if ( (self.retryCount == -1) )
				{
					window.setTimeout(function(){
						self.readFromIterator((iteratorPosition || 0))
					}, self.RETRY_DELAY)
				}
				else if ( true )
				{
					self.onFailure()
				}
			});
			self._currentFuture = future;
			return future
		}
	}
})
eventbus.init=	function(){
		var self=eventbus;
	}
eventbus.init()

