/*
---------------------------------------------------------------------------------------

	Moonbeam - A File/Image Viewer

---------------------------------------------------------------------------------------

 Based on Cody Lindley's Thickbox:
  http://codylindley.com/Javascript/257/thickbox-one-box-to-rule-them-all
*/


var moonbeam = new Object();

// Initial settings
moonbeam.settings = {
	targetString: '.moonbeam',
	imageExtensions: ['jpg', 'jpeg', 'png', 'gif'],
	fileExtensions: ['html', 'htm', 'php', 'cfm', 'asp', 'aspx', 'jsp', 'jst', 'rb', 'txt'],
	resizeImages: true,
	cookieNameResizeImages: 'moonbeam_resize_images',
	overlayFadeSpeed: 300,
	contentFadeInSpeed: 800
};

moonbeam.makeRegExCallback = function(element, index, array) {
	if (!array.regEx) {
		array.regEx = '';
	}

	array.regEx += '\\.' + element;

	if (index < (array.length - 1)) {
		// Not the last index
		array.regEx += '|';
	} else {
		// Last index
		array.regEx = new RegExp(array.regEx, 'i');
	}
};

// Assemble RegExs for each array
moonbeam.settings.imageExtensions.forEach(moonbeam.makeRegExCallback);
moonbeam.settings.fileExtensions.forEach(moonbeam.makeRegExCallback);

moonbeam.setImageResizeCookie = function() {
	return $.cookie(moonbeam.settings.cookieNameResizeImages, moonbeam.settings.resizeImages,
		{expires: 365 * 5, path: '/'}
	);
}

moonbeam.eventHandler = function(event) {
	event.preventDefault();
	this.blur();

// 	var caption = this.title || stripTags(this.innerHTML) || this.href;
	var caption = this.moonbeamCaption || $(this).attr('title') || $(this).text() || $(this).attr('href');
	moonbeam.load(this.href, caption);
};

moonbeam.createViewer = function() {
/*
	This function creates the following HTML:
	-----------------------------------------

	<div id="moonbeam-overlay"></div>
	<div id="moonbeam-viewer">
		<div id="moonbeam-header">
			<h3 id="moonbeam-caption">Caption</h3>
			<a href="#" id="moonbeam-close" title="Close viewer">Close</a>
		</div>
		<form id="moonbeam-image-form" action="./">
			<div>
				<input type="checkbox" id="moonbeam-image-resize" />
				<label for="moonbeam-image-resize">Shrink images to fit window</label>
			</div>
		</form>
		<div id="moonbeam-content">
			<!-- Content -->
		</div>
	</div>
*/

	$(document.body).append(
		'<div id="moonbeam-overlay"></div>' +
		'<div id="moonbeam-viewer">' +
			'<div id="moonbeam-header">' +
				'<h3 id="moonbeam-title"></h3>' +
				'<a href="#" id="moonbeam-close" title="Close viewer">Close</a>' +
			'</div>' +
			'<form id="moonbeam-image-form" action="./">' +
				'<div>' +
					'<input type="checkbox" id="moonbeam-image-resize" />' +
					'<label for="moonbeam-image-resize">Shrink images to fit window</label>' +
				'</div>' +
			'</form>' +
			'<div id="moonbeam-content">' +
				'<div id="moonbeam-loading">Loading...</div>' +
			'</div>' +
		'</div>'
	);

	// Overlay
	moonbeam.overlay = $('#moonbeam-overlay')[0];
	addEvent(moonbeam.overlay, 'click', moonbeam.close);

	// Viewer
	moonbeam.viewer = $('#moonbeam-viewer')[0];

	// Header element
	moonbeam.viewer.headerElement = $('#moonbeam-header')[0];
		// The title/caption element
		moonbeam.viewer.titleElement = $('#moonbeam-title')[0];

		// Close link
		moonbeam.viewer.closeLink = $('#moonbeam-close')[0];
		addEvent(moonbeam.viewer.closeLink, 'click', function(event) {
			event.preventDefault();
			moonbeam.close();
		});

	// Image resize form
	moonbeam.viewer.imageForm = $('#moonbeam-image-form')[0];
		// Checkbox
		moonbeam.viewer.imageForm.resizeCheckbox = $('#moonbeam-image-resize')[0];
		if (moonbeam.settings.resizeImages == true) {
// 			moonbeam.viewer.imageForm.resizeCheckbox.checked = true;
			$(moonbeam.viewer.imageForm.resizeCheckbox).attr('checked', 'checked');
		}
		addEvent(moonbeam.viewer.imageForm.resizeCheckbox, 'click', function(event) {
			if (moonbeam.settings.resizeImages == true) {
				moonbeam.settings.resizeImages = false;
// 				$('img', moonbeam.viewer.contentElement).each(function() {
// 					this.style.width = '';
// 					this.style.height = '';
// 				});
				$('img', moonbeam.viewer.contentElement).width('').height('');
			} else {
				moonbeam.settings.resizeImages = true;
			}
			moonbeam.setImageResizeCookie();
			moonbeam.updateSize();
		});

	// Content element
	moonbeam.viewer.contentElement = $('#moonbeam-content')[0];
		// Loading element
		moonbeam.viewer.contentElement.loading = $('#moonbeam-loading')[0];


	moonbeam.viewer.resized = false;



/* ------------- Stuff that should really be in a callback ------------- */


// Let the formManager make our pretty checkboxes interactive
formManager.add('checkbox', moonbeam.viewer);

// $(moonbeam.viewer.closeLink).Tooltip({
// 	track: false,
// 	extraClass: 'no-heading'
// });


/*
		Extra code to add these elements around the content element, for borders:
		-------------------------------------------------------------------------

		<div id="moonbeam-content-wrapper" class="divider-v">
			<div class="divider-v">
				<div class="divider-h" />
				<div id="moonbeam-content">

					<!-- Content -->

				</div>
				<div class="divider-h" />
			</div>
		</div>
*/

	$(moonbeam.viewer).append(
		'<div id="moonbeam-content-wrapper" class="divider-v">' +
			'<div class="divider-v">' +
				'<div class="divider-h"></div>' +
			'</div>' +
		'</div>'
	);
	var contentWrapper = $('#moonbeam-content-wrapper')[0];
	$('.divider-v', contentWrapper).append(moonbeam.viewer.contentElement);
	$('.divider-v', contentWrapper).append('<div class="divider-h"></div>');


/*
	Extra code to add these elements around the entire viewer contents,
	for edge effects:
	-------------------------------------------------------------------

	<div id="moonbeam-viewer">
		<div id="moonbeam-top">
			<div class="top-left" />
			<div class="top-right" />
		</div>
		<div id="moonbeam-body"><div>

				<!-- Header, Image Form, and Content -->

		</div></div>
		<div id="moonbeam-bottom">
			<div class="bottom-left" />
			<div class="bottom-right" />
		</div>
	</div>
*/

	$(moonbeam.viewer).append(
		'<div id="moonbeam-top">' +
			'<div class="top-left"></div>' +
			'<div class="top-right"></div>' +
		'</div>' +
		'<div id="moonbeam-body">' +
			'<div id="moonbeam-body-wrapper"></div>' +
		'</div>' +
		'<div id="moonbeam-bottom">' +
			'<div class="bottom-left"></div>' +
			'<div class="bottom-right"></div>' +
		'</div>'
	);
	$('#moonbeam-body-wrapper').append(moonbeam.viewer.headerElement);
	// jQuery bug? -> label gets left behind in previous location (FIXED!)
	$('#moonbeam-body-wrapper').append(moonbeam.viewer.imageForm);
// 	$('#moonbeam-body-wrapper')[0].appendChild(moonbeam.viewer.imageForm);
	$('#moonbeam-body-wrapper').append(contentWrapper);

};

moonbeam.load = function(url, caption) {
	
	// Create the viewer and overlay if they don't exist yet
	if (!moonbeam.viewer) {
		moonbeam.createViewer();
	}

	// IE 6 shows select boxes above overlay, hide them
	if ($.browser.msie && ieVersion < 7) {
		$('select:visible').addClass('ie-selects');
	}

	$(moonbeam.viewer).addClass('loading');

	$(moonbeam.viewer.titleElement).append(caption);

// 	moonbeam.overlay.style.opacity = 0;
	$('body').append(moonbeam.overlay, moonbeam.viewer);
	moonbeam.overlay.initialOpacity = $(moonbeam.overlay).css('opacity');
// 	$(moonbeam.overlay).fadeTo(moonbeam.settings.overlayFadeSpeed, getNumericStyle(moonbeam.overlay, 'opacity'), function() {
// 		this.style.opacity = '';
// 	});

	moonbeam.updateSize();

	if (moonbeam.settings.imageExtensions.regEx.test(url)) {
		// Content is an image
		moonbeam.viewer.contentType = 'image';

		var imagePreloader = new Image();
		addEvent(imagePreloader, 'load', function() {
			var imageElement = createElement('img');
// 			imageElement.src = this.src;
// 			imageElement.alt = this.alt;
			$(imageElement).attr({
				src: $(this).attr('src'),
				alt: $(this).attr('alt')
			});

			$(moonbeam.viewer).removeClass('loading');
			$(moonbeam.viewer.contentElement.loading).remove();

			$(imageElement).hide();
			$(moonbeam.viewer.contentElement).append(imageElement);
			$(imageElement).fadeIn(moonbeam.settings.contentFadeInSpeed, function() {
// 				this.style.opacity = '';
// 				$(this).css('opacity', '');
			});

			moonbeam.updateSize();
		});
// 		imagePreloader.src = url;
// 		imagePreloader.alt = caption;
		$(imagePreloader).attr({
			src: url,
			alt: caption
		});
	} else if (url.match(moonbeam.settings.fileExtensions.regEx) == '.txt') {
		// Content is a text file
		moonbeam.viewer.contentType = 'text';

		$.get(url, function(textContent) {
			var textfileContainer = createElement('pre');
			textfileContainer.id = 'text-file-container';
			$(textfileContainer).hide();
			$(moonbeam.viewer.contentElement).append(textfileContainer);

// 			$('#text-file-container').append(escapeHTML(textContent));
			$('#text-file-container').text(textContent);

			$(moonbeam.viewer).removeClass('loading');
			$(moonbeam.viewer.contentElement.loading).remove();

			$('#text-file-container').fadeIn(moonbeam.settings.contentFadeInSpeed, function() {
// 				this.style.opacity = '';
// 				$(this).css('opacity', '');
			});
			moonbeam.updateSize();
		});
	} else {
		// All other content types
	}
	
	$(moonbeam.viewer).addClass('content-' + moonbeam.viewer.contentType);

// 	alert('offsetWidth: '+ moonbeam.viewer.offsetWidth
// 		+ '\nCSS Width: ' + parseInt(getStyle(moonbeam.viewer, 'width', 'width'))
// 		+ '\noffsetHeight: ' + moonbeam.viewer.offsetHeight
// 		+ '\nCSS Height: ' + parseInt(getStyle(moonbeam.viewer, 'height', 'height')));

	addEvent(window, 'resize', moonbeam.updateSize);
	if ($.browser.msie && ieVersion < 7) {
		addEvent(window, 'scroll', moonbeam.updatePosition);
	}
};

moonbeam.close = function() {
	$(moonbeam.viewer).remove();
	$(moonbeam.overlay).fadeTo(moonbeam.settings.overlayFadeSpeed, 0, function() {
		$(this).remove();
		$(this).css('opacity', '');
// 		$(this).css('opacity', this.initialOpacity);

		if ($.browser.msie) {
			this.style.filter = '';
			if (ieVersion < 7) {
				$('select:hidden').removeClass('ie-selects');
			}
		}
	});

	// Empty caption and content elements
	$(moonbeam.viewer.titleElement).empty();
	$(moonbeam.viewer.contentElement).empty();

	// Insert the "Loading..." message for the next time viewer is opened
	moonbeam.viewer.contentElement.appendChild(moonbeam.viewer.contentElement.loading);

	// Remove inline width/height styles
// 	moonbeam.viewer.style.width = '';
// 	moonbeam.viewer.style.height = '';
// 	moonbeam.viewer.contentElement.style.width = '';
// 	moonbeam.viewer.contentElement.style.height = '';
	$([moonbeam.viewer, moonbeam.viewer.contentElement]).width('').height('');

	// Remove the content and resized classes
	$(moonbeam.viewer).removeClass('content-' + moonbeam.viewer.contentType);
	$(moonbeam.viewer).removeClass('resized');
	moonbeam.viewer.resized = false;

	// Empty the content type variable
	moonbeam.viewer.contentType = '';

	// Remove resize event
	removeEvent(window, 'resize', moonbeam.updateSize);

	// Remove the scroll event for IE
	if ($.browser.msie && ieVersion < 7) {
		removeEvent(window, 'scroll', moonbeam.updatePosition);
	}
};

moonbeam.updatePosition = function() {
	$(moonbeam.viewer).removeClass('resized');

// 	var viewportSize = getViewportSize();
	var viewportW = $(window).width();
	var viewportH = $(window).height();

	var viewerW = moonbeam.viewer.offsetWidth;
	var viewerH = moonbeam.viewer.offsetHeight;

// 	var marginTop = getNumericStyle(moonbeam.viewer, 'margin-top', 'marginTop');
// 	var marginLeft = getNumericStyle(moonbeam.viewer, 'margin-left', 'marginLeft');
	var marginTop = parseInt($(moonbeam.viewer).css('margin-top'));
	var marginLeft = parseInt($(moonbeam.viewer).css('margin-left'));

// 	moonbeam.viewer.style.left = Math.round((parseInt(viewportSize[0]) - viewerW) / 2) - marginLeft + 'px';
// 	moonbeam.viewer.style.top = Math.round((parseInt(viewportSize[1]) - viewerH) / 2) - marginTop + 'px';
	$(moonbeam.viewer).css({
		left: Math.round((viewportW - viewerW) / 2) - marginLeft,
		top: Math.round((viewportH - viewerH) / 2) - marginTop
	});

	// IE 6 - simulate fixed position
	if ($.browser.msie && ieVersion < 7) {
// 		var pageScroll = getPageScroll();
		$(moonbeam.viewer).css('top', parseInt($(moonbeam.viewer).css('top')) + $(window).scrollTop());
	}

	if (moonbeam.viewer.resized == true) {
		$(moonbeam.viewer).addClass('resized');
	}
};

moonbeam.updateSize = function(noUpdatePosition) {

	moonbeam.viewer.resized = false;
	$(moonbeam.viewer).removeClass('resized');

// 	moonbeam.viewer.style.width = '';
// 	moonbeam.viewer.style.height = '';
// 	moonbeam.viewer.contentElement.style.width = '';
// 	moonbeam.viewer.contentElement.style.height = '';
	$([moonbeam.viewer, moonbeam.viewer.contentElement]).width('').height('');

// 	var viewportSize = getViewportSize();
// 	var viewportW = parseInt(viewportSize[0]);
// 	var viewportH = parseInt(viewportSize[1]);
	var viewportW = $(window).width();
	var viewportH = $(window).height();

// 	var viewerW = moonbeam.viewer.offsetWidth;
// 	var viewerH = moonbeam.viewer.offsetHeight;
	var viewerW = $(moonbeam.viewer).outerWidth();
	var viewerH = $(moonbeam.viewer).outerHeight();

	// Viewer left/right margins
// 	var viewerMarginW = getNumericStyle(moonbeam.viewer, 'margin-left', 'marginLeft')
// 		+ getNumericStyle(moonbeam.viewer, 'margin-right', 'marginRight');
	var viewerMarginW = parseInt($(moonbeam.viewer).css('margin-left'))
		+ parseInt($(moonbeam.viewer).css('margin-right'));
	// Viewer top/bottom margins
// 	var viewerMarginH = getNumericStyle(moonbeam.viewer, 'margin-top', 'marginTop')
// 		+ getNumericStyle(moonbeam.viewer, 'margin-bottom', 'marginBottom');
	var viewerMarginH = parseInt($(moonbeam.viewer).css('margin-top'))
		+ parseInt($(moonbeam.viewer).css('margin-bottom'));

// 	var contentW = moonbeam.viewer.contentElement.offsetWidth;
// 	var contentH = moonbeam.viewer.contentElement.offsetHeight;
	var contentW = $(moonbeam.viewer.contentElement).outerWidth();
	var contentH = $(moonbeam.viewer.contentElement).outerHeight();

	var ratioW = viewportW / (viewerW + viewerMarginW);
	var ratioH = viewportH / (viewerH + viewerMarginH);
	
	var contentDiffW = viewerW - contentW;
	var contentDiffH = viewerH - contentH;

	// If viewer is wider than viewport...
	if ((viewerW + viewerMarginW) > viewportW) {
		// Viewer left/right border widths
// 		var viewerBorderW = getNumericStyle(moonbeam.viewer, 'border-left-width', 'borderLeftWidth')
// 			+ getNumericStyle(moonbeam.viewer, 'border-right-width', 'borderRightWidth');
		var viewerBorderW = parseInt($(moonbeam.viewer).css('border-left-width'))
			+ parseInt($(moonbeam.viewer).css('border-right-width'));

		// Viewer left/right padding
// 		var viewerPaddingW = getNumericStyle(moonbeam.viewer, 'padding-left', 'paddingLeft')
// 			+ getNumericStyle(moonbeam.viewer, 'padding-right', 'paddingRight');
		var viewerPaddingW = parseInt($(moonbeam.viewer).css('padding-left'))
			+ parseInt($(moonbeam.viewer).css('padding-right'));

		// Content left/right border widths
// 		var contentBorderW = getNumericStyle(moonbeam.viewer.contentElement, 'border-left-width', 'borderLeftWidth')
// 			+ getNumericStyle(moonbeam.viewer.contentElement, 'border-right-width', 'borderRightWidth');
		var contentBorderW = parseInt($(moonbeam.viewer.contentElement).css('border-left-width'))
			+ parseInt($(moonbeam.viewer.contentElement).css('border-right-width'));

		// Content left/right padding
// 		var contentPaddingW = getNumericStyle(moonbeam.viewer.contentElement, 'padding-left', 'paddingLeft')
// 			+ getNumericStyle(moonbeam.viewer.contentElement, 'padding-right', 'paddingRight');
		var contentPaddingW = parseInt($(moonbeam.viewer.contentElement).css('padding-left'))
			+ parseInt($(moonbeam.viewer.contentElement).css('padding-right'));

		$(moonbeam.viewer).width(Math.round(viewerW * ratioW) - (viewerBorderW + viewerPaddingW));
		$(moonbeam.viewer.contentElement).width(Math.round(viewerW * ratioW) - (contentDiffW + contentBorderW + contentPaddingW));
		moonbeam.viewer.resized = true;
	}

	// If viewer is taller than viewport...
	if ((viewerH + viewerMarginH) > viewportH) {
		// Viewer top/bottom border widths
// 		var viewerBorderH = getNumericStyle(moonbeam.viewer, 'border-top-width', 'borderTopWidth')
// 			+ getNumericStyle(moonbeam.viewer, 'border-bottom-width', 'borderBottomWidth');
		var viewerBorderH = parseInt($(moonbeam.viewer).css('border-top-width'))
			+ parseInt($(moonbeam.viewer).css('border-bottom-width'));

		// Viewer top/bottom padding
// 		var viewerPaddingH = getNumericStyle(moonbeam.viewer, 'padding-top', 'paddingTop')
// 			+ getNumericStyle(moonbeam.viewer, 'padding-bottom', 'paddingBottom');
		var viewerPaddingH = parseInt($(moonbeam.viewer).css('padding-top'))
			+ parseInt($(moonbeam.viewer).css('padding-bottom'));

		// Content top/bottom border widths
// 		var contentBorderH = getNumericStyle(moonbeam.viewer.contentElement, 'border-top-width', 'borderTopWidth')
// 			+ getNumericStyle(moonbeam.viewer.contentElement, 'border-bottom-width', 'borderBottomWidth');
		var contentBorderH = parseInt($(moonbeam.viewer.contentElement).css('border-top-width'))
			+ parseInt($(moonbeam.viewer.contentElement).css('border-bottom-width'));

		// Content top/bottom padding
// 		var contentPaddingH = getNumericStyle(moonbeam.viewer.contentElement, 'padding-top', 'paddingTop')
// 			+ getNumericStyle(moonbeam.viewer.contentElement, 'padding-bottom', 'paddingBottom');
		var contentPaddingH = parseInt($(moonbeam.viewer.contentElement).css('padding-top'))
			+ parseInt($(moonbeam.viewer.contentElement).css('padding-bottom'));

		$(moonbeam.viewer).height(Math.round(viewerH * ratioH) - (viewerBorderH + viewerPaddingH));
		$(moonbeam.viewer.contentElement).height(Math.round(viewerH * ratioH) - (contentDiffH + contentBorderH + contentPaddingH));
		moonbeam.viewer.resized = true;
	}

	if ((moonbeam.viewer.contentType == 'image') && (moonbeam.settings.resizeImages == true)) {
// 		$('img', moonbeam.viewer.contentElement).each(function() {
// 			moonbeam.resizeImage(this);
// 		});
		moonbeam.resizeImage($('img', moonbeam.viewer.contentElement)[0]);
	} else if (moonbeam.viewer.resized == true) {
		$(moonbeam.viewer).addClass('resized');
	}

	moonbeam.updatePosition();
};

moonbeam.resizeImage = function(imageElement) {
	// Modified version of Thickbox's image resizing code
	
// 	imageElement.style.width = '';
// 	imageElement.style.height = '';
	$(imageElement).width('').height('');

// 	var contentW = moonbeam.viewer.contentElement.offsetWidth
// 		- (getNumericStyle(moonbeam.viewer.contentElement, 'border-left-width', 'borderLeftWidth')
// 		+ getNumericStyle(moonbeam.viewer.contentElement, 'border-right-width', 'borderRightWidth')
// 		+ getNumericStyle(moonbeam.viewer.contentElement, 'padding-left', 'paddingLeft')
// 		+ getNumericStyle(moonbeam.viewer.contentElement, 'padding-right', 'paddingRight')
// 	);
// 	var contentH = moonbeam.viewer.contentElement.offsetHeight
// 		- (getNumericStyle(moonbeam.viewer.contentElement, 'border-top-width', 'borderTopWidth')
// 		+ getNumericStyle(moonbeam.viewer.contentElement, 'border-bottom-width', 'borderBottomWidth')
// 		+ getNumericStyle(moonbeam.viewer.contentElement, 'padding-top', 'paddingTop')
// 		+ getNumericStyle(moonbeam.viewer.contentElement, 'padding-bottom', 'paddingBottom')
// 	);
	var contentW = $(moonbeam.viewer.contentElement).width();
	var contentH = $(moonbeam.viewer.contentElement).height();

	// Don't use $(imageElement).attr() to get 'width' or 'height' attributes,
	// jQuery assumes you meant $(imageElement).width()/.height(), which is CSS!
	if (imageElement.width > contentW) {
		$(imageElement).height(Math.round(imageElement.height * (contentW / imageElement.width)));
		$(imageElement).width(contentW);

		$([moonbeam.viewer, moonbeam.viewer.contentElement]).height('');

		if (imageElement.height > contentH) {
			$(imageElement).width(Math.round(imageElement.width * (contentH / imageElement.height)));
			$(imageElement).height(contentH);

			$([moonbeam.viewer, moonbeam.viewer.contentElement]).width('');
		}
	} else if (imageElement.height > contentH) {
		$(imageElement).width(Math.round(imageElement.width * (contentH / imageElement.height)));
		$(imageElement).height(contentH);

		$([moonbeam.viewer, moonbeam.viewer.contentElement]).width('');

		if (imageElement.width > contentW) {
			$(imageElement).height(Math.round(imageElement.height * (contentW / imageElement.width)));
			$(imageElement).width(contentW);

			$([moonbeam.viewer, moonbeam.viewer.contentElement]).height('');
		}
	}
};

moonbeam.init = function() {
	
	// I'm just sick of putting up with IE 6's bugs
	if ($.browser.msie && ieVersion < 7) {
		return;
	}

	$(moonbeam.settings.targetString).each(function(i) {
		addEvent(this, 'click', moonbeam.eventHandler);
	});

	var imageResizeCookie = $.cookie(moonbeam.settings.cookieNameResizeImages);
	if (imageResizeCookie === 'false') {
		moonbeam.settings.resizeImages = false;
	}

// 	moonbeam.createViewer();
};

if (jQuery) {
	$(document).ready(moonbeam.init);
}
