/*
	unFocus.Utilities.EventManager, version 1.0b (beta) (2005/12/16)
	Copyright: 2005, Kevin Newman (http://www.unfocus.com/Projects/)
	License: http://creativecommons.org/licenses/LGPL/2.1/
*/
// make sure faux-namespace is available before adding to it
if (typeof unFocus == "undefined") var unFocus = {};
if (!unFocus.Utilities) unFocus.Utilities = {};

/* Class EventManager
	Provides the interface and functionality to a Subscriber/Subscriber Pattern interface for
	classes to easily inherit or use. Event types are passed in during instantiation. I'm not
	sure that's the best way to do it, but that's how it is for now (comments are welcome). */
unFocus.Utilities.EventManager = function(arg) {
	this._listeners = {};
	for (var i = 0; i < arguments.length; i++) {
		this._listeners[arguments[i]] = [];
	}
};

/* Method: addEventListener
	A public method that adds an event listener to be called when the hash changes. */
unFocus.Utilities.EventManager.prototype.addEventListener = function($type, $listener) {
	// check that listener is not in list
	for (var i = 0; i < this._listeners[$type].length; i++)
		if (this._listeners[$type][i] == $listener) return;
	// add listener to appropriate list
	this._listeners[$type].push($listener);
};

/* Method: removeListener
	A public method that removes an event listener. */
unFocus.Utilities.EventManager.prototype.removeEventListener = function($type, $listener) {
	// search for the listener method
	for (var i = 0; i < this._listeners[$type].length; i++) {
		if (this._listeners[$type][i] == $listener) {
			this._listeners.splice(i,1);
			return;
		}
	}
};

/* Method: notifyListeners
	Notifies listeners when an event accurs. */
unFocus.Utilities.EventManager.prototype.notifyListeners = function($type, $data) {
	for (var i = 0; i < this._listeners[$type].length; i++)
		this._listeners[$type][i]($data);
};


/*
Based on the excellent work of Dean Edwards (and others):
http://dean.edwards.name/weblog/2005/09/busted/
*/

unFocus.Utilities.QuickLoader = (function() {
	var _eventMgr = new unFocus.Utilities.EventManager("_quickLoad", "_quickLoadPriority");
	
	function _quickLoad() {
		// cancel the standard load to prevent double call
		if (document.removeEventListener)
			document.removeEventListener("load", _load, false);
		// prevents double load and cleans up possible memory leak issues in IE
		else if (window.detachEvent) window.detachEvent("onload", _load);
		// call loading script
		_load();
	}
	function _load(e) {
		// trigger listeners
		_eventMgr.notifyListeners("_quickLoadPriority");
		_eventMgr.notifyListeners("_quickLoad"); // :TODO: send the event object
	}
	
	// the following lines all attempt to set up the early load events.
	if (document.addEventListener) {
		// add the quick load for Mozilla (and Opera 9+)
    	document.addEventListener("DOMContentLoaded", _quickLoad, false);
		// fail safe load method (in case the quicker load method fails)
		document.addEventListener("load", _load, false);
	} else if (window.attachEvent)
		window.attachEvent("onload", _load);
	
	// For Safari
	// this doesn't seem to work if the document is small enough
	/*if (/WebKit/i.test(navigator.userAgent)) { // sniff
		var _timer = setInterval(function() {
			if (/loaded|complete/.test(document.readyState)) {
				clearInterval(_timer);
				delete _timer;
				_quickLoad(); // call the onload handler
			}
		}, 10);
	}*/
	
	// For IE (conditional comments would have been better, but they break compression techniques)
	if (window.ActiveXObject && window.print && !window.opera) {
		document.write("<script id=__"+"ie_onload defer src=javascript:void(0)><\/script>");
		var _script = document.getElementById("__"+"ie_onload");
		_script.onreadystatechange = function() {
			if (this.readyState == "complete")
				_quickLoad();
		};
	}
	
	// return an object with public interface
	var _QuickLoader = {
		addListener: function($method, $priority) {
			var $type = (!$priority)?"_quickLoad":"_quickLoadPriority";
			_eventMgr.addEventListener($type, $method);
		},
		removeListener: function($method, $priority) {
			var $type = (!$priority)?"_quickLoad":"_quickLoadPriority";
			_eventMgr.removeEventListener($type, $method);
		}
	};
	return _QuickLoader;
})();