//Define the Synapse Main Object
if(!Synapse)
{
	var Synapse = {};
}


Synapse.Bus = (function(){
	//The actual object
	var that = {};
	//import everything already set
	if(Synapse.Bus)
	{
		for(i in Synapse.Bus)
		{
			that[i] = Synapse.Bus[i];
		}
	}
	//On to definitions
	//The linked list nodes
	var linkedListHolder = function(func, scope, priority)
	{
		if(typeof(func) != 'function')
		{
			throw new {
				'name' 		: 'IllegalArgumentException',
				'message'	: 'Synapse.Bus.linkedListHolder passed not a function for function.'
			};
		}
		this.func = func;
		this.scope = scope;
		this.priority = (priority ? priority : 0);
		this.Child = null;
		this.Parent = null;
	};
	//setting the child
	linkedListHolder.prototype.setChild = function(newChild)
	{
		if(this.Child)
		{
			newChild.Child = this.Child;
			this.Child.Parent = newChild;
		}
		this.Child = newChild; 
		this.Child.Parent = this;
	};
	//setting the parent
	linkedListHolder.prototype.setParent = function(newParent)
	{
		if(this.Parent)
		{
			newParent.Parent = this.Parent;
			this.Parent.Child = newParent;
		}
		this.Parent = newParent;
		this.Parent.Child = this;
	};

	
	
	//Define the instance of the bus
	var busInstance = function()
	{
		//the linked lists
		this.nodeLinkedList = null;
	}
		
		
	busInstance.prototype.addBusNode = function(func, scope, priority)
	{
		var Node = new linkedListHolder(func, scope, priority);
		if(!this.nodeLinkedList)
		{
			this.nodeLinkedList = Node;
		} else {
			var Next = this.nodeLinkedList;
			var Tail = null;
			while(Next !== null && Next.priority >= priority)
			{
				Tail = Next;
				Next = Next.Child;
			};
			if(Tail == null)
			{
				Node.setChild(this.nodeLinkedList);
				this.nodeLinkedList = Node;
			}
			else
			{
				Tail.setChild( Node );
			}
		}
	}
	
	busInstance.prototype.sendMessage = function(Message)
	{
		if(	! Message.subject
			||
			! Message.body
		)
		{
			Synapse.fault('Synapse.Bus.sendMessage','Did not receive a Message with at least a subject and body.');	
		}
		Node = this.nodeLinkedList;
		var returnArray = [];
		while(Node !== null)
		{
			var Scope = (typeof(Node.scope) == 'object' ? Node.scope : Node);
			var returnValue = Node.func.apply(Scope, [Message, returnArray]);
			if(returnValue !== null)
			{
				returnArray[returnArray.length] = returnValue;
			}
			Node = Node.Child;
		};
		return(returnArray);
	};
	
	
	//make it so that only the factory is visible.
	var busesByName = {};
	that.getBus = function(bname) {
		bname = bname.toLowerCase();
		if(! busesByName[bname])
		{
			busesByName[bname] = new busInstance(bname);
		}
		return busesByName[bname];
	};
	return that;
}());	