
(function($) {
	
	var lbElement, lbCloseBtnClassName, lbContent, lbPreserve, lbOptions, originElement, originContainer, lbCallback;
	
	/**
	 * @param triggerElement		object - DOM element from which meLightbox function call is made
	 * @param containerClassName	string - (optional)
	 * @param closeButtonClassName	string - (optional)
	 * @param options 				object - (optional)
	 * @param ajaxReq 				array(ajaxURL, ajaxMethod, ajaxData, ajaxDataType) - (optional)
	 * @param callbackFunction 		function - (optional)
	 */
	jQuery.fn.meLightbox = function (triggerElement, containerClassName, closeButtonClassName, options, ajaxReq, callbackFunction) {
		return this.each (function () {
			lbOptions = "";
			lbElement = $("body").children("#lbTarget")[0];
			originElement = triggerElement;
			lbCallback = callbackFunction;
			if (!lbElement.id) lbElement.id= new Date().getMilliseconds();
			var empty = {};
			lbElement.defaults = { 
					containerPosition:		'center',				// (string) = 'relative', = 'center'
					overlayBgColor: 		'#000000',				// (string) Background color to overlay; inform a hexadecimal value like: #RRGGBB. Where RR, GG, and BB are the hexidecimal values for the red, green, and blue values of the color.
					overlayOpacity:			0.8,					// (integer) Opacity value to overlay; inform: 0.X. Where X are number from 0 to 9
					overlaySelection:		'exclusive',			// (string) = 'exclusive', = 'inclusive'
					effectDuration:			500,					// (integer) default duration in milliseconds of all effects
					padding:				'25px 25px 25px 25px',	// (string)
					width:					'800px',					// (integer)
					height:					'450px',					// (integer)
					overflow:				'auto',
					position:				'fixed',
					backgroundColor:		'#ffffff'
			};

			originContainer = $(this);
			lbContent = "";
			if (originContainer.html()) {
				lbContent = originContainer.children();
			}
			lbPreserve = {
					thehtml:		originContainer.html(),
					theChildren:	originContainer.children(),
					styleAttr:		originContainer.attr("style"),
					classAttr:		originContainer.attr("class")
			};
			originContainer.children().detach();
			originContainer.html("");
			
			lbContainer = $("body").children("#lbTarget");
			if ((typeof containerClassName != "undefined") && (containerClassName != "")) {
				lbContainer.addClass(containerClassName);
				containerClassSettings = {
						padding:			lbContainer.css("padding"),
						width:				lbContainer.css("width"),
						height:				lbContainer.css("height"),
//						cannot use overflow declaration from the CSS class parameter due to subsequent launches of lightbox in Opera using the computed overflow-x and overflow-y values
//						overflow:			lbContainer.css("overflow"),
						position:			lbContainer.css("position"),
						backgroundColor:	lbContainer.css("backgroundColor")
				};
				// lbContainer will have a height and width regardless of whether either property has been declared by the CSS class definition
				// therefore will need to check for zero pixel value
				if (containerClassSettings.width == "0px") {
					delete containerClassSettings.width;
				}
				if (containerClassSettings.height == "0px") {
					delete containerClassSettings.height;
				}
			} else {
				containerClassSettings = "";
			}
			
			if (typeof options !== 'undefined') {
				if (options != "") {
				lbOptions = options;
//					lbContainer.addClass(options);
//					if ($.metadata) {
//						$.metadata.setType("class");
//						lbOptions = {
//								top:				lbContainer.metadata().top,
//								left:				lbContainer.metadata().left,
//								margin:				lbContainer.metadata().margin,
//								padding:			lbContainer.metadata().padding,
//								width:				lbContainer.metadata().width,
//								height:				lbContainer.metadata().height,
//								overflow:			lbContainer.metadata().overflow,
//								position:			lbContainer.metadata().position,
//								backgroundColor:	lbContainer.metadata().backgroundColor,
//								calcWideMedia:		lbContainer.metadata().calcWideMedia,
//								vOffset:			lbContainer.metadata().vOffset
//						};
//					}
				}
			}
			if (typeof lbOptions.vOffset === 'undefined') {
				lbOptions.vOffset = 0;
			}
			lbElement.settings = $.extend(true, {}, lbElement.defaults, containerClassSettings, lbOptions);
			
			if ((typeof closeButtonClassName != "undefined") && (closeButtonClassName != "")) {
				lbCloseBtnClassName = closeButtonClassName;
			} else {
				lbCloseBtnClassName = "";
			}

			lbContainer.css({
				zIndex:				10001,
				padding:			lbElement.settings.padding,
				width:				lbElement.settings.width,
				height:				lbElement.settings.height,
				overflow:			lbElement.settings.overflow,
				position:			lbElement.settings.position,
				backgroundColor:	lbElement.settings.backgroundColor
			});
			var lbDim = new Array();
			if (lbElement.settings.containerPosition == 'center') {
				lbDim = lbContainer.lbCenterInViewport();
			} else if (lbElement.settings.containerPosition == 'relative') {
				lbContainer.lbPositionRelative(originElement);
			}
			
			if (lbElement.settings.calcWideMedia == 1) {
				var wmw = 0; 
				var wmh = 0;
				var height = 0;
				var top = 0;
				var left = 0;
				paddingTop = lbContainer.css("paddingTop");
				if (typeof paddingTop != "number") {
					if (paddingTop.indexOf("px") >= 0) {
						paddingTop = paddingTop.substring(0, paddingTop.indexOf("px"));
					}
				}
				paddingRight = lbContainer.css("paddingRight");
				if (typeof paddingRight != "number") {
					if (paddingRight.indexOf("px") >= 0) {
						paddingRight = paddingRight.substring(0, paddingRight.indexOf("px"));
					}
				}
				paddingBottom = lbContainer.css("paddingBottom");
				if (typeof paddingBottom != "number") {
					if (paddingBottom.indexOf("px") >= 0) {
						paddingBottom = paddingBottom.substring(0, paddingBottom.indexOf("px"));
					}
				}
				paddingLeft = lbContainer.css("paddingLeft");
				if (typeof paddingLeft != "number") {
					if (paddingLeft.indexOf("px") >= 0) {
						paddingLeft = paddingLeft.substring(0, paddingLeft.indexOf("px"));
					}
				}
				wmh = Math.max(lbDim[1], lbDim[3] - 40 - 18) - (parseInt(paddingTop) + parseInt(paddingBottom) + lbElement.settings.vOffset);
				wmw = Math.max(lbDim[0], lbDim[2] - 40 - 18) - (parseInt(paddingRight) + parseInt(paddingLeft));
				if ((wmh < 324) || (wmw < 576)) {
					wmh = 324;
					wmw = 576;
				} else if ((wmh > 540) && (wmw > 960)) {
					wmh = 540;
					wmw = 960;
				} else if ((wmw/wmh) > (16/9)) {
					wmw = (wmh * 16) / 9;
				} else {
					wmh = (wmw * 9) / 16;
				}
				height = wmh + parseInt(paddingTop) + parseInt(paddingBottom) + lbElement.settings.vOffset - 25;
				top = Math.max((lbDim[3] - height - 18 - 18)/2, 20);
				left = Math.max((lbDim[2] - wmw - 18 - 18)/2, 20);
				lbContainer.css({
					width: 		wmw+"px",
					height: 	height+"px",
					top: 		top+"px",
					left: 		left+"px"
				});
			}

			if ((typeof ajaxReq !== 'undefined')) {
				if ((ajaxReq[0] != "") && (ajaxReq[1] != "")) {
					if ((wmw > 0) && (wmh > 0)) {
						ajaxReq[2] += "&wmw="+wmw+"&wmh="+wmh;
					}
					$.ajax({
						type:		ajaxReq[1].toUpperCase(),
						url:		ajaxReq[0],
						data:		ajaxReq[2],
						dataType:	ajaxReq[3],
//						async:		false,
						success:	function(data) { lbContent += data; appendCloseBtn(); },
						error:		function(XMLHttpRequest, textStatus) { lbContent = "Error retrieving data: "+textStatus+"."; }
					});
				} else {
					appendCloseBtn();
				}
			} else {
				appendCloseBtn();
			}
			
			lbContainer.html("");
			
			lbContainer.lbSetOverlay();
			lbContainer.lbOpen();
			
			$('#lbCloseBtn').click( function () {
				lbContainer.lbClose();
			});
			
//			$('#lbOverlay').click( function () {
//				lbContainer.lbClose();
//			});

			$(document).keyup( function (event) {
				if (event.keyCode == '27' && lbContainer.css("display") !== 'none') {
					lbContainer.lbClose();
				}
			});
		});
	};
				
	jQuery.fn.lbCenterInViewport = function () {
		viewportW = getViewportWidth() - 18;
		viewportH = getViewportHeight() - 18;
		containerW = (lbElement.settings.width != "") ? lbElement.settings.width : lbContainer.css("width");
		if (typeof containerW != "number") {
			if (containerW.indexOf("px") >= 0) {
				containerW = containerW.substring(0, containerW.indexOf("px"));
			} else if (containerW == "auto") {
				containerW = lbElement.defaults.width.substring(0, lbElement.defaults.width.indexOf("px"));
			}
		}
		containerH = (lbElement.settings.height != "") ? lbElement.settings.height : lbContainer.css("height");
		if (typeof containerH != "number") {
			if (containerH.indexOf("px") >= 0) {
				containerH = containerH.substring(0, containerH.indexOf("px"));
			} else if (containerH == "auto") {
				containerH = lbElement.defaults.height.substring(0, lbElement.defaults.height.indexOf("px"));
			}
		}
		var top  	= Math.max((viewportH - containerH - 18)/2, 20);
		var left 	= Math.max((viewportW - containerW - 18)/2, 20);
		containerH 	= Math.min(containerH, viewportH - 40 - 36);
		containerW 	= Math.min(containerW, viewportW - 40 - 36);
		if (typeof lbOptions.top != "undefined") {
			if (lbOptions.top.indexOf("px") >= 0) {
				lbOptions.top = lbOptions.top.substring(0, lbOptions.top.indexOf("px"));
			}
			top	= Math.max(top, lbOptions.top);
			containerH = Math.min(containerH, viewportH - 20 - 36 - lbOptions.top);
		}
		lbContainer.css({
			width:		containerW+"px",
			height:		containerH+"px",
			position:	'fixed',
			top:		top+"px",
			left:		left+"px"
		});
		return [containerW, containerH, viewportW, viewportH];
	};
	
	getViewportWidth = function() {
		var width = 0;
		if( document.documentElement && document.documentElement.clientWidth ) {
		    width = document.documentElement.clientWidth;
		}
		else if( document.body && document.body.clientWidth ) {
			width = document.body.clientWidth;
		}
		else if( window.innerWidth ) {
			width = window.innerWidth;
		}
//		width = window.innerWidth;
		return width;
	};

	getViewportHeight = function() {
		var height = 0;
		if( document.documentElement && document.documentElement.clientHeight ) {
			height = document.documentElement.clientHeight;
		}
		else if( document.body && document.body.clientHeight ) {
			height = document.body.clientHeight;
		}
		else if( window.innerHeight ) {
			height = window.innerHeight;
		}
//		height = window.innerHeight;
		return height;
	};
	
	jQuery.fn.lbPositionRelative = function (originElement) {
		var offset = $(originElement).offset();
		lbContainer.css({
			position:			'absolute',
			top:				(offset.top + $(originElement).height()),
			left:				offset.left
		});
	};
	
	jQuery.fn.lbSetOverlay = function () {
		$('#lbOverlay').css({
			backgroundColor:	lbElement.settings.overlayBgColor,
			opacity:			lbElement.settings.overlayOpacity,
			position:			'fixed',
			top:				'0px',
			left:				'0px',
			width:				'100%',
			height:				'100%',
			zIndex:				10000
		}).fadeIn(lbElement.settings.effectDuration);
	};
	
	jQuery.fn.lbOpen = function () {
		lbContainer.show("scale", {}, lbElement.settings.effectDuration, function () { setTimeout( "insertContent()", 500); });
//		lbContainer.show("scale", {}, lbElement.settings.effectDuration, function () { lbContainer.html(lbContent).lbCloseBtn(); });
	};
	
	insertContent = function() {
		lbContainer.append(lbContent).lbCloseBtn();
		lbContainer.attr("tabIndex", "0").focus();
		
		if (lbCallback !== undefined) {
			lbCallback();
		}
		
		if (typeof bindEventHandlers === 'function') {
			bindEventHandlers();
		}
	};
	
	jQuery.fn.lbClose = function () {
		//lbContainer.html("");
		//lbContainer.hide("scale", {}, 300, function () { lbContainer.html(lbContent); });
		//lbContainer.hide(300);
		lbContainer.fadeOut(100);
		$('#lbOverlay').fadeOut(300, function() { returnFocus(); } );
		if (lbElement.settings.calcWideMedia == 1) {
			lbContainer.find(".jwplayer").remove();
		}
		lbContainer.contents().remove();
		lbContainer.removeAttr("class").removeAttr("style").removeAttr("tabIndex");
		$(lbContent).find("#lbCloseBtn").remove();
		if (lbPreserve.theChildren.length > 0) {
			originContainer.append(lbPreserve.theChildren);
		}
	};
	
	returnFocus = function() {
		// make originElement focusable if not already
		if ($(originElement).attr("tabIndex") == undefined) {
			$(originElement).attr("tabIndex", "0");
		}
		$(originElement).focus();
	};
	
	appendCloseBtn = function() {
		closeButton = '<a id="lbCloseBtn" href="javascript:lbContainer.lbClose()" title="Close"></a>';
		if (typeof lbContent == "object") {
			lbContent.append(closeButton);
		} else if (typeof lbContent == "string"){
			lbContent += closeButton;
		}
	}
	
	jQuery.fn.lbCloseBtn = function () {
		if (lbCloseBtnClassName != "") {
			$('#lbCloseBtn').addClass(lbCloseBtnClassName);
		} else {
			$('#lbCloseBtn').css({
				backgroundImage:	'url("/images/close.gif")',
				display: 			'block',
				position: 			'absolute',
				top: 				'5px',
				right: 				'5px',
				indent: 			'-9999em',
				width: 				'16px',
				height: 			'16px'
			});
		}
	};
	
})(jQuery);

//// findPos() by quirksmode.org
//// Finds the absolute position of an element on a page
//findPos: function(obj) {
//	var curleft = curtop = 0;
//	if (obj.offsetParent) {	
//		do {
//			curleft += obj.offsetLeft;
//			curtop += obj.offsetTop;	
//		} while (obj = obj.offsetParent);
//	}
//	return [curleft,curtop];
//},
//
//// getPageScroll() by quirksmode.org
//// Finds the scroll position of a page
//getPageScroll: function() {
//	var xScroll, yScroll;
//	if (self.pageYOffset) {
//		yScroll = self.pageYOffset;
//		xScroll = self.pageXOffset;
//	} else if (document.documentElement && document.documentElement.scrollTop) {
//		yScroll = document.documentElement.scrollTop;
//		xScroll = document.documentElement.scrollLeft;
//	} else if (document.body) {// all other Explorers
//		yScroll = document.body.scrollTop;
//		xScroll = document.body.scrollLeft;
//	}
//	return [xScroll,yScroll]
//},
//
//// Finds the position of an element relative to the viewport.
//findPosRelativeToViewport: function(obj) {
//	var objPos = this.findPos(obj)
//	var scroll = this.getPageScroll()
//	return [ objPos[0]-scroll[0], objPos[1]-scroll[1] ]
//}

