/*
 * TODO
 * - improve requireJS to check for existence of the requested script by href, intead of using the namespace
 */

if(!window.jscore) (function() {
	
	if(!String.trim)
		String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }

	//textSelect
	function rtnFalse(){		
		return false;
	}
	var init_id = 0; //ID for init functions to prevent from calling the callback more than once
	var init_called = {};
	/*
	var queueCheck = function() {
		
		jscore.loadCount--;
		// console.log("Count:" + jscore.loadCount + ", modLoad:"+modLoaded());
		if (jscore.loadCount < 1 && modLoaded()) {
			if (jscore.initProcess == false && jscore.initQueue.length > 0) {
				jscore.initProcess = true;
				
				//jscore.initQueue = [];
				jscore.initProcess = false;
			}
		}
	}
	*/
	
	var loadCheck = function() {
		jscore.initProcess = false; 
		if(jscore.modAllLoaded()) {
			for(var a in jscore.loaded) {
				for(var i in jscore.loaded[a].init) {
					if(jscore.isFunction(jscore.loaded[a].init[i])) {
						if(!(jscore.loaded[a].initid.toString()+i.toString() in init_called)) {
							init_called[jscore.loaded[a].initid.toString()+i.toString()] = true;
							jscore.loaded[a].init[i]();
							//delete jscore.loaded[a].init[i];
						}
					}
				}
			}
		}
	}
	
jscore = {
		config : {
			baseNS : "jscore",
			checkNSOnRequireJS : true,
			basePath : "./"
		},
		Browser: {
			IE: !!(window.attachEvent && !window.opera),
			IE6 : !!(window.attachEvent && !window.opera && navigator.userAgent.indexOf('MSIE 6') > -1),
			IE7 : !!(window.attachEvent && !window.opera && navigator.userAgent.indexOf('MSIE 7') > -1),
			IE8 : !!(window.attachEvent && !window.opera && navigator.userAgent.indexOf('MSIE 8') > -1),
			Opera: !!window.opera,
			WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
			Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
			FF3: !!navigator.userAgent.match(/Gecko.*Firefox.*3/),
			Safari: !!navigator.userAgent.match(/AppleWebKit*Safari/),
			MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
		},
		
		get_init_called : function() {
			return init_called;
		},
		
		//loadCount : 0,
		loaded : {},
		//initQueue : [],
		initProcess : false,
		
		isElement: function(object) {
		return !!(object && object.nodeType == 1);
		},
		
		isObject: function(object) {
		return typeof object == "object";// && !('length' in object);
		},
		
		isArray: function(object) {
		return object != null && typeof object == "object" &&
		  'splice' in object && 'join' in object;
		},
		
		isFunction: function(object) {
		return typeof object == "function";
		},
		
		isString: function(object) {
		return typeof object == "string";
		},
		
		isEmptyString: function(object) {
			if(this.isString(object)) {
				return object == "";
			}
			return true;
		},
		
		isNumber: function(object) {
		return typeof object == "number";
		},
		
		isUndefined: function(object) {
		return typeof object == "undefined";
		},
		
		ce : function (type, p) { // p = object
			if(this.isObject(p)) {
				var element = (this.ge(p['id']) ? this.ge(p['id']) : this.ne(type));
				return this.extend(element, p);
			} else {
				return this.ne(type);
			}
		},
		
		ne: function(type) {
			if(typeof type == 'string') {
				return document.createElement(type);
			}
			
			return null;
		},
		
		ge : function(eleId) {
				if(typeof eleId == 'string' && document.getElementById) {
					if (document.getElementById(eleId)) {
						return document.getElementById(eleId);
					}
				}else if(document.all) {
					if(document.all[eleId]) {
						return document.all[eleId];
					}
				}
				
				return null;
		},
				
		//getElementsByTagName
		geTagName : function(eleName) {
				if(typeof eleName == 'string' && document.getElementsByTagName) {
					if (document.getElementsByTagName(eleName)) {
						return document.getElementsByTagName(eleName);
					}					
				}
				return null;
		},

                geName : function(eleName) {
				if(typeof eleName == 'string' && document.getElementsByName) {
					if (document.getElementsByName(eleName)) {
						return document.getElementsByName(eleName);
					}
				}
				return null;
		},
		
		//Gets the absolute position of an element	
		getPos : function (e){
			
			//* 
			var left = 0,top  = 0,leftSet = false;
			
			if (jscore.isElement(e)) {
				do {
					
					leftSet = false
					
					if (this.Browser.IE6) { //IE Fix to get the correct Left Position
						if(e.style.styleFloat.toLowerCase() == "left") {
							if (e.offsetParent) {
								left += (e.offsetParent.offsetWidth+e.offsetLeft);
								leftSet = true;
							}
						}
					}
					
					if(!leftSet) {
						left += e.offsetLeft;
					}
					top += e.offsetTop;
						
					if(e.offsetParent) {
						e = e.offsetParent;
					} else{
						break;
					}
					
				} while (e.offsetParent);
				
				if (this.Browser.IE6 || this.Browser.IE7) { //IE Fix to get the correct Left Position
					if(e.nodeName == "BODY") {
						left += e.offsetLeft;
						top += e.offsetTop;
					}
				}
				
				//left += this.getScrollLeft();
				//top += this.getScrollTop();
				
				//left += e.offsetLeft;
				//top += e.offsetTop;
			}
	
			return {x:left, y:top}; 
			//*/
			
			/*
			//Prototype Version
			var left = 0,top  = 0,leftSet = false;
			
			if (jscore.isElement(e)) {
				do {
			      top += e.clientTop  || 0;
			      left += e.clientLeft || 0;
			      e = e.offsetParent;
			      if (e) {
			        if (e.tagName.toUpperCase() == 'BODY') break;
			        var p = e.style.position;
			        if (p !== 'static') break;
			      }
			    } while (e);
			}
			return {x:left, y:top}; 
			//*/
		},
		
		textSelect : function(el,selectable) {
			var sel = selectable || false;
			
			if(el) {
				if (this.Browser.IE) {
					(sel ? el.onselectstart = null : el.onselectstart = rtnFalse);
				} else if (this.Browser.Gecko && el.style) {
					el.style.MozUserSelect = (sel ? "" : "none");
				} else {
					(sel ? el.onmousedown = null : el.onmousedown = rtnFalse);
				}

			}
		},
		
		namespace : function(ns) {
			var obj = null,name=[],space=window;
			if(jscore.isString(ns)) {
				name = ns.split(".");
				for(var i=0;i<name.length;i++) {
					space = space[name[i]] = space[name[i]] || {};
				}
			}
			return space;
		},
		
		namespaceExist : function(ns) {
			var obj = null,name=[],space=window;
			if(jscore.isString(ns)) {
				name = ns.split(".");
				for(var i=0;i<name.length;i++) {
					if (space[name[i]]) {
						space = space[name[i]];
					} else {
						return false;
					}
				}
				return true;
			}
			return false;
		},
		
		
		//force - if true creates object if not exist, else extend the current
		//extends up to 2 levels only. Anything more than that will be overwritten.
		//TODO: if possible unlimited level of extending
		//Arguments
		//- dest (String or Object) the namespace object or the namespace in String
		extend : function(dest, src) {
			//var dest=str_dest;
			if(jscore.isString(dest)) {
				dest = this.namespace(dest);
			}

			
			for (var p in src) {
				
				
				if (this.isObject(src[p])) {
					//dest[p] = this.namespace(str_dest+"."+p);
					if(src[p] && !jscore.isArray(src[p]) && !jscore.isElement(src[p])) {
                                                if(!dest[p]) dest[p] = {};
						this.extend(dest[p],src[p]);
						
					} else {
						if(!dest[p]) dest[p] = {};
						dest[p] = src[p];
					}
				} else {
				//console.log(src[p]);
					//IE Checks - Checks for any occurence of 'NaN'
					//IE will trigger an error, causing JS to stall
					if(p == "width" || p == "height") {
						if(jscore.isString(src[p])) {
							dest[p] = "";
							if(src[p].indexOf("NaN")) {
								dest[p] = "100%";
							}
						}
					} else {
						dest[p] = src[p];
					}
					
					//console.log(str_dest+"."+p+" - "+typeof(src[p])+" = "+src[p]);
				}
			}
						
			return dest;

			
		},
		
		cloneObj : function(obj) {
		 	return jscore.extend({},obj);
		},
		
		//Relative path to absolute path
		absoluteURL : function(path) {
			var absurl="",el=null;
			if(this.isString(path)) {
				el=jscore.ne("a");
				el.href=path;
				absurl=el.href;
				delete el;
			}
			
			return absurl;
		},
		
		modAllLoaded : function() {
			var i,loaded=true;
			for(i in jscore.loaded) {
				if(!jscore.loaded[i].stat) {
					loaded = false;
					break;
				}
			}
			return loaded;
		},
		
		require : function(mod,elType,prop,callback,id_init) {
			var file = jscore.ne(elType),cbInit;

			if (elType == "script") {

				//this.loadCount++;
				this.loaded[mod] = {stat:false,init:[],initid:0};
				
				/*
				if (typeof callback == "function") {
					this.initQueue.push (callback);
				}
				*/
				
				if(jscore.isFunction(callback)) {
					this.loaded[mod].init.push(callback);
					if(!jscore.isUndefined(id_init)) {
						this.loaded[mod].initid = id_init;
					}
				}
				
				var fileLoad =  function() {
							if (arguments.callee.done) return;
							
							
							if(mod in jscore.loaded) {
								jscore.loaded[mod].stat = true;
								arguments.callee.done = true;
							} else {
								//jscore.loaded[mod] = {stat:true,init:[],initid:0};
								//arguments.callee.done = true;
							}
							//queueCheck();
							//loadCheck();
							if(!jscore.initProcess) {
							jscore.initProcess = true; 
							setTimeout(loadCheck,10);
							}
						};
				
				if (this.Browser.IE) {
					file.onreadystatechange = function(){
						if (file.readyState == 'complete' || file.readyState == 'loaded') {
							/*
							if (arguments.callee.done) return;
							arguments.callee.done = true;
							jscore.loaded[mod].stat = true;
							//queueCheck();
							if(!jscore.initProcess) {
							jscore.initProcess = true; 
							setTimeout(loadCheck,10);
							}
							//loadCheck();					
							*/
							fileLoad();
						}
					};
				}else if (/Opera/i.test(navigator.userAgent)) { // sniff
						
						if(document.addEventListener)
							document.addEventListener("DOMContentLoaded", fileLoad, false);
				} else  {
					/*
						file.onload = function() {
							if (arguments.callee.done) return;
							arguments.callee.done = true;
							jscore.loaded[mod].stat = true;
							//queueCheck();
							//loadCheck();
							if(!jscore.initProcess) {
							jscore.initProcess = true; 
							setTimeout(loadCheck,10);
							}
						};
						*/
						file.onload = fileLoad;
					}
					
			}

			if(typeof prop == "object")
				this.extend(file,prop);
				
			document.getElementsByTagName('head')[0].appendChild(file);
		},
		
		
		requireCSS : function(modData,cpath) {
			
			if(this.isString(modData)) {
				modData = [modData];
			}

			if (this.isArray(modData)) {
				for (var i = 0; i < modData.length; i++) {
					var mod = modData[i];
					var path = (!this.isUndefined(cpath) ? (this.isString(cpath) ? cpath : "./_css/") : "./_css/") + mod + ".css", absPath = this.absoluteURL(path);
					var found = false, styleSh = document.styleSheets;
					
					//check if css file already been included
					for (var a in styleSh) {
						if (styleSh[a].href == absPath) {
							found = true;
							break;
						}
					}
					
					if (!found) {
						this.require(mod, "link", {
							rel: "stylesheet",
							href: path
						});
					}
				}
			}
		},
		
		/*
		 * Check if JS file & namespace is loaded else load it.
		 * 
		 * If checkNSOnRequireJS in config is true, both File and Namespace will be checked, priority to namespace check
		 * Else if false only File is checked.
		 */
		requireJS : function(modList,callbackInit,altPath) {
			var modData=[];
			
			if(this.isString(modList)) {
				modData = [modList];
			} else if(this.isArray(modList)){
				modData = modList;	
			}
			init_id++;

			if (this.isArray(modData)) {
				var addedCallback = false;
				for (var i = 0; i < modData.length; i++) {
					var mod = modData[i], nsNotFound = true;
					var path = (this.isString(altPath) ? altPath+mod+".js" : this.config.basePath + "_js/" + mod + ".js"), absPath = this.absoluteURL(path);
					var found = false;
					var body = (document.body ? document.body.childNodes : null);
					var head = (document.childNodes[0] ? (document.childNodes[0].nodeName == "HEAD" ? document.childNodes[0].childNodes : null) : null);
					
					//*
					if(!jscore.isUndefined(this.loaded[mod])) {
						found = true;
					}
					//*/
					
					if(this.config.checkNSOnRequireJS && !found) {
						if(this.namespaceExist(this.config.baseNS + "." + mod)) {
							nsNotFound = false;
							return;
						}
					}
					
					if (nsNotFound && !found) {

						//File Check
						if (head) {
							for (var a in head) {
								if (head[a].src && head[a].nodeName == "SCRIPT") {
									if (head[a].src == absPath) {
										found = true;
										break;
									}
								}
							}
						}
						
						if (body && !found) {
							for (var a in body) {
								if (body[a].src && body[a].nodeName == "SCRIPT") {
									if (body[a].src == absPath) {
										found = true;
										break;
									}
								}
							}
						}
						
					}
					/*
						if (!found) {
							if (!addedCallback && this.isFunction(callback)) {
								addedCallback = true;
								//console.log(mod);
								var wrapper = function() {
									var loaded = true;
									var mod = modData;
									for (var i = 0; i < mod.length; i++) {
										if(mod[i] in jscore.loaded) {
											if(!jscore.loaded[modData[i]]) {
												
												loaded = false;
												break;
											}
										}
									}
									
									if(loaded) {
										callback();
									}
								}
								this.require(mod, "script", {
									src: path
								}, wrapper);
							}
							else {
								this.require(mod, "script", {
									src: path
								});
							}
						} else { //If mod already loaded
							if(this.isFunction(callback)) {
								if(this.loadCount > 0) {
									this.initQueue.push (callback);
									//queueCheck();
								} else {
									callback();
								}
								
							}
						}
					*/
					
					/*
					if (this.isFunction(callback)) {
						
						var wrapper = function() {
							var loaded = true;
							var modArr = modData;
							var init = [],i,a;
							
							for (i = 0; i < modArr.length; i++) {
								if(modArr[i] in jscore.loaded) {
									if(!jscore.loaded[modArr[i]].stat) {
										loaded = false;
										break;
									}
								}
							}

							if(loaded) {
								callback();
							}
						}
					}
					*/
					
					
					var callback = null;
					if(this.isFunction(callbackInit)) {
						callback = function() {
							if (arguments.callee.done) return;
								arguments.callee.done = true;
								callbackInit();
						}
					}
					
						if (!found) {
							if (this.isFunction(callback) && !addedCallback) {
								addedCallback = true;
								this.require(mod, "script", {
									src: path
								}, callback,init_id);
							}
							else {
								this.require(mod, "script", {
									src: path
								},null,init_id);
							}
						} else { //If mod already loaded
							if(this.isFunction(callback) && !addedCallback) {
								if(this.modAllLoaded() && !(i<modData.length)) {
									callback();
								} else {
									jscore.loaded[mod].init.push(callback);	
									jscore.loaded[mod].initid = init_id;
								}
								//wrapper();
								/*
								if(this.loadCount > 0) {
									this.initQueue.push (callback);
									//queueCheck();
								} else {
									callback();
								}*/
								
							}
						}
					
				}
			}
		},
		
		Class : {
			create : function(source) {
				var p;
				
				function f() {
					f.prototype._construct.apply(this,arguments);
				}

				if(jscore.isObject(source)) {
					for (p in source) {
						f.prototype[p] = source[p];
					}
				}
				
				if(!f.prototype._construct) {
					f.prototype._construct = function(){};
				}
				
				f.prototype.constructor = f;
				return f;
			}
		},
               endPropogation : function(e) {
                    if (!e) var e = window.event;
                    if (e) {
                    	e.cancelBubble = true;
                    	if (e.stopPropagation) e.stopPropagation();
                    }
                    //return false;
               },
                disableScroll : function(doScroll) {
                    var state = (!doScroll ? "" : "hidden");
                    if(jscore.Browser.IE) {
                            document.body.scroll = (!doScroll ? "yes" : "no");
                            document.documentElement.style.overflow = state;
                    } else {
                            document.body.style.overflow = state;
                    }
                },
                getScrollTop : function() {
                	return document.body.scrollTop || window.pageYOffset || (document.body.parentElement ? document.body.parentElement.scrollTop : 0);
                },
                getScrollLeft : function() {
                	return document.body.scrollLeft || window.pageXOffset || (document.body.parentElement ? document.body.parentElement.scrollLeft : 0);
                },
                elementMovePrev : function(el) {
                    if(jscore.isString(el)) {
                        el = this.ge(el);
                    }
                    if(el) {
                            //console.log(el.previousSibling.previousSibling);
                            
                            if(el.previousSibling) {
                                var preEl = el.previousSibling;
                                if(preEl) {
                                        var parent = el.parentNode;
                                        parent.insertBefore(el,preEl);
                                        //parent.removeChild(el);

                                }

                            }

                    }
                },

                elementMoveNext : function(el) {
                    if(jscore.isString(el)) {
                        el = this.ge(el);
                    }

                    if(el) {
                            

                            var preEl =null;
                            if(el.nextSibling) {
                                    if(el.nextSibling.nextSibling) {
                                            preEl = el.nextSibling.nextSibling;
                                    } else {
                                            //preEl = el.nextSibling;
                                    }

                                    var parent = el.parentNode;
                                    parent.insertBefore(el,preEl);
                            }

                            //if(preEl) {
                                    //var parent = el.parentNode;
                                    //parent.insertBefore(el,preEl);
                                    //parent.removeChild(el);

                            //}


                    }
                },
                getScreenSize : function() {
                    var winW = 630, winH = 460;

                    if (parseInt(navigator.appVersion)>3) {
                     if (navigator.appName=="Netscape") {
                      winW = window.innerWidth;
                      winH = window.innerHeight;
                     }
                     if (navigator.appName.indexOf("Microsoft")!=-1) {
                      winW = document.body.offsetWidth;
                      winH = document.body.offsetHeight;
                     }
                    }

                    return {width:winW,height:winH};

                },
                onload : function(func) {					
					if(typeof func == "function") {
					 if (window.addEventListener){ 
					   window.addEventListener('load', func, false); 

					 } else if (window.attachEvent){ 
					   window.attachEvent("onload", func); 

					 }
					}

                }

	
}

})();

