(function($){
	$.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);
			$(settings.appendId).append(BBHTML);
			if ($.browser.msie && $.browser.version < 7) {
				$('#BBContainer').prepend(fn.buildElement({tag:'iframe', id:'BBIframe', frameborder:0, tabindex:-1, src:'javascript:false'}));
				$('#BBOverlay').css('opacity',settings.bgOpacity);	
			} else {
				if ((navigator.appVersion.indexOf("Mac")!=-1) && (($.browser.mozilla && $.browser.version < 1.9) || $.browser.opera) && settings.hideFlashInFFMac) $('embed').css('visibility','hidden');
				$('#BBOverlay').css('opacity',0).animate({opacity:settings.bgOpacity},'fast');
			}
			if (settings.bgClick) {
				$('#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) {
					$('#BBBtnBar').append(settings.btnBar)
						.css('bottom','-' + fn.btnBarSize() + 'px')
							.animate({bottom:0},'fast');
					settings.setup = true;
					if (callback) {
						callback.call();
					}
				}
			}
		};

		fn.createLoading = function() {
			if (!($.browser.msie && $.browser.version < 7)) { 
				$('#BBModalOutside').animate({opacity:1}, 'fast');
			}
			$('#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() {
				$('#BBContent').append(settings.html);
				fn.revealBtnBar();
			});
		};

		fn.displayId = function() {
			var placeHolder = '<div id="badBoxPlaceHolder" style="display:none;"></div>';
			var element = typeof(settings.id) == 'string' ? $('#'+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() {
				$('#BBContent').append(element);
				element.show();
				fn.revealBtnBar();
			});
		};

		fn.displayImage = function() {
			$(settings.appendId).append(fn.buildElement({tag:'img', id:'BBModalImage', src:settings.image, style:'position:absolute;top:0;left:0'}));
			$('#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 = $('.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($(this).width(), $(this).height(), function() {
						fn.showHideButtons();
						$('#BBModalImage').appendTo($('#BBContent'))
							.css('position', 'relative')
								.hide()
									.css('opacity',1)
										.fadeIn('fast');
						var bindActions = function() {
							$('#BBPrev').click(function(event) {
								settings.curIndex--;
								fn.changeImage();
								return false;
							});
							$('#BBNext').click(function(event) {
								settings.curIndex++;
								fn.changeImage();
								return false;
							});
							$('#BBClose').click(fn.removeModal);
							fn.showHideButtons();
						};
						fn.revealBtnBar(bindActions);
					});
				});
		};

		fn.changeImage = function() {
			settings.currentImage = $($('.badBox').get(settings.curIndex));
			$('#BBPrev, #BBNext, #BBClose, #BBImageCount').hide();
			settings.image = settings.currentImage.attr('href');
			$('#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() {
				$('#BBContent').append(fn.buildElement({tag:'div', id:'BBMap'}));
				var BBMap = $('#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 = $('#BBMap').searchAddress({
						address: settings.mapTo,
						cache: $.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 {
					$('#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() {
					$('#BBClose').click(fn.removeModal);
					$('#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() {
				$('#BBContent').InsertObject({
					width: settings.width,
					height: settings.height,
					src: settings.movie
				});
				var bindActions = function() {
					$('#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() {
				$('#BBClose').click(fn.removeModal);
			};
			fn.removeLoading();
			var callback = function() {
				var wmode = 'transparent';
				var bgcolor = '#ffffff';
				if ((navigator.appVersion.indexOf("Mac")!=-1) && $.browser.mozilla) {
					bgcolor = fn.convertToHex($('#BBModalInside').css('background-color'));
					wmode = 'window';
				}
				$('#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() {
			$('#BBImageCount').text(settings.curIndex + 1 + ' of ' + $('.badBox').size()).show();
			settings.curIndex != 0 ? $('#BBPrev').show() : $('#BBPrev').hide();
			settings.curIndex + 1 != $('.badBox').size() ? $('#BBNext').show() : $('#BBNext').hide();
			$('#BBClose').show();
		};
		
		fn.btnBarSize = function() {
			var paddingTop = $('#BBBtnBar').css('paddingTop');
			var paddingTopLength = paddingTop.length;
			var paddingTopNumber = parseInt(paddingTop.substring(0,paddingTopLength-2));
			return ($('#BBBtnBar').height() + paddingTopNumber);
		};

		fn.resizeModal = function(width,height,callback) {
			width += fn.getTotalSpacing('Left');
			height += fn.getTotalSpacing('Top');
			if (settings.btnBar) {
				height += fn.btnBarSize();
			}
			$('#BBModalOutside').animate({width: width, marginLeft: -width/2},'fast', function() {
				var animObject = {
					height: height
				};
				if (!($.browser.msie && $.browser.version < 7)) {
					animObject.marginTop = (-height/2);
				}
				var speed = 'fast';
				$('#BBModalOutside').animate(animObject, speed, function() {
					if (callback) {callback.call()}
				});
			});
		};
		
		fn.getTotalSpacing = function(side) {
			var total = 0;
			var containers = [$('#BBModalOutside'), $('#BBModalInside'), $('#BBContent')];
			var types = ['padding'];
			for (x in containers) {
				for (y in types) {
					var stringValue = containers[x].css(types[y] + side);
					var intValue = parseInt(stringValue.substring(0,stringValue.length-2));
					if (intValue > 0) {total += intValue}
				}
			}
			return total;
		};

		fn.getAJAX = function() {
			settings.ajaxParams = settings.ajaxParams || null;
			$.get(settings.ajaxURL, settings.ajaxParams, function(data){
				fn.removeLoading();
				fn.resizeModal(settings.width, settings.height, function() {
					$('#BBContent').html($(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})];
				$('#BBContent').append(html);
				fn.revealBtnBar();
			});
		}
		
		fn.removeLoading = function() {
			$('#BBLoading').remove();
		};

		fn.removeModal = function(e, callback) {
			if (callback) {
				settings.callback = callback;
			}
			if (settings.retainContent && settings.id) $('#badBoxPlaceHolder').before($('#BBContent').children().hide());
			$('#badBoxPlaceHolder').remove();
			if (settings.movie) {document.getElementById('BBContent').innerHTML = ' '};
			$('#BBContainer, #BBModalImage').remove();
			if ((navigator.appVersion.indexOf("Mac") != -1) && ($.browser.mozilla || $.browser.opera) && settings.hideFlashInFFMac) {
				$('embed').each(function() {
					$(this).css('visibility', 'visible').width($(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();
		$.BadBox.close = fn.removeModal;
		window.closeBadBox = fn.removeModal;
	};

	$.BadBox = $.fn.BadBox;

	$(function() {
		$('.badBox').click(function() {
			var imageUrl = $(this).attr('href');
			var imageRel = $(this).attr('rel');
			$.BadBox({image:imageUrl,imageRel:imageRel,currentImage:$(this)});
			return false;
		});
	});
})(jQuery);

function badBox(o) {$.BadBox(o);};
