/*
* Lighterbox - a popup replacer for images and html content
*
* Version: 0.1 Beta
* Author:  David Dixon (info@digitaloasis.co.uk)
*
* Acknowledgements:
*          Idea, and functionality adapted from ThickBox 2.1 (http://jquery.com/demo/thickbox/)
*          and Lightbox JS 2.0 (http://www.huddletogether.com/projects/lightbox2/)
*
* Non-public beta. No unautorised usage or copying permitted until official release
*/
var Lighterbox = Class.create();
// document.write('<link rel="stylesheet" type="text/css" href="/css/lighterbox.css" media="screen"/>');

Lighterbox.prototype = {

	page_size: {'px':0, 'py':0, 'wx':0, 'wy':0, 'ox':0, 'oy':0}, // px/py - full page, wx/wy - visible window
	loading_image: {},
	observers: {}, // reference object to own observers
	valid_images: /(\.jpg|\.jpeg|\.png|\.gif|\.bmp)$/g,
	body: {},
	gallery: {},
	view_width: 0,
	valid_params: ['height', 'width','iframe'],

	initialize: function() {
		var hotspots = document.getElementsByTagName('a');

		for (var i = 0; i < hotspots.length; i++) {
		    var hotspot =  hotspots[i];

			if (hotspot.getAttribute('href') && hotspot.className.indexOf('lighterbox') != -1) {
				hotspot.onclick = function(e) { this.show(e); }.bind(this);
			}
		}

		this.loading_image = new Image();
		this.loading_image.src = '/staticfiles/images/application/loading.gif';
		
		this.body = document.getElementsByTagName('body')[0];

	},
	
	show: function (e) {
	    e = e || window.event;
		Event.stop(e);
	    targ = Event.findElement(e,'a');
	    this.getPageSize();
	    this.showOverlay();
		this.showContent(targ);
	},
	
	showOverlay: function() {
		var iframe = $E({tag: 'iframe', id: 'lighterbox-iframe'});
		var container = $E({tag: 'div',	id: 'lighterbox-overlay'});
		container.onclick = function() { this.hide() }.bindAsEventListener(this);
		this.resizeOverlay(iframe);
		this.resizeOverlay(container);
		this.body.appendChild(iframe);
		this.body.appendChild(container);
		this.observers['adjustPosition'] = function() { this.adjustPosition()}.bindAsEventListener(this);
		Event.observe(window, 'resize', this.observers['adjustPosition'], false);
		Event.observe(window, 'scroll', this.observers['adjustPosition'], false);
	},
	
	hideOverlay: function() {
		Event.stopObserving(window, 'resize', this.observers['adjustPosition'], false);
		Event.stopObserving(window, 'scroll', this.observers['adjustPosition'], false);
		
		Effect.Fade('lighterbox-overlay', {duration: .2, afterFinish:
			function() { Element.remove($('lighterbox-overlay')); Element.remove($('lighterbox-iframe')); }
		});
	},
	
	showContent: function(targ) {
		var content = $E({tag: 'div', id: 'lighterbox-content'});
		this.body.appendChild(content);
		
		var url = targ.href.indexOf('?')!==-1 ? targ.href.substr(0, targ.href.indexOf('?')) : targ.href;
		if (url.toLowerCase().match(this.valid_images)) {
			this.showImage(targ);
		} else {
		    this.showHTML(targ);
		}
	},

	showImage: function(targ) {
		this.show_content();
		this.adjustPosition($('lighterbox-content').getHeight());
		this.showLoading();
		if (targ.rel) { // grouped
			var hotspots = document.getElementsByTagName('a');
			var siblings = [];
			this.gallery = {next_html: '', prev_html: ''};
			for (var i = 0; i < hotspots.length; i++) {
			    var hotspot =  hotspots[i];
				if (hotspot.getAttribute('href') && hotspot.className.indexOf('lighterbox') != -1 && hotspot.getAttribute('rel') == targ.rel) {
					siblings.push(hotspot);
				}
			}

			for (var i = 0; (i < siblings.length && !this.gallery.next); i++) {
				if (siblings[i] != targ) {
					 if (this.gallery.found) { // next
					    this.gallery.next = siblings[i];
					    this.gallery.next_html = '<span id="lighterbox-next">&nbsp;&nbsp;<a href="#">Next &gt;</a></span>';
					 } else { // prev
					    this.gallery.prev = siblings[i];
					    this.gallery.prev_html = '<span id="lighterbox-prev">&nbsp;&nbsp;<a href="#">&lt; Prev</a></span>';
					 }
				} else {
				    this.gallery.found = true;
				    this.gallery.count = 'Image ' + (i + 1) +' of '+ (siblings.length);
				}
			}
	    }

		this.gallery.image = new Image();
		this.gallery.image.onload = function() { this.resizeContent(targ); }.bindAsEventListener(this);
	   	this.gallery.image.src = targ.href;
	},
	
	resizeContent: function(targ) {
		// get current height and width
		var size = Element.getDimensions('lighterbox-content');
		
		this.gallery.image_size = this.resizeImage(); // calc image size based on avail screen area

		// scalars based on change from old to new
		var xScale = ((this.gallery.image_size.width  + (10 * 2)) / size.width) * 100;
		var yScale = ((this.gallery.image_size.height  + (10 * 2)) / size.height) * 100;

		// calculate size difference between new and old image, and resize if necessary
		wDiff = (size.width - 10 * 2) - this.gallery.image_size.width;
		hDiff = (size.height - 10 * 2) - this.gallery.image_size.height;

		if(!( hDiff == 0) && !( wDiff == 0)){
			new Effect.Scale('lighterbox-content', yScale, {scaleContent: false, scaleFromCenter: true, scaleX: false, duration: .6, queue: 'front'});
			new Effect.Scale('lighterbox-content', xScale, {scaleContent: false, scaleFromCenter: true, scaleY: false, delay: .6, duration: .6, afterFinish: function(){this.createImage(targ)}.bind(this)});
		} else if (!( hDiff == 0)) {
			new Effect.Scale('lighterbox-content', yScale, {scaleContent: false, scaleFromCenter: true, scaleX: false, duration: .8, queue: 'front', afterFinish: function(){this.createImage(targ)}.bind(this)});
		} else if ( !( wDiff == 0)) {
			new Effect.Scale('lighterbox-content', xScale, {scaleContent: false, scaleFromCenter: true, scaleY: false, delay: .8, duration: .8, afterFinish: function(){this.createImage(targ)}.bind(this)});
		} else {
			this.createImage(targ);
		}

	},
	
	createImage: function(targ) {
	    this.hideLoading();
	    
	    if ($('lighterbox-content')) {

		    var border = 10;
		    this.gallery.image_size = this.resizeImage();

		    this.view_width = this.gallery.image_size.width + (border*2);

	     	this.gallery.image_content = $E({ tag:'span', id:'lighterbox-image_content' });
			this.gallery.image_desc = $E({ tag:'div', id:'lighterbox-desc', children:{ tag: 'div', id:'lighterbox-desc2' } });
			this.gallery.image_caption = $E({
				tag:'div', id:'lighterbox-caption', children:[
				    targ.title
				,{
				    tag:'div', id:'lighterbox-caption2', innerHTML:this.gallery.count + this.gallery.prev_html + this.gallery.next_html
				}]
			});
			this.gallery.image_close = $E({
			    tag:'div', id:'lighterbox-close', children:{
					tag:'a', id:'lighterbox-closebutton', href:'#', title:'close', innerHTML:'close', onclick:function() { this.hide(); return false; }.bindAsEventListener(this)
				}
			});

			$('lighterbox-content').appendChild(this.gallery.image_content);
			this.showImagePic(targ);
			$('lighterbox-content').appendChild(this.gallery.image_desc);
			$('lighterbox-desc2').appendChild(this.gallery.image_caption);
			$('lighterbox-desc2').appendChild(this.gallery.image_close);

			$('lighterbox-desc').hide();
			Element.setOpacity($('lighterbox-desc'), 0);

			this.adjustPosition();

			new Effect.Parallel([
				new Effect.SlideDown( 'lighterbox-desc', { sync: true, duration: .8, from: 0.0, to: 1.0 }),
		  		new Effect.Opacity('lighterbox-desc', { sync: true, duration: 1.2, from: 0.0, to: .9999 }),
		  		new Effect.Opacity('lighterbox-image', { sync: true, duration: 1.2, from: 0.0, to: .9999 })
		  	]);
		  	$('lighterbox-image_content').onclick = function(){ this.hide(); }.bindAsEventListener(this);
			if ($('lighterbox-next')) {
				$('lighterbox-next').onclick = function() { this.showNext(); return false; }.bindAsEventListener(this);
			}
			if ($('lighterbox-prev')) {
				$('lighterbox-prev').onclick = function() { this.showNext(true); return false; }.bindAsEventListener(this);
			}
		}
	},
	
	removeImage: function() {
	    Element.remove($('lighterbox-image_content'));
		Element.remove($('lighterbox-desc'));
	},
	
	showImagePic: function(targ) {
	    this.gallery.image_image = $E({
			tag:'img', id:'lighterbox-image', src:targ.href, width:this.gallery.image_size.width, height:this.gallery.image_size.height, alt:targ.title
		});
		Element.setOpacity(this.gallery.image_image, 0);
		$('lighterbox-image_content').appendChild(this.gallery.image_image);
	},
	
	hideImagePic: function() {
	    Element.remove($('lighterbox-image'));
	},
	
	showNext: function(prev) {
	    var cur_width = $('lighterbox-content').offsetWidth + 'px';
		var cur_height = ($('lighterbox-content').offsetHeight - $('lighterbox-caption').offsetHeight - 11) + 'px';
		 new Effect.Parallel(
			[
				new Effect.SlideUp('lighterbox-desc', { sync: true, duration: .8, from: 0.0, to: 1.0 }),
	  			new Effect.Fade('lighterbox-desc', { sync: true, duration: .8}),
	  			new Effect.Fade('lighterbox-image_content', { sync: true, duration: .8})
			],{
				afterFinish: function()	{
				    $('lighterbox-content').style.height = cur_height;
				    $('lighterbox-content').style.width = cur_width;
					this.removeImage();
					if (prev) { this.showImage(this.gallery.prev); } else { this.showImage(this.gallery.next); }
				}.bind(this)
			}
		);
	},
	
	resizeImage: function() {
		var x = this.page_size.wx - 150;
		var y = this.page_size.wy - 150;
		var imageWidth = this.gallery.image.width;
		var imageHeight = this.gallery.image.height;
		if (imageWidth > x) {
			imageHeight = imageHeight * (x / imageWidth);
			imageWidth = x;
			if (imageHeight > y) {
				imageWidth = imageWidth * (y / imageHeight);
				imageHeight = y;
			}
		} else if (imageHeight > y) {
			imageWidth = imageWidth * (y / imageHeight);
			imageHeight = y;
			if (imageWidth > x) {
				imageHeight = imageHeight * (x / imageWidth);
				imageWidth = x;
			}
		}
		return {width: imageWidth, height: imageHeight};
	},

	showHTML: function (targ) {
		this.showLoading();
		var t_qs = targ.href.split('?');
		var qs = {base_url:t_qs[0], query:t_qs[1]?$H(t_qs[1].parseQuery()):null};
		// if qs is present, add lb params to qs obj and remove from qs
		if (qs.query) {
		    this.valid_params.each(function(elem){
		        qs[elem] = this.query_get('lb_'+elem, qs.query);
		    }.bind(this));
		    
			qs.query = this.query_clean(qs.query);
			qs.base_url += '?' + qs.query.toQueryString();
		}

		if (qs.iframe) {
		    Element.update($('lighterbox-content'),'<div id="lighterbox-html_caption"><div id="lighterbox-html_title">'+targ.title+'</div><div id="lighterbox-html_close" class="replace"><a href="#" id="lighterbox-closebutton" title="close">close<span></span></a></div></div><iframe frameborder="0" hspace="0" src="'+qs.base_url+'" id="lightbox-html_framed" name="lightbox-html_framed" style="height:'+(qs.height ? qs.height : (this.page_size.wy-100)+'px')+';width:'+(qs.width ? qs.width : (this.page_size.wx-80)+'px')+';"></iframe>');
	        $('lightbox-html_framed').onload = function() { this.showLoaded('lightbox-html_framed') }.bindAsEventListener(this);
	        $('lightbox-html_framed').onreadystatechange = this.ieLoaded.bindAsEventListener(this);
        	if (Browser.isSafari) { // be nice to safari
	        	this.showLoaded('lightbox-html_framed');
	    	}
	        this.view_width = $('lightbox-html_framed').offsetWidth;

		} else {
		    $('lighterbox-content').innerHTML += '<div id="lighterbox-html_caption"><div id="lighterbox-html_title">'+targ.title+'</div><div id="lighterbox-html_close" class="replace"><a href="#" id="lighterbox-closebutton" title="close">close<span></span></a></div></div><div id="lightbox-html_ajax" style="height:'+(qs.height ? qs.height : (this.page_size.wy -100)+'px')+';width:'+(qs.width ? qs.width : (this.page_size.wx -80)+'px')+';"></div>';
        	this.view_width = $('lightbox-html_ajax').offsetWidth;
        	new Ajax.Updater('lightbox-html_ajax', qs.base_url, {method: 'get', parameters: '', onComplete: function() {this.showLoaded('lightbox-html_ajax')}.bind(this)});
		}

        $('lighterbox-closebutton').onclick = function(e) { Event.stop(e); this.hide(); }.bindAsEventListener(this)
        
		this.createBorders();
		this.adjustPosition();
		this.show_content();
	},
	
	ieLoaded: function() {
	    if ($('lightbox-html_framed').readyState == 'complete') {
	        this.showLoaded('lightbox-html_framed');
	    }
	},
	
	showLoaded: function(targ) {
	    this.hideLoading();
	    $(targ).style.visibility = 'visible';
	},
	
	createBorders: function() {
		Element.addClassName($('lighterbox-content'), 'html-border');
	},
	
	
	query_get: function (key, query) {
		if (query[key]) {
			var tmp = query[key];
			query[key] = null;
			return tmp;
		} else {
		    return null;
		}
	},
	
	query_clean: function (query) {
	    var qs_keys = query.keys();
	    var new_qs = {};
        qs_keys.each(function(key){
			if (query[key]) {
			    new_qs[key] = query[key];
			}
		});
		return $H(new_qs);
	},
	
	showLoading: function() {
		var loading = $E({tag: 'img', src: this.loading_image.src, id: 'lighterbox-loading', width: this.loading_image.width, height: this.loading_image.height});

		loading.style.top = (this.page_size.wy - this.loading_image.height)/2 + 'px';
		loading.style.left = (this.page_size.wx - this.loading_image.width)/2 + 'px';
		loading.style.display = 'block';
		loading.onclick = function() { this.hide() }.bindAsEventListener(this);

		this.body.appendChild(loading);
	},
	
	hideLoading: function() {
	    if ($('lighterbox-loading')) {
	    	Element.remove($('lighterbox-loading'));
		}
	},
	
	hide: function(refresh) {
	
	    if ($('lighterbox-loading')) {
	        Element.remove($('lighterbox-loading'));
	    }
	
		if (!refresh) {
			Event.stopObserving(window, 'resize', this.observers['adjustPosition'], false);
			Event.stopObserving(window, 'scroll', this.observers['adjustPosition'], false);

	        Try.these (
	        	function() { Element.remove($('lighterbox-content')); return 1;},
	        	function() { this.remove(); return 1 }.bind(this)
	        )
	        Effect.Fade('lighterbox-overlay', {duration: .2, afterFinish: this.remove});
		} else {
			//new Effect.switchOff($('lighterbox-content'));
		    Element.remove($('lighterbox-content'));
		}
	
	},
	
	show_content: function() {
	    $('lighterbox-content').style.visibility = 'visible';
	},
	
	hide_content: function() {
	    $('lighterbox-content').style.visibility = 'hidden';
	},
	
	remove: function() {
	    Element.remove($('lighterbox-overlay'));
		Element.remove($('lighterbox-iframe'));
	},
	
	adjustPosition: function(height) {
        this.resizeOverlay($('lighterbox-iframe'));
		this.resizeOverlay($('lighterbox-overlay'));
		if ($('lighterbox-loading')) {
			$('lighterbox-loading').style.top = (this.page_size.wy - this.loading_image.height)/2 + this.page_size.oy + 'px';
			$('lighterbox-loading').style.left = (this.page_size.wx - this.loading_image.width)/2 + this.page_size.ox + 'px';
		}
		if ($('lighterbox-content')) {
		    if (this.view_width) {
    			$('lighterbox-content').style.width = this.view_width + 'px';
			}
    		$('lighterbox-content').style.height = (height ? height + 'px' : 'auto');
		    $('lighterbox-content').style.top = (this.page_size.wy - $('lighterbox-content').offsetHeight)/2 + this.page_size.oy + 'px';
		   	$('lighterbox-content').style.left = (this.page_size.wx - $('lighterbox-content').offsetWidth)/2 + this.page_size.ox + 'px';
		}
	},
	
	resizeOverlay: function(overlay) {
	    this.getPageSize();
	    overlay.style.height = this.page_size.wy+'px';
		overlay.style.width = this.page_size.wx+'px';
		overlay.style.top = this.page_size.oy+'px';
		overlay.style.left = this.page_size.ox+'px';
	},

	getPageSize: function() {	

		var px, py, wx, wy, ox, oy; // px/py - full page, wx/wy - visible window area (excl scrollbars), ox/oy - offset to visible area caused by scrolling
		var docbod = document.body, docel = document.documentElement;
		
		if (Browser.isOpera) {
		    wx = docbod.clientWidth;
		    wy = docbod.clientHeight;
		} else {
		    wx = docel.clientWidth;
		    wy = docel.clientHeight;
		}

        oy = docel.scrollTop;
		ox = docel.scrollLeft;
		
		this.page_size = {'px':px, 'py':py, 'wx':wx, 'wy':wy, 'ox':ox, 'oy':oy}
	}

}
function pause(numberMillis) {
	var now = new Date();
	var exitTime = now.getTime() + numberMillis;
	while (true) {
		now = new Date();
		if (now.getTime() > exitTime)
			return;
	}
}

Event.observe(window, 'load', function() { new Lighterbox(); }, false);
