(function(jQuery){
	jQuery.fn.BadBox = function(settings) {
		var fn = new Object();
		
		if (settings && settings.height) settings.providedDimensions = true;
		
		settings = jQuery.extend({
			width: 640,
			height: 480,
			setup: false,
			btnBar: null,
			bgClick: true,
			callback: null,
			image: null,
			html: null,
			id: null,
			movie: null,
			ajaxURL: null,
			ajaxParams: null,
			bgOpacity: 0.8,
			flashVars: null,
			hideFlashInFFMac: true,
			retainContent:true,
			appendId:'body'
		}, settings);
		
		if (typeof(this) != 'function') {settings.id = this;}
		
		fn.setup = function() {
			var newHTML = { tag: 'div', id: 'BBContainer', content: [ { tag: 'div', id: 'BBOverlay' }, { tag: 'div', id: 'BBModalOutside', content: { tag: 'div', id: 'BBModalInside', content: [ { tag: 'div', id: 'BBContent' }, { tag: 'div', id: 'BBBtnBar' } ] } } ] };
			var BBHTML = fn.buildElement(newHTML);
			jQuery(settings.appendId).append(BBHTML);
			if (jQuery.browser.msie && jQuery.browser.version < 7) {
				jQuery('#BBContainer').prepend(fn.buildElement({tag:'iframe', id:'BBIframe', frameborder:0, tabindex:-1, src:'javascript:false'}));
				jQuery('#BBOverlay').css('opacity',settings.bgOpacity);	
			} else {
				if ((navigator.appVersion.indexOf("Mac")!=-1) && ((jQuery.browser.mozilla && jQuery.browser.version < 1.9) || jQuery.browser.opera) && settings.hideFlashInFFMac) jQuery('embed').css('visibility','hidden');
				jQuery('#BBOverlay').css('opacity',0).animate({opacity:settings.bgOpacity},'fast');
			}
			if (settings.bgClick) {
				jQuery('#BBOverlay').bind('click',fn.removeModal);
			}
			fn.createLoading();
			fn.routeType();
		};
		
		fn.routeType = function() {
			if (settings.html) {
				fn.displayHTML();
			} else if (settings.image) {
				fn.displayImage();
			} else if (settings.movie) {
				fn.displayMovie();
			} else if (settings.ajaxURL) {
				fn.getAJAX();
			} else if (settings.id) {
				fn.displayId();
			} else if (settings.mapTo) {
				fn.displayMap();
			} else if (settings.flash) {
				fn.displayFlash();
			} else if (settings.iframe) {
				fn.displayIframe();
			}
		};

		fn.revealBtnBar = function(callback) {
			if (settings.btnBar) {
				if (!settings.setup) {
					jQuery('#BBBtnBar').append(settings.btnBar)
						.css('bottom','-' + fn.btnBarSize() + 'px')
							.animate({bottom:0},'fast');
					settings.setup = true;
					if (callback) {
						callback.call();
					}
				}
			}
		};

		fn.createLoading = function() {
			if (!(jQuery.browser.msie && jQuery.browser.version < 7)) { 
				jQuery('#BBModalOutside').animate({opacity:1}, 'fast');
			}
			jQuery('#BBContent').append(fn.buildElement({tag:'div', id:'BBLoading', content:{tag:'div',id:'BBLoadingImage'}, text:'Loading'}));
		};

		fn.displayHTML = function() {
			fn.removeLoading();
			fn.resizeModal(settings.width, settings.height, function() {
				jQuery('#BBContent').append(settings.html);
				fn.revealBtnBar();
			});
		};

		fn.displayId = function() {
			var placeHolder = '<div id="badBoxPlaceHolder" style="display:none;"></div>';
			var element = typeof(settings.id) == 'string' ? jQuery('#'+settings.id) : settings.id;
			element.before(placeHolder);
			if (!settings.providedDimensions) {
				var elementHeight = element.css('height');
				settings.height = parseInt(elementHeight.slice(0, elementHeight.length-2));
				var elementWidth = element.css('width');
				settings.width = parseInt(elementWidth.slice(0, elementWidth.length-2));
			}
			fn.removeLoading();
			fn.resizeModal(settings.width, settings.height, function() {
				jQuery('#BBContent').append(element);
				element.show();
				fn.revealBtnBar();
			});
		};

		fn.displayImage = function() {
			jQuery(settings.appendId).append(fn.buildElement({tag:'img', id:'BBModalImage', src:settings.image, style:'position:absolute;top:0;left:0'}));
			jQuery('#BBModalImage').css('position','absolute')
				.bind('load', function(){
					if (settings.imageRel) {
						settings.btnBar = 	[	fn.buildElement({tag:'span', id:'BBImageCount'}),
												fn.buildElement({tag:'a', id:'BBPrev', href:'#', className:'btn', content:{tag:'span', text:'Previous'}}),
												fn.buildElement({text:' '}),
												fn.buildElement({tag:'a', id:'BBClose', href:'#', className:'btn', content:{tag:'span', text:'Close'}}),
												fn.buildElement({text:' '}),
												fn.buildElement({tag:'a', id:'BBNext', href:'#', className:'btn', content:{tag:'span', text:'Next'}})
											];
						settings.curIndex = jQuery('.badBox').index(settings.currentImage.get(0));
					} else {
						settings.btnBar = 	[	
												fn.buildElement({tag:'a', id:'BBClose', href:'#', className:'btn', content:{tag:'span', text:'Close'}}),
												fn.buildElement({text:' '})
											];
					}
					fn.removeLoading();
					fn.resizeModal(jQuery(this).width(), jQuery(this).height(), function() {
						fn.showHideButtons();
						jQuery('#BBModalImage').appendTo(jQuery('#BBContent'))
							.css('position', 'relative')
								.hide()
									.css('opacity',1)
										.fadeIn('fast');
						var bindActions = function() {
							jQuery('#BBPrev').click(function(event) {
								settings.curIndex--;
								fn.changeImage();
								return false;
							});
							jQuery('#BBNext').click(function(event) {
								settings.curIndex++;
								fn.changeImage();
								return false;
							});
							jQuery('#BBClose').click(fn.removeModal);
							fn.showHideButtons();
						};
						fn.revealBtnBar(bindActions);
					});
				});
		};

		fn.changeImage = function() {
			settings.currentImage = jQuery(jQuery('.badBox').get(settings.curIndex));
			jQuery('#BBPrev, #BBNext, #BBClose, #BBImageCount').hide();
			settings.image = settings.currentImage.attr('href');
			jQuery('#BBModalImage').remove();
			fn.createLoading();
			fn.displayImage();
		};
		
		fn.displayMap = function() {
			settings.btnBar = 	[	fn.buildElement({tag:'span', id:'BBImageCount'}),
									fn.buildElement({tag:'a', id:'BBFullMap', href:'#', className:'btn', content:{tag:'span', text:'Full Map'}}),
									fn.buildElement({text:' '}),
									fn.buildElement({tag:'a', id:'BBClose', href:'#', className:'btn', content:{tag:'span', text:'Close'}})
								];
			fn.removeLoading();
			fn.resizeModal(settings.width, settings.height, function() {
				jQuery('#BBContent').append(fn.buildElement({tag:'div', id:'BBMap'}));
				var BBMap = jQuery('#BBMap');
				BBMap.width(settings.width).height(settings.height);
				BBMap.jmap({language:"en"});
				BBMap.jmap({mapCenter: [34.033614,-118.395081], mapControlSize: "large", mapEnableScrollZoom: true});
				BBMap.createMarkerManager();
				BBMap.createGeoCache();
				var fullMap = new String();
				var lat, lng, toAddress, fromAddress;
				toAddress = settings.mapTo.replace(/ /g,"+");
				var geocoder = new GClientGeocoder();
				geocoder.getLatLng(settings.mapTo, function(point) {
					lat = point.lat();
					lng = point.lng();
				});
				if (!settings.mapFrom) {
					var testing = jQuery('#BBMap').searchAddress({
						address: settings.mapTo,
						cache: jQuery.jmap.GGeoCache
					});
					fullMap = 'http://maps.google.com/maps?f=q&hl=en&geocode=&time=&date=&ttype=&q=' + toAddress + '&sll=&sspn=0.006588,0.007596&ie=UTF8&ll=' + lat + ',' + lng + '&spn=&z=15&iwloc=addr&om=1';
				} else {
					jQuery('#BBMap').searchDirections({
	        			fromAddress: settings.mapFrom,
	        			toAddress: settings.mapTo,
	        			directionsPanel: "directions"
					});
					var fromAddress = settings.mapFrom.replace(/ /g,"+");
					fullMap = 'http://maps.google.com/maps?f=d&hl=en&geocode=&time=&date=&ttype=&saddr=' + fromAddress + '&daddr=' + toAddress + '&sll=' + lat + ',' + lng + '&sspn=&ie=UTF8&z=5&om=1';
				}
				var bindActions = function() {
					jQuery('#BBClose').click(fn.removeModal);
					jQuery('#BBFullMap').click(function() {
						window.open(fullMap,'gMapWindow','width=1024,height=768,resizable=yes,resizable=yes');
						return false;
					});
				};
				fn.revealBtnBar(bindActions);
			});
		};
		
		fn.displayMovie = function() {
			settings.btnBar = 	[	
									fn.buildElement({tag:'a', id:'BBClose', href:'#', className:'btn', content:{tag:'span', text:'Close'}}),
									fn.buildElement({text:' '})
								];
			fn.removeLoading();
			var callback = function() {
				jQuery('#BBContent').InsertObject({
					width: settings.width,
					height: settings.height,
					src: settings.movie
				});
				var bindActions = function() {
					jQuery('#BBClose').click(fn.removeModal);
				};
				fn.revealBtnBar(bindActions);
			};
			fn.resizeModal(settings.width, settings.height, callback);
		};
		
		fn.displayFlash = function() {
			settings.btnBar = 	[	
									fn.buildElement({tag:'a', id:'BBClose', href:'#', className:'btn', content:{tag:'span', text:'Close'}}),
									fn.buildElement({text:' '})
								];
			var bindActions = function() {
				jQuery('#BBClose').click(fn.removeModal);
			};
			fn.removeLoading();
			var callback = function() {
				var wmode = 'transparent';
				var bgcolor = '#ffffff';
				if ((navigator.appVersion.indexOf("Mac")!=-1) && jQuery.browser.mozilla) {
					bgcolor = fn.convertToHex(jQuery('#BBModalInside').css('background-color'));
					wmode = 'window';
				}
				jQuery('#BBContent').InsertObject({
					width: settings.width,
					height: settings.height,
					src: settings.flash,
					flashVars: settings.flashVars,
					wmode: wmode,
					bgcolor: bgcolor
				});
				fn.revealBtnBar(bindActions);
			};
			fn.resizeModal(settings.width, settings.height, callback);
		};
		
		fn.convertToHex = function(strBGColor) {
			var DecToHex = function(intDec, intPlaces) {
				var strHexDef = new String("0123456789ABCDEF");

				var strHex = strHexDef.substr(intDec & 15, 1);

				while(intDec > 15) {
					intDec >>= 4;
					strHex = strHexDef.substr(intDec & 15, 1) + strHex;
				}

				for (var intX = strHex.length; intX < intPlaces; intX++) {
					strHex = '0' + strHex;
				}

				return strHex;
			}
			
			if (strBGColor.indexOf('rgb(') == 0) {
				var strTempColorAry = strBGColor.replace(/ /g, '').substring(4, strBGColor.length - 1).split(',');
				var strRed = DecToHex(parseInt(strTempColorAry[0]), 2);
				var strGreen = DecToHex(parseInt(strTempColorAry[1]), 2);
				var strBlue = DecToHex(parseInt(strTempColorAry[2]), 2);

				return '#' + strRed + strGreen + strBlue;
			} else {
				return strBGColor.toUpperCase();
			}
		}
		
		fn.showHideButtons = function() {
			jQuery('#BBImageCount').text(settings.curIndex + 1 + ' of ' + jQuery('.badBox').size()).show();
			settings.curIndex != 0 ? jQuery('#BBPrev').show() : jQuery('#BBPrev').hide();
			settings.curIndex + 1 != jQuery('.badBox').size() ? jQuery('#BBNext').show() : jQuery('#BBNext').hide();
			jQuery('#BBClose').show();
		};
		
		fn.btnBarSize = function() {
			var paddingTop = jQuery('#BBBtnBar').css('paddingTop');
			var paddingTopLength = paddingTop.length;
			var paddingTopNumber = parseInt(paddingTop.substring(0,paddingTopLength-2));
			return (jQuery('#BBBtnBar').height() + paddingTopNumber);
		};

		fn.resizeModal = function(width,height,callback) {
			width += fn.getTotalSpacing('Left');
			height += fn.getTotalSpacing('Top');
			if (settings.btnBar) {
				height += fn.btnBarSize();
			}
			jQuery('#BBModalOutside').animate({width: width, marginLeft: -width/2},'fast', function() {
				var animObject = {
					height: height
				};
				if (!(jQuery.browser.msie && jQuery.browser.version < 7)) {
					animObject.marginTop = (-height/2);
				}
				var speed = 'fast';
				jQuery('#BBModalOutside').animate(animObject, speed, function() {
					if (callback) {callback.call()}
				});
			});
		};
		
		fn.getTotalSpacing = function(side) {
			var total = 0;
			var containers = [jQuery('#BBModalOutside'), jQuery('#BBModalInside'), jQuery('#BBContent')];
			var types = ['padding'];
			for (var iContainers=0; iContainers<containers.length; iContainers++) {
				for (var iTypes=0; iTypes<types.length; iTypes++) {
				    var cssPaddingName = types[iTypes] + side;
				    var cssPaddingSize = containers[iContainers].css(cssPaddingName);
				    var intValue = parseInt(cssPaddingSize.substring(0,cssPaddingSize.length-2));
				    if (intValue > 0) {total += intValue}
				}
			}
			return total;
		};

		fn.getAJAX = function() {
			settings.ajaxParams = settings.ajaxParams || null;
			jQuery.get(settings.ajaxURL, settings.ajaxParams, function(data){
				fn.removeLoading();
				fn.resizeModal(settings.width, settings.height, function() {
					jQuery('#BBContent').html(jQuery(data).html());
					fn.revealBtnBar();
				});
			});
		};
		
		fn.displayIframe = function() {
			fn.removeLoading();
			fn.resizeModal(settings.width, settings.height, function() {
				var html = [fn.buildElement({tag:'iframe', src:settings.iframe, width:settings.width, height:settings.height, frameborder:0, frameBorder: 0})];
				jQuery('#BBContent').append(html);
				fn.revealBtnBar();
			});
		}
		
		fn.removeLoading = function() {
			jQuery('#BBLoading').remove();
		};

		fn.removeModal = function(e, callback) {
			if (callback) {
				settings.callback = callback;
			}
			if (settings.retainContent && settings.id) jQuery('#badBoxPlaceHolder').before(jQuery('#BBContent').children().hide());
			jQuery('#badBoxPlaceHolder').remove();
			if (settings.movie) {document.getElementById('BBContent').innerHTML = ' '};
			jQuery('#BBContainer, #BBModalImage').remove();
			if ((navigator.appVersion.indexOf("Mac") != -1) && (jQuery.browser.mozilla || jQuery.browser.opera) && settings.hideFlashInFFMac) {
				jQuery('embed').each(function() {
					jQuery(this).css('visibility', 'visible').width(jQuery(this));
				});
			}
			if (settings.callback) {
				settings.callback.call();
			}
			window.closeBadBox = null;
			return false;
		};
		
		fn.buildElement = function(o) {
			var element = o.tag ? document.createElement(o.tag) : null;
			for ( var i in o) {
				switch(i) {
					case 'tag':
						break;
					case 'text':
						if (element) {
							element.appendChild(document.createTextNode(o[i]));	
						} else {
							element = document.createTextNode(o[i]);
						}
						break;
					case 'className':
						element.setAttribute('className', o[i]);
						element.setAttribute('class', o[i]);
						break;
					case 'content':
						if (o[i].length){
							for (var a = 0; a < o[i].length; a++) {
								element.appendChild(fn.buildElement(o[i][a]));		
							}
						} else {
							element.appendChild(fn.buildElement(o[i]));	
						}
						break;
					default:
						element.setAttribute(i, o[i]);
						break;
				}
			}
			return element;
		};
		
		fn.setup.call();
		jQuery.BadBox.close = fn.removeModal;
		window.closeBadBox = fn.removeModal;
	};

	jQuery.BadBox = jQuery.fn.BadBox;

	jQuery(function() {
		jQuery('.badBox').click(function() {
			var imageUrl = jQuery(this).attr('href');
			var imageRel = jQuery(this).attr('rel');
			jQuery.BadBox({image:imageUrl,imageRel:imageRel,currentImage:jQuery(this)});
			return false;
		});
	});
})(jQuery);

function badBox(o) {jQuery.BadBox(o);};
