/**
 * Signals and Slots plugin for Centrik
 * @link http://customr.net
 * @copyright Copyright (c) 2009 James Ellis http://customr.net
 * @license Licensed under the MIT license
 * @since 0.1 (17.02.2009)
 * @depends jquery >= 1.3.1
 */

/**
 * centrik_signaller
 * hits multiple slots when a signal is emited ( emit() )
 * a signaller can contain one signal which can hit many slots
 */
jQuery.centrik_signaller = {
	slots : [],
	signalo : null,
	emit : function(args) {
		try {
			var result = this.signal.apply(this, args);
			this.hitslots(result);//hit slots
		} catch (e) {
			throw('Error: cannot emit signal "' + this.signal + '" with exception "' + e + '"');
		}
	},
	addsignal : function(sigo, signal) {
		this.signal = sigo[signal];
	},
	addslot : function(sloto, slot, priority) {
		this.slots.push(sloto[slot]);
	},
	hitslots : function(result) {
		for(i=0;i<this.slots.length;i++) {
			this.slots[i](result);
		}
	}
}

/**
 * centrik_signal_slot
 * registers signals and their slot(s)
 * signal objects can be window,document, a DOM element or an Object
 * signals can be a JS event or a method on an Object
 * slot objects are only hit if the signal object is an Object
 * slots are anonymous functions
 * priority is not yet supported
 */
jQuery.centrik_signal_slot = {
	signals : {},
	signalprefix : '__CENTRIK_SIGNAL_',
	signallerprefix : '__CENTRIK_SIGNALLER_',
	slotprefix : '__CENTRIK_SLOT_',
	connect : function(sigo, signal, sloto, slot, priority) {
		if(sigo == document || sigo == window) {
			$(sigo).bind(signal, slot);
		} else if('object' == typeof sigo) {
			var _signal = this.signalprefix + signal;//the prefixed signal name
			if(!sigo[_signal]) {
				//signaller not yet attached
				sigo[_signal] = jQuery.centrik_signaller;
				sigo[_signal].addsignal(sigo, signal);
			}
			sigo[_signal].addslot(sloto, slot, priority);//add the slot - one signal can call hit multiple slots
			//when original method called, hit emit in the signaller instead, pass in local arguments collection as arguments
			sigo[signal] = function() {
				sigo[_signal].emit(arguments);
			}
		} else if($('#' + sigo).length > 0) {
			//a DOM element
			//if slot is not an anonymous function -- make it so, calling sloto.slot(this)
			$('#' + sigo).bind(signal, slot);
		} else {
			throw('Error: cannot attach signal ' + signal + ' to non existent object --> ' + sigo);
			return false;
		}
		return true;
	},
	disconnect : function(sigo, signal) {
			var _signal = this.signalprefix + signal;//the prefixed signal name
			sigo[signal] = sigo[_signal];
			sigo[_signal] = null;
	}
}

//Examples
/**
jQuery.centrik_signal_slot.connect(document, 'ready', null, functionjQuery.centrik_signal_slot() { alert('domready'); }, 0);
jQuery.centrik_signal_slot.connect(window, 'load', null, function() { alert('loaded 1'); }, 0);
jQuery.centrik_signal_slot.connect(window, 'load', null, function() { alert('loaded 2'); }, 0);
jQuery.centrik_signal_slot.connect('logo', 'click', null, function() { alert('click'); }, 0);

var greeting = {
	hi : function(nm) { alert('hi ... ' + nm); },
	bye : function() { alert('bye'); }
}

jQuery.centrik_signal_slot.connect(greeting, 'hi', greeting, 'bye', 0);
greeting.hi('bill');
**/