if (!window['NABB']) window.NABB = new Object;
if (!window['console']) {
	window.console = new Object();
	window.console.debug = function() {}
}


NABB.min_start = 30;
NABB.max_start = 60;

// Detect IE6 -- can't use transparent PNGs, use transparent GIFs instead
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();

if (BrowserDetect.browser == 'Explorer' && BrowserDetect.version < 7) {
	NABB.is_ie6 = true;
	NABB.img_ending = 'gif';
}
else {
	NABB.img_ending = 'png';
}


function aalert(key, text) {
	if (!window['x_' + key]) {
		alert(text);
		window['x_' + key] = true;
	}
}


//===============================================================================
//========================== string object extension ============================
//===============================================================================
// Cross-Browser Split v0.2; MIT license
// By Steven Levithan <http://stevenlevithan.com>

var nativeSplit = nativeSplit || String.prototype.split;

String.prototype.split = function(s, limit) {
	// If s (separator) is not a regex, just use the native split method
	if (s instanceof RegExp) {
		var flags = (s.global?"g":"") + (s.ignoreCase?"i":"") + (s.multiline?"m":"");
		if (!s.global) {
			s = new RegExp(s.source, "g" + flags);
		}
	} else {
		return nativeSplit.apply(this, arguments);
	}
	
	/* Behavior for limit: If it's...
	- Undefined: No limit
	- Zero: Return an empty array
	- A positive number: Use limit after dropping any decimal value (if it's then zero, return an empty array)
	- A negative number: No limit, same as if limit is undefined
	- A type/value which can be converted to a number: Convert, then use the above rules
	- A type/value which can't be converted to a number: Return an empty array */
	if (limit === undefined || +limit < 0) {
		limit = false;
	} else {
		limit = Math.floor(+limit);
		if (!limit) return [];
	}
	
	var s2 = new RegExp("^" + s.source + "$", flags),
		match,
		output = [],
		lastLastIndex = 0,
		i = 0;
	
	while ((limit ? i++ <= limit : true) && (match = s.exec(this))) {
		var zeroLengthMatch = !match[0].length;
		
		// Fix IE's infinite-loop-resistant but incorrect lastIndex
		if (zeroLengthMatch && s.lastIndex > match.index) s.lastIndex = match.index;
		
		if (s.lastIndex > lastLastIndex) {
			// Fix IE and Opera to always return undefined for non-participating capturing groups
			if (match.length > 1) {
				match[0].replace(s2, function() {
					for (var j = 1; j < arguments.length - 2; j++){
						if (arguments[j] === undefined) match[j] = undefined;
					}
				});
			}
			
			output = output.concat(this.substring(lastLastIndex, match.index), (match.index === this.length ? [] : match.slice(1)));
			lastLastIndex = s.lastIndex;
		}
		
		if (zeroLengthMatch) s.lastIndex++;
	}
	
	return (lastLastIndex === this.length)
		? (s.test("") ? output : output.concat(""))
		: (limit ? output : output.concat(this.substring(lastLastIndex)));
};
//===============================================================================


//===============================================================================
//===========================  BG image animation  ==============================
//===============================================================================

if (!NABB['bgimg']) NABB.bgimg = new Object;
if (!NABB.bgimg['sm']) {
	var sm = NABB.bgimg.sm = new Image;
	sm.src = 'img/background_700.jpg';
}

if (!NABB.bgimg['lg']) {
	var lg = NABB.bgimg.lg = new Image;
	lg.src = 'img/background_800.jpg';
}


/*************************************************************
 *
 *************************************************************/
NABB.bg_to_lg = function() {
	document.body.style.backgroundImage = 'url(' + NABB.bgimg.lg.src + ')';
	document.body.style.backgroundPosition = '-38px -38px';
}

/*************************************************************
 *
 *************************************************************/
NABB.bg_to_sm = function() {
	document.body.style.backgroundImage = 'url(' + NABB.bgimg.sm.src + ')';
	document.body.style.backgroundPosition = '0px 0px';
}


/*************************************************************
 *
 *************************************************************/
NABB.animate_bg = function(step) {
	if (step == 1) {
		NABB.bg_to_lg();
		setTimeout(function () { NABB.animate_bg(step+1);}, 50);
	}
	else if (step == 2) {
		NABB.bg_to_sm();
		setTimeout(function () { NABB.animate_bg(step+1);}, 100);
	}
	else if (step == 3) {
		NABB.bg_to_lg();
		setTimeout(function () { NABB.animate_bg(step+1);}, 50);
	}
	else if (step == 4) {
		NABB.bg_to_sm();
		setTimeout(function () { NABB.animate_bg(step+1);}, 100);
	}
	else if (step == 5) {
		NABB.bg_to_lg();
		setTimeout(function () { NABB.animate_bg(step+1);}, 50);
	}
	else if (step == 6) {
		NABB.bg_to_sm();
		setTimeout(function () { NABB.animate_bg(step+1);}, 100);
	}
	else {
		var min_wait = NABB.min_start;
		var max_wait = NABB.max_start;
		
		var wait = min_wait + Math.random() * (max_wait - min_wait);
		wait *= 1000; // convert to milliseconds
		
		setTimeout(function () { NABB.animate_bg(1);}, wait);
	}
}




//===============================================================================
//===========================  text flip animation  =============================
//===============================================================================

/*************************************************************
 *
 *************************************************************/
NABB.getTextNodes = function() {
	var texts = new Array();
	var nodes = new Array();
	
	nodes.push(document.body);
	
//	console.debug('nodes length: ' + nodes.length);
	
	while (nodes.length) {
		var node = nodes.shift();
//		console.debug('nodeType: ' + node.nodeType);
		
		if (node.nodeType == 3) {
//			console.debug('got nodeType == 3');
			// text node
			texts[texts.length] = node;
		}
		else if (node.nodeType == 1) {
//			console.debug('got nodeType == 1, tagName: ' + node.tagName);
			// regular element
			for (var i = node.childNodes.length-1; i >= 0; i--) {
//				console.debug('pushing child #' + i + ': ' + node.childNodes[i].nodeType);
				nodes.push(node.childNodes[i]);
			}
		}
	}
	
	return texts;
}


/*************************************************************
 * If prep_only is true, the text isn't flipped, but we calculate
 * and store the flipped values for use during future flips
 *************************************************************/
NABB.flip_text = function(prep_only) {
	var texts = NABB.getTextNodes();
	
//	alert("Got " + texts.length + " text elements");
	
//	console.debug('Got ' + texts.length + ' text elements');
	
//	console.debug('prep_only: ' + prep_only);
	
	
	for (var i = texts.length-1; i >= 0; i--) {
		var node = texts[i];
		
		// IE6 won't allow us to add extra properties ('origValue' and 'flipValue')
		// to a text node -- gives us an 'element doesn't support that proprty'
		// error message. So, instead, we add a hidden div before the text node
		// and set the properties in that object instead!
		if (!node.previousSibling || !node.previousSibling.origValue) {
			var div = document.createElement('div');
			div.style.display = 'none';
			node.parentNode.insertBefore(div, node);
		}
		
		// First, determine the value we want to flip to
		if (node.previousSibling.flipValue) {
			// do nothing, already has flip value
		}
		else if (node.nodeValue == 'E') {
			// Swap the 'E' in Exorcism with the 'm'
			node.previousSibling.origValue = 'E';
			node.previousSibling.flipValue = 'm';
		}
		else if (node.nodeValue == 'm') {
			// Swap the 'm' in Exorcism with the 'E'
			node.previousSibling.origValue = 'm';
			node.previousSibling.flipValue = 'E';
		}
		else {
			node.previousSibling.origValue = node.nodeValue;
			node.previousSibling.flipValue = NABB.reverse_text_by_word(node.nodeValue);
		}
		
		// Now flip the value unless prep_only is true
		if (prep_only !== true) {
			node.nodeValue = node.previousSibling.flipValue;
		}
	}
}


/*************************************************************
 *
 *************************************************************/
NABB.unflip_text = function() {
	var texts = NABB.getTextNodes();
	
//	console.debug('Got ' + texts.length + ' text elements');
	
	for (var i = texts.length-1; i >= 0; i--) {
		var node = texts[i];
		if (node.previousSibling.origValue) {
			node.nodeValue = node.previousSibling.origValue;
		}
	}
}


/*************************************************************
 *
 *************************************************************/
NABB.reverse_text_by_word = function(str) {
	if (str.length == 0) {
		return str;
	}
	
	// In FF, this returns an array of words *with* the non-words we split
	// on in between. In IE6, this just returns the words, not the non-words
	var words = str.split(/([^a-zA-Z0-9])/);
	
	for (var i = words.length-1; i >= 0; i--) {
		var chars = words[i].split('').reverse();
		
		if (chars.length) {
			// Check the case of the (old) first letter, if upper-case, we want to make the new first letter
			// upper-case and make the old first letter lower-case
			var dec = chars[chars.length-1].charCodeAt(0); // get the decimal value of the character
			if (dec >= 65 && dec <= 90) { // 'A' == 65, 'Z' == 90
				// uppercase character, make the new first character upper-case and this lower-case
				chars[0] = chars[0].toUpperCase();
				chars[chars.length-1] = chars[chars.length-1].toLowerCase();
			}
		}
		
		words[i] = chars.join('');
	}
	
	return words.join('');
}


/*************************************************************
 *
 *************************************************************/
NABB.reverse_text = function(str) {
	return str.split('').reverse().join('');
}


/*************************************************************
 *
 *************************************************************/
NABB.animate_text = function(step) {
//	console.debug('animate_text -- step: ' + step);
	
	// One or more blinks (NABB.flip_text_count >= 1)
	if (step == 1) {
		NABB.flip_text();
		setTimeout(function () { NABB.animate_text(step+1);}, 500);
	}
	else if (step == 2) {
		NABB.unflip_text();
		setTimeout(function () { NABB.animate_text(step+1);}, 300);
	}
	
	// Two or more blinks (NABB.flip_text_count >= 2)
	else if (NABB.flip_text_count >= 2 && step == 3) {
		NABB.flip_text();
		setTimeout(function () { NABB.animate_text(step+1);}, 500);
	}
	else if (NABB.flip_text_count >= 2 && step == 4) {
		NABB.unflip_text();
		setTimeout(function () { NABB.animate_text(step+1);}, 300);
	}
	
	// Set up next animation
	else {
		if (Math.random() > 0.5) {
			NABB.flip_text_count = 2;
		}
		else {
			NABB.flip_text_count = 1;
		}
		
		var min_wait = NABB.min_start;
		var max_wait = NABB.max_start;
		
		var wait = min_wait + Math.random() * (max_wait - min_wait);
		wait *= 1000; // convert to milliseconds
		
		setTimeout(function () { NABB.animate_text(1);}, wait);
	}
}



//===============================================================================
//===========================  Bat shadow animation  ============================
//===============================================================================


/*************************************************************
 *
 *************************************************************/
NABB.get_bat_div = function() {
	var div = document.getElementById('nabb_bat_div');
	
	if (!div) {
		div = document.createElement('div');
		div.id = 'nabb_bat_div';
		
		div.style.position = 'absolute';
		div.style.left = '-1000px';
		div.style.top = '-1000px';
		div.style.zIndex = 999;
//		div.style.border = '1px solid red';
	
		
		div.innerHTML = '<img src="img/bat_shadow.' + NABB.img_ending + '" border="0"/>';
		
//		var clip = document.createElement('div');
//		clip.id = 'nabb_bat_clip_div';
		
//		clip.style.position = 'absolute';
//		clip.style.top = '0px';
//		clip.style.left = '0px';
//		clip.style.zIndex = 1;
//		clip.style.overflow = 'hidden';
//		clip.style.border = '1px solid yellow';
//		clip.style.background = 'white';
		
//		div.clip = clip;
		
//		clip.appendChild(div);
		
		
//		document.body.appendChild(clip);
		document.body.appendChild(div);
	}
	
	return div;
}


/*************************************************************
 *
 *************************************************************/
NABB.start_bat_div_animate = function() {
	var div = NABB.get_bat_div();
//	var clip = div.clip;
	
	// First, get the size of the viewport
	var vs = NABB.view_size();
	
//	console.debug("View size: " + vs.w + 'x' + vs.h);
	
	// set the clipping area
//	clip.style.width = (vs.w - 20) + 'px';
//	clip.style.height = (vs.h - 20) + 'px';
//	clip.style.top = '0px';
//	clip.style.left = '0px';
//	clip.style.display = 'block';
	
	
	// Start position is randomly off to the right of the screen
	div.start = {
					top: -200 + (Math.random() * vs.h),
					left: (vs.w - 200 - 20) // just inside the viewport -- otherwise scrollbars show
					}
	
	// End position is randomly off to the left of the screen
	div.end = {
					top: -200 + (Math.random() * vs.h),
					left: -200
					}
	
	// Step is 50 pixels horizontal and a corresponding step vertical (depending on where it is going vertically)
	var h_step = -30;
	var iters = (div.end.left - div.start.left) / h_step; // number of steps it will take to get there
	var v_step = (div.end.top - div.start.top) / iters; // vertical step
	
	div.h_step = h_step;
	div.v_step = v_step;
	
	// Set the image depending on the direction the image is moving -- right-to-left, up-and-left, down-and-left
	// calculate this based on the ratio of h_step to v_step
	if (v_step / h_step < -0.30) {
		// down-and-left
		div.innerHTML = '<img src="img/bat_shadow_dl.' + NABB.img_ending + '" border="0"/>';
	}
	else if (v_step / h_step > 0.30) {
		// up-and-left
		div.innerHTML = '<img src="img/bat_shadow_ul.' + NABB.img_ending + '" border="0"/>';
	}
	else {
		// left-to-right
		div.innerHTML = '<img src="img/bat_shadow_rtl.' + NABB.img_ending + '" border="0"/>';
	}
	
//	console.debug("Start: " + div.start.left + ', ' + div.start.top);
//	console.debug("End: " + div.end.left + ', ' + div.end.top);
//	console.debug("Step: " + div.h_step + ', ' + div.v_step);
	
	div.style.top = div.start.top + 'px';
	div.style.left = div.start.left + 'px';
//	div.clip.style.display = 'block';
	div.style.display = 'block';
	div.cur = {top: div.start.top, left: div.start.left};
	
	setTimeout(NABB.step_bat_div, 200);
	
}


/*************************************************************
 *
 *************************************************************/
NABB.step_bat_div = function() {
	var div = NABB.get_bat_div();
	
	var new_top = div.cur.top + div.v_step;
	var new_left = div.cur.left + div.h_step;
	
//	console.debug("Step to: " + new_left + ', ' + new_top);
	
//	if (((div.start.top > div.end.top && new_top < div.end.top) // moving up, new_top higher than end
//			|| new_top > div.end.top) // moving down, new_top lower than end
//			|| new_left < div.end.left) { // new left is beyond (more left than) end
	if (new_left < div.end.left) { // new left is beyond (more left than) end
		// at end of animation, stop
//		div.clip.style.display = 'none';
		div.style.display = 'none';
		
		// retrigger the animation
		NABB.animate_bat_div();
		return;
	}
	

	div.style.top = new_top + 'px';
	div.style.left = new_left + 'px';
	div.cur.top = new_top;
	div.cur.left = new_left;
	
	setTimeout(NABB.step_bat_div, 100);
}



/*************************************************************
 *
 *************************************************************/
NABB.animate_bat_div = function() {
	var min_wait = NABB.min_start;
	var max_wait = NABB.max_start;
	
	var wait = min_wait + Math.random() * (max_wait - min_wait);
	wait *= 1000; // convert to milliseconds
	
	setTimeout(NABB.start_bat_div_animate, wait);
}


//===============================================================================
//=================================  General  ===================================
//===============================================================================


/*************************************************************
 *
 *************************************************************/
NABB.on = function(el, event_name, handler) {
    if (el.addEventListener) {
        el.addEventListener(event_name, handler, false);
    }
    else if (el.attachEvent) {
        el.attachEvent('on' + event_name, handler);
    }
    else {
    	if (el['on' + event_name]) {
    		// existing handler, call it first, then our new handler
    		var orig = el['on' + event_name];
    		
    		el['on' + event_name] = function (e) {
     			orig(e);
    			handler(e);
   			}
    	}
    	else {
    		// no existing handler
 			el['on' + event_name] = handler;
 		}
    }
}


/*************************************************************
 *
 *************************************************************/
NABB.view_size = function() {
	var w, h;
	
	if (typeof(window.innerWidth) != 'undefined') {
		  w = window.innerWidth,
		  h = window.innerHeight
	 }
	 
	// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
	
	 else if (typeof(document.documentElement) != 'undefined'
				 && typeof(document.documentElement.clientWidth) != 'undefined'
				 && document.documentElement.clientWidth != 0) {
		w = document.documentElement.clientWidth,
		h = document.documentElement.clientHeight
	 }
	 
	 // older versions of IE
	 
	 else
	 {
		   w = document.getElementsByTagName('body')[0].clientWidth,
		   h = document.getElementsByTagName('body')[0].clientHeight
	 }
	 
	 return { w: w, h: h };
}


//===============================================================================
//================================  Execution  ==================================
//===============================================================================

NABB.on(window, 'load', function (e) {
//	console.debug('onload handler called');
	NABB.animate_bg();
	
	NABB.flip_text(true);
	NABB.animate_text();
	
	NABB.animate_bat_div();
});

