
/**
*	BaseClass
*
*	Base object that other classes should extend.
*/


//	Factory that extends and creates divs
var BaseClass = Class.create();

BaseClass.prototype = {
	classid : "BaseClass",
	log:null,
	disableLog:false,
	logLoaded:false,
	
	hSettingsCookie:"_hSettings",
	//	Set variables about what kind of browser we have
	//	Check browser capabilities and set variables
	ie4:document.all,
	dom:(document.getElementById?true:false),
	
	//	Used to register global references to objects
	CBOBJ_NAME : "__globa1ca11bobj",
	
	initialize : function(el) {
		this.createLogger();
		},
	
	getClassId : function(){
		return this.classid;
		},
	/**
	*	Convert into an array, if a single string, number, or object
	*	then convert to a single element array
	*/
	makeArray: function(val){
		var t=typeof val;
		if((t===null) || (t=="string") || (t=="number") || ((t=="object") && !t.length)){
			val=$A([val]);
			}
		else if((t=="object") && t.length){
			val=$A(val);
			}
		else{
			val=$A(val);
			this.log.error("Trying to convert variable " + val + " to array, is not the appropriate type, type is " + t);
			}
		return val;
		},
	addRollover: function(img){
		var id=img._observeId;
		if(!id){
			id=__c0mm0n.overImgListeners.length;
			img._observeId=id;
			}
		var imgSrc=img.src;
		var imgOverSrc=this.cacheOverImg(img);
		var list=__c0mm0n.overImgListeners[id];
		if(!list){
			list=__c0mm0n.overImgListeners[id]={
				over:this.swapImage.bindAsEventListener(this,imgOverSrc),
				off:this.swapImage.bindAsEventListener(this,imgSrc)
				};
			}
		//	Add event listener to over state
		Event.observe(img, 'mouseover', list.over);
		Event.observe(img, 'mouseout', list.off);
		},
	removeRollover: function(img){
		var id=img._observeId;
		if(!id){this.log.warn("removeRollover() Could not obtain observer id from image, can not unregister rollover.");return;}
		var imgSrc=img.src;
		var list=__c0mm0n.overImgListeners[id];
		if(!list){this.log.warn("Can not find listener for roll over on img " + imgSrc);return;}
		Event.stopObserving(img, 'mouseover', list.over);
		Event.stopObserving(img, 'mouseoout', list.off);
		__c0mm0n.overImgListeners[id]=null;
		},
	cacheOverImg: function(img){
		is=img.src;var ext=".gif";
		if(!is){return;}
		var ePos=is.indexOf(ext);
		if(ePos<0){
			ext=".jpg";ePos=is.indexOf(ext);
			}
		if(ePos<0){
			this.log.warn("Could not get extension for image src " + is);
			return;
			}
		var numb=Number.NaN;
		var stateStr="";
		//	Build the src string of the roll over image
		//	Check if the image has an ending of _f3 or _f4, etc, if so,
		//	remove this ending before adding the _f2, this allows for handling of 
		//	images with "on" states that still need to "roll-over" to _f2
		if(is.indexOf("_f")>0){
			//	Get "state", number after "_f" string
			stateStr=is.lastIndexOf("_f");
			numb=is.substring(stateStr+2,ePos);
			}
		//	If state is a number, build the imgSrc variable without
		//	the "_fx" ending, otherwise just add "_f2" to base file name
		if(!isNaN(parseInt(numb))&&(stateStr!="")){
			imgSrc=is.substring(0,stateStr) + "_f2"+ext;
			}
		else imgSrc=is.substring(0,ePos) + "_f2"+ext;
		//	Get over image src name and cache
		if(!document["__imgcache"+imgSrc]){
			document["__imgcache"+imgSrc]=new Image();
			document["__imgcache"+imgSrc].src=imgSrc;
			}
		return imgSrc;
		},
	swapImage: function(evt,newSrc){
		var img = Event.element(evt);
		img.src=newSrc;
		},
	getHashSetting: function(key){
		this.parseHashSettings();
		return __c0mm0n.hSettings[key];
		},
	saveHashSetting: function(key,value){
		this.parseHashSettings();
		__c0mm0n.hSettings[key]=value;
		var jsn=Object.toJSON(__c0mm0n.hSettings);
		Cookie.set(this.hSettingsCookie,encodeURIComponent(jsn),15,this.getWebroot());
		},
	parseHashSettings: function(){
		if(__c0mm0n.hSettings.init==false){
			var hashStr=Cookie.get(this.hSettingsCookie);
			//this.log.warn("Hash string is " + hashStr);
			if(hashStr){
				__c0mm0n.hSettings=decodeURIComponent(hashStr).evalJSON(true);
				}
			__c0mm0n.hSettings.init==true;
			}
		},
	/**
	*	getScreenHeight
	*	Returns the screen height.
	*/
	getScreenHeight: function(){
		if(window.innerHeight){return window.innerHeight;}//	Dom except IE
		if(document.documentElement.clientHeight&&(document.documentElement.clientHeight>0)){
			//	 IE 6 strict
			return document.documentElement.clientHeight;
			}
		else if(document.body.clientHeight){
			//	IE 4 and 5-7 quirks mode
			return document.body.clientHeight;
			}
		return 0;
	},	//	getScreenHeight
	/**
	*	getScreenWidth
	*	Returns the screen width.
	*/
	getScreenWidth: function(){
		if(window.innerWidth){return window.innerWidth;}//	Dom except IE
		if(document.documentElement.clientWidth&&(document.documentElement.clientWidth>0)){
			//	IE 4 and 5-7 quirks mode
			return document.documentElement.clientWidth;
			}
		else if(document.body.clientWidth){
			//	 IE 6 strict
			return document.body.clientWidth;
			}
		return 0;
	},	//	getScreenWidth
	/**
	*	getScrollHorizontal
	*	Returns the amount the window is scrolled horizontally.
	*/
	getScrollHorizontal: function(){
		if(window.pageXOffset){
			return window.pageXOffset;
			}
		else if(document.body.scrollLeft){
			return document.body.scrollLeft;
			}
		return 0;
	},
	/**
	*	getScrollVertical
	*	Returns the amount the window is scrolled vertically.
	*/
	getScrollVertical: function(){
		if(window.pageYOffset){
			return window.pageYOffset;
			}
		else if(document.body.scrollTop){
			return document.body.scrollTop;
			}
		return 0;
	},
	/**
	*	addTimeoutCall
	*	Creates a setTimeout that calls a method of an object after a delay. Saves
	*	the object/method call in the globalCallbackObject bound to the obj so the method can
	*	execute in the proper scope.  Can also pass a parameter object to the method.
	*/
	addTimeoutCall: function(obj,method,delay,params){
		window.setTimeout(this.getGlobalCallbackStr(obj,method,params,true),delay);
	},
	/**
	*	addIntervalCall
	*	Creates a setInterval that repeatedly calls a method of an object after a delay. 
	*	Saves the object/method call in the globalCallbackObject so the method can
	*	execute in the proper scope.  Can also pass a parameter object to the method.
	*	If a duration is passed, the interval is automatically canceled after the
	*	specified duration.  Returns the id of the interval, use window.clearInterval(id) 
	*	with the returned id to stop the interval call if a duration is not set.
	*/
	addIntervalCall: function(obj,method,delay,params,duration){
		//this.log.info("setInterval(" + obj + ", " + method + "," + delay + "," + params + "," + duration+")");
		var id=window.setInterval(this.getGlobalCallbackStr(obj,method,params,false),delay);
		if(duration && !isNaN(parseInt(duration))){
			this.addTimeoutCall(this,this.clearCallback,duration,id,true);
			}
		return id;
	},
	clearCallback: function(id){
		var cbo=this.getGlobalCallbackObject();
		cbo.clearFunction(id);
	},
	/**
	*	getGlobalCallbackStr
	*	Creates a string containing a global function call that can call the passed 
	*	object's method with the included parameters.  Used in addTimeoutCall() and
	*	addIntervalCal() methods.  Can be used to register an out of scope call to an 
	*	object without having to save a global variable reference to that object.
	*/
	getGlobalCallbackStr: function(obj,method,params,clear){
		var cbo=this.getGlobalCallbackObject();
		var id=this.buildUniqueId(cbo, "cb");
		cbo[id]={clear:clear,method:method.bind(obj,params)};
		//this.log.warn("global call back object is " + this.CBOBJ_NAME+".callFunction('"+id+"')");
		return "document['"+this.CBOBJ_NAME+"'].callFunction('"+id+"')";
	},
	/**
	*	getGlobalCallbackObject
	*	Returns a reference to the global callback object. This object functions
	*	as a singleton, only one should be created per document.
	*/
	getGlobalCallbackObject: function(){
		if(__c0mm0n.gCallbacks != null){return __c0mm0n.gCallbacks;}
		if((document[this.CBOBJ_NAME]===undefined)||(document[this.CBOBJ_NAME]===null)){
			document[this.CBOBJ_NAME]={
				callFunction:function(id){
					if(this[id]){this[id].method();if(this[id].clear){this[id]=null;}}
					},
				clearFunction:function(id){if(this[id]){this[id]=null;}}
				}
			}
		__c0mm0n.gCallbacks=document[this.CBOBJ_NAME];
		//this.log.warn("Returning " + __c0mm0n.gCallbacks);
		return __c0mm0n.gCallbacks;
	},
	disableLogging : function(disable){this.disableLog=disable;},
	createLogger : function(){
		/**
		*	createLogger
		*	Initially creates logger stub, which will be replaced by 
		*	log4javascript logger if/when it loads.
		*/
	
		if(this.logLoaded == false){
			if((!this.ignoreLogs) && (typeof log4JsLogger == "object")){
				//	Write logs that were saved while logger 
				//	was loaded to logger
				if(this.log!==null)this.log.writeSavedLogs(log4JsLogger);
				this.log=log4JsLogger;
				this.logLoaded = true;
				}
			else if(this.log === null){
				if(this.disableLog){
					//	Just load temp logger
					this.logLoaded = true;
				}
				this.log = new TempLogger(this,this.disableLog);
				return;
				}
			}
		//	createLogger
	},
	
	buildUniqueId : function(object, baseName){
		/**
		*	buildUniqueId
		*	Builds a unique property name for an associative array object, 
		*	takes an object, and a base name, and adds numbers to
		*	the base name until there are no properties in the object
		*	that have the same name, returns the unique name.
		*/
	
		if(!object && (typeof object!="object"))return null;
		if(!object[baseName])return baseName;
		var numb=0;
		var name;
		while (numb < 200){
			name=baseName+this.getTwoDigitString(numb);
			if(!object[name])break;
			numb++;
			}
		return name;
	},
	getTwoDigitString : function(numb){
		if(!numb) numb = 0;
		var nStr = "0";
		if(numb < 10) nStr += new String(numb);
		else nStr = new String(numb);
		return nStr;
		},
	/**
	*	Check whether this page is loaded from an alternative port, if so
	*	assume its running locally, and get context path as webroot, otherwise
	*	use the root of the web site "/".
	*/
	getWebroot: function(){
		var webroot=document.location.href;
		var port=":8080/";
		var ssdev="ssdev1/";
		var loc=webroot.indexOf(port);
		var devloc=webroot.indexOf(ssdev);
		if((loc<0) && (devloc<0)){return "/";}
		if(loc>=0){
			var loc2=webroot.indexOf("/",loc+port.length);
			webroot=webroot.substring(loc+port.length - 1,loc2 + 1);
			}
		else{
			var loc2=webroot.indexOf("/",devloc + ssdev.length);
			webroot=webroot.substring(devloc + ssdev.length - 1,loc2 + 1);
			}
		return webroot;
		}
};



/**
 * global object created to store shared settings and references
 * used by the methods of the BaseClass
 */
var __c0mm0n={
	/* 
	 * bound event listeners used in image roll overs, 
	 * references saved so they can be unbound if needed
	 */
	overImgListeners:[],
	/* settings hash loaded from cookies : */
	hSettings:{init:false},
	/*
	 * Global callback object, used to schedule timed
	 * callbacks that keep object scope
	 */
	gCallbacks:null
	}



//	Extend Event object to add domReady event
Object.extend(Event, {
  _domReady : function() {
    if (arguments.callee.done) return;
    arguments.callee.done = true;

    if (this._timer)  clearInterval(this._timer);
    
    this._readyCallbacks.each(function(f) { f() });
    this._readyCallbacks = null;
	},
  onDOMReady : function(f) {
    if (!this._readyCallbacks) {
      var domReady = this._domReady.bind(this);
      
      if (document.addEventListener)
        document.addEventListener("DOMContentLoaded", domReady, false);
        
        /* @cc_on @ */
		
        /* @if (@_win32)
            document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
            document.getElementById("__ie_onload").onreadystatechange = function() {
                if (this.readyState == "complete") domReady(); 
            };
        */
        /* @end @ */
        
        if (/WebKit/i.test(navigator.userAgent)) { 
          this._timer = setInterval(function() {
            if (/loaded|complete/.test(document.readyState)) domReady(); 
          }, 10);
        }
        
        Event.observe(window, 'load', domReady);
        Event._readyCallbacks =  [];
    }
    Event._readyCallbacks.push(f);
  }
});


var Cookie = {
  set: function(name, value, daysToExpire, path) {
    var expire = '';
	var pathStr = '';
    if (daysToExpire) {
      var d = new Date();
      d.setTime(d.getTime() + (86400000 * parseFloat(daysToExpire)));
      expire = '; expires=' + d.toGMTString();
    }
	if(path){pathStr ='; path=' + path;}
	return (document.cookie = escape(name) + '=' + escape(value || '') + expire + pathStr);
  },
  get: function(name) {
    var cookie = document.cookie.match(new RegExp('(^|;)\\s*' + escape(name) + '=([^;\\s]*)'));
    return (cookie ? unescape(cookie[2]) : null);
  },
  erase: function(name) {
    var cookie = Cookie.get(name) || true;
    Cookie.set(name, '', -1);
    return cookie;
  },
  accept: function() {
    if (typeof navigator.cookieEnabled=='boolean') {
      return navigator.cookieEnabled;
    }
    Cookie.set('_test', '1');
	var suc=((Cookie.erase('_test') == '1')?true:false)
    return suc;
  }
};


//	Temp stub logger object, used while log4javascript logger loads,
//	if passed true to constructor, it will not keep logged messages
function TempLogger(parent,ignoreLogs){
		this.parent=parent;
		this.msgs={debug:[],info:[],warn:[],error:[],fatal:[],trace:[]};
		this.msgs.info.push("loaded temporary logger..");
		this.ignoreLogs=(ignoreLogs?ignoreLogs:false);
		this.debug=tLog_debug;
		this.info=tLog_info;
		this.warn=tLog_warn;
		this.error=tLog_error;
		this.fatal=tLog_fatal;
		this.trace=tLog_trace;
		this.writeSavedLogs=tLog_writeSavedLogs;
		this.writeLogs=tLog_writeLogs;
	};
	tLog_debug=function(msg){if(!this.ignoreLogs){this.msgs.debug.push(msg);this.parent.createLogger();}};
	tLog_info=function(msg){if(!this.ignoreLogs){this.msgs.info.push(msg);this.parent.createLogger();}};
	tLog_warn=function(msg){if(!this.ignoreLogs){this.msgs.warn.push(msg);this.parent.createLogger();}};
	tLog_error=function(msg){if(!this.ignoreLogs){this.msgs.error.push(msg);this.parent.createLogger();}};
	tLog_fatal=function(msg){if(!this.ignoreLogs){this.msgs.fatal.push(msg);this.parent.createLogger();}};
	tLog_trace=function(msg){if(!this.ignoreLogs){this.msgs.trace.push(msg);this.parent.createLogger();}};
	tLog_writeSavedLogs=function(logger){
		for(type in this.msgs){this.writeLogs(logger,type,this.msgs[type]);}
	};
	tLog_writeLogs=function(logger,type,msgs){
		for(var i=0; i<msgs.length; i++){logger[type](msgs[i]);}
		};


	
