/***

DB_Thunder.Base Beta

***/

if (typeof(DB_Thunder) == 'undefined') {
	DB_Thunder = {};
}
if (typeof(DB_Thunder.Base) == 'undefined') {
	DB_Thunder.Base = {};
}
if (typeof(DB_Thunder.__export__) == 'undefined') {
	DB_Thunder.__export__ = true;
}

/*
	Update an object with methods/variables of another object
*/
DB_Thunder.Base.update = function (self, obj/*, ... */) {
	if (self == null) {
		self = {};
	}
	for (var i = 1; i < arguments.length; i++) 
	{
		var o = arguments[i];
		if (typeof(o) != 'undefined' && o !== null) 
		{
			for (var k in o) 
			{
				self[k] = o[k];
			}
		}
	}
	return self;
};

DB_Thunder.Base.update( DB_Thunder.Base, {
	__repr__: function () 
	{
		return "[" + this.NAME + " " + this.VERSION + "]";
	},
	toString: function () 
	{
		return this.__repr__();
	},
    clone: function (obj) 
	{
        var me = arguments.callee;
        if (arguments.length == 1) {
            me.prototype = obj;
            return new me();
        }
    },
	extend : function (self, obj, /* optional */skip)
	{
		if (!skip) 
		{
			skip = 0;
		}
		if (obj)
		{
			var l = obj.length;
			if (!self)
			{
				self = [];
			}
			for (var i = skip; i < l; i++)
			{
				self.push(obj[i]);
			}
		}
		return self;
	},
	concat : function (/* lst... */)
	{
		var rval = [];
		var extend = DB_Thunder.Base.extend;
		for (var i = 0; i < arguments.length; i++)
		{
			extend(rval, arguments[i]);
		}
		return rval;
	},
	bind : function (func, self/*args ... */)
	{
		var m = DB_Thunder.Base;
		if (typeof(func) == "string")
		{
			func = self[func];
		}
		/*
			Maybe function was already bound before
		*/
		var im_func = func.im_func;
		var im_preargs = func.im_preargs;
		var im_self = func.im_self;

		if (typeof(im_func) != 'function')
		{// func is not an already bound function
			im_func = func;
		}
		if (typeof(self) != 'undefined') 
		{// Use self if defined
			im_self = self;
		}
		if (typeof(im_preargs) == 'undefined') {
			im_preargs = [];
		} else {
			im_preargs = im_preargs.slice();
		}

		m.extend(im_preargs, arguments, 2);
		var new_func = function () 
		{
			var args = arguments;
			var me = arguments.callee;
			if (me.im_preargs.length > 0)
			{
				args = m.concat(me.im_preargs, args);
			}
			var self = me.im_self;
			if (!self)
			{
				self = this;
			}
			return me.im_func.apply(self, args);
		};
		new_func.im_self = im_self;
		new_func.im_func = im_func;
		new_func.im_preargs = im_preargs;
		return new_func;
	},
	/* this function is used when you need an empty function.
		Use this one to prevent memory leaks with closures
	*/
	noop: function(a)
	{
		return a;
	},
	partial: function(func /*args ... */)
	{
		var m = DB_Thunder.Base;
		return m.bind.apply(this, m.extend([func, undefined], arguments, 1));
	},
	map: function (fn, lst/*, lst... */)
	{
		var m = DB_Thunder.Base;
		if (arguments.length <= 2)
		{
			if (fn == null)
			{
				return m.extend(null, lst);
			}
			var rval = [];
			for (var i = 0; i < lst.length; i++)
			{
				rval.push(fn(lst[i]));
			}
			return rval;
		}
		else
		{
			if (fn == null)
			{
				fn = Array;
			}
			/* Find minimum length of all arrays */
			var min_length = null;
			for (i = 0; i < arguments.length; i++)
			{
				var length = arguments[i].length;
				if (min_length == null || min_length > length)
				{
					min_length = length;
				}
			}
			rval = [];
			for (i = 0; i < min_length; i++)
			{
				var args = [];
				for (var j = 1; j < arguments.length; j++)
				{
					args.push(arguments[j][i]);
				}
				rval.push(fn.apply(this, args));
			}
			return rval;
		}
	},
	camelize: function (selector) 
	{ 
		var arr = selector.split('-');
		var cc = arr[0];
		for (var i = 1; i < arr.length; i++) {
			cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
		}
		return cc;
	},
    updatetree: function (self, obj/*, ...*/) {
        if (self === null) {
            self = {};
        }
        for (var i = 1; i < arguments.length; i++) {
            var o = arguments[i];
            if (typeof(o) != 'undefined' && o !== null) {
                for (var k in o) {
                    var v = o[k];
                    if (typeof(self[k]) == 'object' && typeof(v) == 'object') {
                        arguments.callee(self[k], v);
                    } else {
                        self[k] = v;
                    }
                }
            }
        }
        return self;
    },
	/*
		Strip whitespace form both sides of string
	*/
	trim: function (str) 
	{
		return str.replace(/^\s*|\s*$/g,"");
	}
}
)

/* List of functions that will be added to global
	namespace
*/
DB_Thunder.Base.EXPORT_LIST = [ 
	"camelize", "trim", 
	"bind", "partial" ];

DB_Thunder.Base.export_symbols = function(globals, module) {
	if (!DB_Thunder.__export__) 
	{
		return;
	}
	var all = module.EXPORT_LIST;
	for (var i = 0; i < all.length; i++)
	{
		globals[all[i]] = module[all[i]];
	}
};

/* 
	Code taken from http://www.quirksmode.org/js/detect.html 
*/

DB_Thunder.Base.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"
		}
	]

};

DB_Thunder.Base.__new__ = function () 
{
	var m = this;

	// Add array push function
	if (typeof(Array.prototype.push) == 'undefined')
	{
		Array.prototype.push = function () {
			var i=0, b=this.length, a=arguments;
			for (i; i<a.length;i++)
			{
				this[b+i]=a[i];
			}
			return this.length;
		};
	}
	// Instantiate Browser Array
	m.BrowserDetect.init();
}


DB_Thunder.Base.__new__();

DB_Thunder.Base.export_symbols(this, DB_Thunder.Base);

/***

DB_Thunder.DOM Beta

***/
try 
{
	if (typeof(DB_Thunder.Base) == 'undefined') 
	{
		throw "";
	}
} 
catch (e) 
{
	throw "DB_Thunder.DOM depends on DB_Thunder.Base";
}

if (typeof(DB_Thunder.DOM) == 'undefined')
{
	DB_Thunder.DOM = {};
}

DB_Thunder.Base.update( DB_Thunder.DOM, {
	/*
		Returns an array of all children of a dom object that match
		either tag, class, or both
	*/
	getElementsByTagAndClass: function (dom, tag_name, class_name)
	{
		if (typeof(tag_name) == 'undefined' || tag_name == null )
		{
			tag_name = '*';
		}
		var children = (dom.getElementsByTagName(tag_name) 
			|| dom.all);

		var results = [];
		var count = 0;
		for (var i=0; i < children.length; i++)
		{
			var child = children[i];
			var classNames = child.className.split(" ");
			for (var j=0; j < classNames.length; j++)
			{
				if (classNames[j] == class_name)
				{
					results[count] = child;
					count++;
					break;
				}
			}
		}
		return results;
	},
	addClassName : function (obj, className)
	{
		var cls = obj.className;
		if (!cls)
		{
			obj.className = className;
			return true;
		}
		if (cls == className)
		{
			return false;
		}
		var classes = obj.className.split(" ");
		for (var i = 0; i < classes.length; i++)
		{
			if (classes[i] == className)
			{
				return false;
			}
		}
		obj.className = (cls + " " + className);
		return true;
	},
	removeClassName : function (obj, className)
	{
		var cls = obj.className;
		if (cls.length == 0)
		{
			return false;
		}
		if (cls == className)
		{
			obj.className = "";
			return true;
		}
		var new_classes = [];
		var classes = obj.className.split(" ");
		var count = 0;
		for (var i=0; i < classes.length; i++)
		{
			if (classes[i] != className)
			{
				new_classes[count] = classes[i];
				count++;
			}
		}
		obj.className = new_classes.join(" ");
		return true;
	}
}
)

DB_Thunder.DOM.EXPORT_LIST = [ 
	"getElementsByTagAndClass", "addClassName", 
	"removeClassName"
];

DB_Thunder.Base.export_symbols(this, DB_Thunder.DOM);

/**
	Image beta
**/
try 
{
	if (typeof(DB_Thunder.Base) == 'undefined') 
	{
		throw "";
	}
} 
catch (e) 
{
	throw "DB_Thunder.Image depends on DB_Thunder.Base";
}

if (typeof(DB_Thunder.Image) == 'undefined')
{
	DB_Thunder.Image = {};
}

DB_Thunder.Base.update( DB_Thunder.Image, {
	/*
		Takes a image and viewer dimensions,
		then computes new image width and height to
		fit inside box
	*/
	fit_to_box : function (image/*{height,width}*/, viewer/*{height,width}*/)
	{
		/* Log Start */
		var log_msg = "fit_to_box({"+image.width+','+image.height
			+'},{'+viewer.width+','+viewer.height+'})';
		/* Log End */

		/* Guard against 0s */
		if (image.height <= 0 || image.width <= 0 ||
			viewer.height <= 0 || viewer.width <= 0)
		{
			/* Log Start */
			log(log_msg+' = { 0,0 }'); 
			/* Log End */
			return {"height" : 0, "width" : 0};
		}

		image.ratio = image.width / image.height;
		viewer.ratio = viewer.width / viewer.height;

		/* Log Start */
			log('image ratio: ',image.ratio,' viewer.ratio: ',viewer.ratio);
		/* Log End */
		var result;
		if (image.ratio == viewer.ratio)
		{
			result = {"height" : viewer.height, 
						"width" : viewer.width };
		}
		else if (image.ratio > viewer.ratio)
		{
			result = {"height" : viewer.width / image.ratio,
					"width" : viewer.width};
		}
		else if (image.ratio < viewer.ratio)
		{
			result = {"height" : viewer.height,
					"width" : viewer.height * image.ratio};
		}
		/* Log Start */
		log(log_msg+' = { '+result.width+','+result.height+' }'); 
		/* Log End */
		return result;
	},
	/* 
		Will load an image and then fire a function if it loads successfully. 
		Returns an Image if successful or null if failed
		interval defines how quickly it should check the status of the
		image.
		attrs will attach additional attributes to the image
	*/
	image_event : function (func, interval, src /*,attrs optional*/)
	{
		var image = new Image();
		image.success = false;
		image.onload = function () { this.success = true; alert(this);};

		image.src = src;

		var _func = function (func)
		{
			if (image.complete)
				if (image.success)
				{
					func(image);
				}
				else 
				{
					return null;
				}
			else
			{
				setTimeout(func, interval);
			}
		};
		_func();
		return image;
	}
});

DB_Thunder.Image.EXPORT_LIST = [ 
	"fit_to_box",
	"image_event"
];

DB_Thunder.Base.export_symbols(this, DB_Thunder.Image);

/**
	Logging Beta
**/
try 
{
	if (typeof(DB_Thunder.Base) == 'undefined') 
	{
		throw "";
	}
} 
catch (e) 
{
	throw "DB_Thunder.Logging depends on DB_Thunder.Base";
}

if (typeof(DB_Thunder.Logging) == 'undefined')
{
	DB_Thunder.Logging = {};
}

DB_Thunder.Logging.LogMessage = function (num, level, info)
{
	this.num = num;
	this.level = level;
	this.info = info;
	this.timestamp = new Date();
}

DB_Thunder.Logging.Logger = function (/*optional*/max_size)
{
	this.counter = 0;
	if (typeof(max_size) == 'undefined' || max_size === null)
	{
		max_size = -1;
	}
	this.max_size = max_size;
	this._messages = [];
	this.use_native_console = false;
}
DB_Thunder.Logging.Logger.prototype = {
	clear: function () 
	{
		this._messages.splice(0, this._messages.length);
	},
	logToConsole: function(msg)
	{
		if (typeof(window) != 'undefined' && window.console 
				&& window.console.log)
		{
			window.console.log(msg.replace(/%/g, '\uFF05'));
		}
		else if (typeof(opera) != 'undefined' && opera.postError)
		{
			opera.postError(msg);
		}
		else if (typeof(printfire) == 'function')
		{
			printfire(msg);
		}
		else if (typeof(Debug) != 'undefined' && Debug.writeln)
		{
			Debug.writeln(msg);
		}
		else if (typeof(debug) != 'undefined' && debug.trace)
		{
			debug.trace(msg);
		}
	},
	baseLog : function (level, message/*, ...*/)
	{
		var msg = new DB_Thunder.Logging.LogMessage(
			this.counter,
			level,
			DB_Thunder.Base.extend(null, arguments, 1)
		);
		this._messages.push(msg);
		if (this.use_native_console)
		{
			this.logToConsole(msg.level + ": " + msg.info.join(" "));
		}
		this.counter += 1;
		while(this.max_size >= 0 && this._messages.length > this.max_size)
		{
			this._messages.shift();
		}
	},
	getMessages: function(howMany)
	{
		var firstMsg = 0;
		if (!(typeof(howMany) == 'undefined' || howMany === null))
		{
			firstMsg = Math.max(0, this._messages.length - howMany);
		}
		return this._messages.slice(firstMsg);
	},
	getMessageText: function (howMany)
	{
		if (typeof(howMany) == 'undefined' || howMany === null)
		{
			howMany = 30;
		}
		var message = this.getMessages(howMany);
		if (messages.length)
		{
			var lst = map(function (m) { 
				return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' ');
			}, messages);
			lst.unshift('LAST ' + messages.length + ' MESSAGES:');
			return lst.join('');
		}
		return '';
	},
	debuggingBookmarklet: function(inline)
	{
		if (typeof(DB_Thunder.LoggingPane) == 'undefined')
		{
			alert(this.getMessageText());
		}
		else 
		{
			DB_Thunder.LoggingPane.createLoggingPane(inline || false);
		}
	}
};

DB_Thunder.Logging.__new__ = function () 
{
	this.LogLevel = {
		ERROR: 40,
		FATAL: 50,
		WARNING: 30,
		INFO: 20,
		DEBUG: 10
	};

	var m = DB_Thunder.Base;

	var partial = m.partial;

	var Logger = this.Logger;
	var baseLog = Logger.prototype.baseLog;

	m.update(this.Logger.prototype, {
		debug: partial(baseLog, 'DEBUG'),
		log: partial(baseLog, 'INFO'),
		error: partial(baseLog, "ERROR"),
		fatal: partial(baseLog, 'FATAL'),
		warning: partial(baseLog, 'WARNING')
	});

	var self = this;
	var connectLog = function(name)
	{
		return function () {
			if (DB_Thunder.Logging.logger.debug_on)
			{
				self.logger[name].apply(self.logger, arguments);
			}
		};
	};

	this.log = connectLog('log');
	this.logError = connectLog('error');
	this.logDebug = connectLog('debug');
	this.logFatal = connectLog('fatal');
	this.logWarning = connectLog('warning');
	// Create Default Logger
	this.logger = new Logger();
	this.logger.use_native_console = true;
	this.logger.debug_on = true;
};

DB_Thunder.Logging.__new__();

DB_Thunder.Logging.EXPORT_LIST = [
 "LogMessage",
 "Logger",
 "LogLevel",
 "logger",
 'log',
 "logError",
 "logDebug",
 "logFatal",
 "logWarning"
 ];

DB_Thunder.Base.export_symbols(this, DB_Thunder.Logging);

/**
	Article_Rotator Beta
**/
try 
{
	if (typeof(DB_Thunder.Base) == 'undefined' || typeof(DB_Thunder.DOM) == 'undefined') 
	{
		throw "";
	}
} 
catch (e) 
{
	throw "DB_Thunder.Article_Rotator depends on DB_Thunder.Base and DB_Thunder.DOM";
}

if (typeof(DB_Thunder.Article_Rotator) == 'undefined')
{
	DB_Thunder.Article_Rotator = {};
}

DB_Thunder.Base.update( DB_Thunder.Article_Rotator, {

	/*
		Takes a DOM object and creates a javascript object
		based off its classnames
	*/
	create_db_object : function (obj, self)
	{
		var m = DB_Thunder.Base;
		var ar = DB_Thunder.Article_Rotator;

		if (!self) {
			self = {};
		}
		var oc = obj.childNodes;
		for (var i=0; i < oc.length; i++)
		{
			var child = oc[i];
			if (!child.className)
			{
				if (child.childNodes.length > 0)
				{
					ar.create_db_object(child, self);
				}
				else
				{
					continue;
				}
			}

			// Handle multiple classes
			var cns = child.className.split(' ');

			for (var j = 0; j < cns.length; j++)
			{
				if ('link' == cns[j])
				{// Bug in IE that screws up relative urls
					self[cns[j]] = child.cloneNode(false);
				}
				else
				{
					self[cns[j]] = child.cloneNode(true);
				}
			}
		}
		return self;
	},
	render_object : function (dbobj, view, fmap /* Optional */)
	{
		var ar = DB_Thunder.Article_Rotator;

		if (!dbobj)
			return view;
		if (typeof(fmap) == 'undefined' || !fmap)
		{
			fmap = ar.default_func_map;
		}
		if (!fmap.inner_html || typeof(fmap["inner_html"]) == 'undefined')
		{
			var ar = DB_Thunder.Article_Rotator;
			fmap.inner_html = ar.default_func_map.inner_html; 
		}
		if (!fmap.dom || typeof(fmap["dom"]) == 'undefined')
		{
			var ar = DB_Thunder.Article_Rotator;
			fmap.dom = ar.default_func_map.dom; 
		}

		var oc = view.childNodes;
		
		for (var i = 0; i < oc.length; i++)
		{
			var child = oc[i];
			var cns = [];
			var matched_class = false;

			if (child.className)
			{
				cns = child.className.split(' ');
				for (var j = 0; j < cns.length; j++)
				{// For each class check fmap and then dbobj
					var cls = cns[j];
					// Check fmap
					for (var key in fmap)
					{
						if (cls == key)
						{
							matched_class = true;
							var fn = fmap[key];

							// Special methods
							if (fn == "innerHTML")
							{// call the fmap's inner_html function
								fmap["inner_html"](dbobj[key],child);
							}
							else if (fn == "dom")
							{// call the fmap's dom function
								fmap["dom"](dbobj[key],child);
							}
							else
							{
								fn(dbobj,child);
							}
							break;
						}
					}
					// Guard
					if (matched_class == true) { break; }
					// Check dbobj
					for (var key in dbobj)
					{
						if (cls == key)
						{// use inner_html fucntion by default
							matched_class = true;
							fmap["inner_html"](dbobj[key],child);
							break;
						}

					}
					// Guard
					if (matched_class == true) { break; }
				}
			}
			ar.render_object(dbobj, child, fmap);
		}
		return view;
	}
})
/* Default Func Map */
DB_Thunder.Article_Rotator.default_func_map = {
	"inner_html" : function(obj, view) 
	{
		view.innerHTML = obj.innerHTML;
	},
	"dom" : function(obj, view)
	{
		var clone = obj.cloneNode(true);	
		child.parentNode.replaceChild(clone,child);
	},
	"link" : function (dbobj, view)
	{
		var link = dbobj["link"];
		view.href = link.href;
	},
	"image" : function (dbobj, view)
	{
		for (var d in dbobj)
		{
			//window.console.log(d);
		}
		view.src = dbobj["image"].src;
	},
	"image_viewer" : function (dbobj, view) 
	{
		// Make sure there is even an image
		/* Log Start */
		log ("image_viewer not run, dbobj.image does not exist");
		/* Log End */
		if (!dbobj.image)
			{ return false; }

		var t = DB_Thunder.Base;
		var dbi = DB_Thunder.Image;

		var image = new Image();
		image.onload = function(){log('IMAGE:', this.src, 'loaded'); };
		image.src = dbobj["image"].src;

		var func = t.partial(
		function (image, view)
		{
			if (image.complete)
			{
				/* Log Start */
				log('image_viewer called. image.src =',image.src);
				/* Log End */
				var result = dbi.fit_to_box (
				{"height":parseInt(image.height),"width":parseInt(image.width) },
				{"height":parseInt(view.style.height),"width":parseInt(view.style.width) } );


				var view_images = view.getElementsByTagName("IMG");
				if (view_images.length > 0)
				{
					var view_image = view_images[0];

					if (typeof result != 'undefined' 
						&& result.height > 0 
						&& result.width > 0)
					{ 
						var br = DB_Thunder.Base.BrowserDetect.browser;
						if (br == 'Mozilla' || br == 'Firefox')
						{
							var new_image = image.cloneNode(false);	
							new_image.height = result.height;
							new_image.width = result.width;
							view_image.parentNode.replaceChild(new_image, view_image);
						}
						else
						{
							view_image.src = image.src;
							view_image.height = result.height;
							view_image.width = result.width;
							DB_Thunder.DOM.removeClassName(view_image, "thunder_hide_image");
						}
					}
					else 
					{
						DB_Thunder.DOM.addClassName(view_image, "thunder_hide_image");
					}
				}
			}
			else 
			{
				setTimeout(func, 50);
			}
		}, image, view);
		func();
	}
};

DB_Thunder.Article_Rotator.EXPORT_LIST = [
	"render_object", "create_db_object"
];

DB_Thunder.Base.export_symbols(this, DB_Thunder.Article_Rotator);

