/**
 * A simple collaboration mechanism.
 *
 * Requires:
 *	Arrays.js
 */

Arrays.augmentArrayPrototype();

function Publisher(self)
{
	self.itsSubscribers = new Array();
	self.itsNotificationFunctions = new Array();
	self.itsBufferedNotification = null;
	self.isHoldingNotifications = false;


	self.addSubscriber = function(inSubscriber,inNotificationFunction)
	{
		var theIndex;

		theIndex = self.itsSubscribers.indexOf(inSubscriber);
		if (theIndex < 0)
			theIndex = self.itsSubscribers.length;
		self.itsSubscribers[theIndex] = inSubscriber;
		self.itsNotificationFunctions[theIndex] = inNotificationFunction;
		return (self);
	};


	self.removeSubscriber = function(inSubscriber)
	{
		var theIndex;

		theIndex = self.itsSubscribers.indexOf(inSubscriber);
		if (theIndex >= 0)
		{
			self.itsSubscribers.splice(theIndex,1);
			self.itsNotificationFunctions.splice(theIndex,1);
		}
		return (self);
	};


	self.notifySubscribers = function()
	{
		var theArguments;

		if (self.itsSubscribers.length == 0)
			return (self);

		if (self.itsNotificationFunctions.length == 0)
			return (self);

		theArguments = Array.prototype.slice.apply(arguments,[0]);
		theArguments[theArguments.length] = self;

		if (self.isHoldingNotifications)
		{
			self.itsBufferedNotification = {
				subscribers: self.itsSubscribers.slice(0),
				functions: self.itsNotificationFunctions.slice(0),
				data: Array.prototype.slice.apply(arguments,[0]) };
			return (self);
		}

		return (notify(self.itsSubscribers,self.itsNotificationFunctions,theArguments));
	};


	self.holdNotifications = function()
	{
		self.isHoldingNotifications = true;
	};


	self.resumeNotifications = function()
	{
		if (self.itsBufferedNotification != null)
		{
			with (self.itsBufferedNotification)
				notify(subscribers,functions,data);
			self.itsBufferedNotification = null;
		}

		self.isHoldingNotifications = true;
	};


	function notify(inSubscribers,inNotificationFunctions,inData)
	{
		var i;

		for (i = 0; i < inSubscribers.length; i++)
			inNotificationFunctions[i].apply(inSubscribers[i],inData);
		return (self);
	}


	return (self);
}
