/**
 * @author christopher
 */

var JDIF_BaseURI = "/js/JDIF/";


/////////////////////////////////

var isset = function(obj) {
	return (typeof(obj) == "undefined"); 
}




var is_array = function(v){
    return v &&
    typeof(v) === "object" &&
    typeof(v.length) === "number" &&
    typeof(v.splice) === "function" &&
    !(v.propertyIsEnumerable("length"));
};

/////////////////////////////////////////////////


if (typeof Object.beget !== 'function') {
	Object.beget = function(o) {
    	var F = function() {};
        F.prototype = o;
        return new F();
    };
}



if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length;
    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;
    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}



if(!String.prototype.toAssoc) {
	String.prototype.toAssoc = function(outerDelim,innerDelim) {
		var ar = this.split(outerDelim);
		var assoc = [];
		for(var i=0;i<ar.length;i++) {
			var pair = ar[i].split(innerDelim);
			assoc[pair[0]] = pair[1];
		}
		return assoc;		
	}
}






var JDIF = (function() {	
	var myself = {};	
	var core_is_loaded = false;
	
	var core_files = {
		"modules/Misc/misc.js":					0,
		"modules/DOM/dom.js":					0,
		"modules/Form/form.js":					0,
		"modules/JSON/jsonize.js":				0,
		"modules/Calendar/calendar.js":			0,
		"modules/Render/render_engine.js":		0
	};
	
	
	var EventHandler = (function() {
		return {
			bless: function(obj) {
				obj.eventTargets = {};
				obj.subscribe = (function(t) {
					return function(p) {
						if(is_array(p)) {
							for(var i=0;i<p.length;i++) {
								t.subscribe(p[i]);
							}
							return t;
						}
						if(!p.method) {
							p.method = "notify";
						}
						if(!t.eventTargets[p.event]) {
							t.eventTargets[p.event] = [];
						}
						t.eventTargets[p.event].push(p);
						return t;
					}
				})(obj);
				
				obj.unsubscribe = (function(t) {
					return function(p) {
						var ar = t.eventTargets[p.event];
						for(var i=0;i<ar.length;i++) {
							if(ar[i].obj === p.obj) {
								ar.splice(i,1);
							}
						}
					}
				})(obj);
				
				obj.notifySubscribers = (function(t) {
					return function(e) {
						var event = 0;
						var msg = "";
						var sendingObj = 0;
						if(typeof(e === "object") && e.event) {
							event = e.event;
							if(e.msg !== "") {
								msg = e.msg;
							}
							if(e.obj !== 0) {
								sendingObj = e.obj;
							}
						} else {
							event = e;
						}
						if(t.eventTargets[event]) {
							for(var i=0;i<t.eventTargets[event].length;i++) {
								var p = t.eventTargets[event][i];
								if (p.obj[p.method]) {
									if(msg === "") {
										msg = p.msg;
									}
									if(sendingObj === 0) {
										sendingObj = p.obj;
									}
									var notification = {
										obj: sendingObj,
										msg: msg,
										event: event,
										from: t
									};
									p.obj[p.method].call(p.obj,notification);
								} else {
									alert(p.method + " not found.");
								}
							}
						}
					}
				})(obj);
				return obj;
			}
		};
	})();
	
	
	var namespaces = [];
	var namespace = function(n) {
		if(namespaces.indexOf(n) === -1) {
			namespaces.push(n);
		}
	};
	myself.namespace = namespace;
	
	
	
	EventHandler.bless(myself);
	var notifySubscribers = myself.notifySubscribers;
	myself.EventHandler = EventHandler;
	
	myself.notify = function(e) {
		if(e.msg == "libLoaded") {
			myself.cbk_ModuleLoaded(e.event);
		}
	};
	
	myself.ready = function() {
		return core_is_loaded;
	};
	
	myself.cbk_ModuleLoaded = function(m) {
		core_is_loaded = true;
		for (var k in core_files) {
			if (m.indexOf(k) !== -1) {
				core_files[k] = 1;
			}
			if (core_files[k] == 0) {
				core_is_loaded = false;
			}
		}
		if(core_is_loaded) {
			notifySubscribers("onReady");
		}
	};
	
	
	myself.init = function() {
		if(JDIF_Mods) {
			for(var i=0;i<JDIF_Mods.length;i++) {
				core_files[JDIF_Mods[i]] = 0;
			}
		}
		// load core files
		for(var k in core_files) {
			var uri = k;
			if(k.indexOf("/") !== 0 && k.indexOf("http://") !== 0) {
				uri = JDIF_BaseURI + k;
			}
			myself.load(uri,myself);
		}
	};
	
	return myself;
})();






JDIF.LibManager = (function() {
	
	var Library = function(){
		var loaded = {};
		var loaders = [];
		var myself = {};
		
		JDIF.EventHandler.bless(myself);
		var notifySubscribers = myself.notifySubscribers;
		
		myself.add = function(n, v){
			loaded[n] = v;
		};
			
		myself.find = function(n,v) {
			for(var s in loaded) {
				if(s == n) {
					return loaded[s];
				}
			}
			return "unavailable";
		};
		
		myself.register_loader = function(s) {
			loaders.push(s);
		};
		
		myself.notify_ScriptLoaded = function(uri) {
			notifySubscribers(uri);
		};
		
		return myself;
	}();
	
	var _nextLoaderID = 0;
	var nextLoaderID = function() {
		return _nextLoaderID++;
	};
	
	var Loader = function(script,obj,include_buster) {
		var my_id = nextLoaderID();
		var uri = script;
		
		var clusterbuster = function() {
			return Math.random() * 99999999;
		}
		
		var load = function(file,id){
			var head = document.getElementsByTagName("head")[0];
			var sc = document.createElement("script");
			if (JDIF.UserAgent.browser == "Explorer") {
				sc.onreadystatechange = function() {
					if(this.readyState == "loaded" || this.readyState == "complete") {
						Library.notifySubscribers(file);
					}
				};
			} else {
				sc.onload = function() {
					Library.notifySubscribers(file);
				}
			}
			sc.type = "text/javascript";
			sc.src = file;
			if (include_buster) {
				sc.src += "?_buster=" + clusterbuster();
			}
			head.appendChild(sc);
		};
		var owner = obj;
		var owner_cbk_notify = 0;
		var myself = {
			set_owner: function(s,funref) {
				owner = s;
				owner_cbk_notify = funref;
				return this;
			},
			
			go: function() {
				Library.subscribe(
					{
						obj:	owner,
						method:	"notify",
						msg:	"libLoaded",
						event:	uri
					}
				);
				Library.register_loader(this);
				load(uri,my_id);
				myself = this;
				return this;
			},
			
			get_id: function() {
				return my_id;
			},
			
			get_uri: function() {
				return uri;
			},
			
			cbk_Loaded: function() {

			}
		}
		myself.go();
		return myself;
	};
	
	var myself = {
		js: function(uri) {
			load_js(uri);
		},
		
		cbk_Script_Loaded: function(loader_id) {
			Library.notify_ScriptLoaded(loader_id);
		},
		
		cbk_Library_Loaded: function(name,version) {
			Library.add(name,version);
		},
		
		is_available: function(lib) {
			return Library.find(lib);
		},
		
		prepare_loader: function(script,obj) {
			var include_buster = true;
			if(arguments[2]) {
				include_buster = false;
			}
			return Loader(script,obj,include_buster);
		}
	};
	myself.load = myself.prepare_loader;
	me = myself;
	JDIF.load = myself.prepare_loader;
	return myself;
})();


// some base modules
JDIF.Misc = {};
JDIF.DOM = {};
JDIF.Calendar = {};
JDIF.JSON = {};
JDIF.Renderer = {};
JDIF.Factory = {};





JDIF.UserAgent = (function() {
	var BrowserDetect = {
		init: function () {
			this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
			this.version = this.searchVersion(navigator.userAgent)
				|| this.searchVersion(navigator.appVersion)
				|| "an unknown version";
			this.OS = this.searchString(this.dataOS) || "an unknown OS";
		},
		searchString: function (data) {
			for (var i=0;i<data.length;i++)	{
				var dataString = data[i].string;
				var dataProp = data[i].prop;
				this.versionSearchString = data[i].versionSearch || data[i].identity;
				if (dataString) {
					if (dataString.indexOf(data[i].subString) != -1)
						return data[i].identity;
				}
				else if (dataProp)
					return data[i].identity;
			}
		},
		searchVersion: function (dataString) {
			var index = dataString.indexOf(this.versionSearchString);
			if (index == -1) return;
			return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
		},
		dataBrowser: [
			{ 	string: navigator.userAgent,
				subString: "OmniWeb",
				versionSearch: "OmniWeb/",
				identity: "OmniWeb"
			},
			{
				string: navigator.vendor,
				subString: "Apple",
				identity: "Safari"
			},
			{
				prop: window.opera,
				identity: "Opera"
			},
			{
				string: navigator.vendor,
				subString: "iCab",
				identity: "iCab"
			},
			{
				string: navigator.vendor,
				subString: "KDE",
				identity: "Konqueror"
			},
			{
				string: navigator.userAgent,
				subString: "Firefox",
				identity: "Firefox"
			},
			{
				string: navigator.vendor,
				subString: "Camino",
				identity: "Camino"
			},
			{		// for newer Netscapes (6+)
				string: navigator.userAgent,
				subString: "Netscape",
				identity: "Netscape"
			},
			{
				string: navigator.userAgent,
				subString: "MSIE",
				identity: "Explorer",
				versionSearch: "MSIE"
			},
			{
				string: navigator.userAgent,
				subString: "Gecko",
				identity: "Mozilla",
				versionSearch: "rv"
			},
			{ 		// for older Netscapes (4-)
				string: navigator.userAgent,
				subString: "Mozilla",
				identity: "Netscape",
				versionSearch: "Mozilla"
			}
		],
		dataOS : [
			{
				string: navigator.platform,
				subString: "Win",
				identity: "Windows"
			},
			{
				string: navigator.platform,
				subString: "Mac",
				identity: "Mac"
			},
			{
				string: navigator.platform,
				subString: "Linux",
				identity: "Linux"
			}
		]
	
	};
	BrowserDetect.init();
	
	
	var myself = {
		browser:	BrowserDetect.browser,
		version:	BrowserDetect.version
	};
	
	
	return myself;
})();
JDIF.LibManager.cbk_Library_Loaded("UserAgent","1.0");

















///////////////////////////////////////////////////////////
var OnLoad = {
	add: function(fun) {
		if (window.addEventListener) {
			window.addEventListener('load', fun, false);
		} else {
			window.attachEvent("onload",fun);
		}
	}
}

OnLoad.add(
	function() { JDIF.init(); }
)







