/**
 * ------------------------------------------------------------------------------------------
 *  DarkBox r1
 * ------------------------------------------------------------------------------------------
 * 
 * Inspired by
 * 		http://www.huddletogether.com/projects/lightbox/
 * 		http://particletree.com/features/lightbox-gone-wild/
 * 		
 * 		
 * 	HOW DOES IT WORK?
 * 	Rather than the previous examples, which all use the same set of elements, this 
 * 	one actually creates it's own individually named tags on the fly. I wanted the whole
 * 	process to be encapsulated into one single class, no mess, no fuss.
 * 	
 * 	It works roughly the same way as the other implementations... it first creates an overlay
 * 	DIV, which covers the screen, etc etc.
 * 	
 * 	It then creates a series of three divs - modal_frame, modal_loading and modal_pane, like so:
 * 	
 * 	-----------------------------------------
 * 	| modal_frame                           |
 * 	|   ---------------------------------   |
 * 	|   |  modal_loading                |   |
 * 	|   |                               |   |
 * 	|   |          (spinner)            |   |
 * 	|   ---------------------------------   |
 * 	|                                       |
 * 	|   ---------------------------------   |
 * 	|   |  modal_pane                   |   |
 * 	|   |                               |   |
 * 	|   |        (ajax target)          |   |
 * 	|   ---------------------------------   |
 * 	|                                       |
 * 	-----------------------------------------
 * 	
 * 	The modal_loading and modal_pane divs are not individually named; instead referencing those elements is
 * 	handled by the class, which does a getElementsByClassName()[0] on them.
 * 	
 * 	More later.
 * 	
 **/


// I need a better browser detection routine.
// todo -- change this to bloody feature detection.

var detect = navigator.userAgent.toLowerCase();
var OS, browser, version, total, thestring;

var DarkBox = Class.create();

var d_box_height = 0;

elementPrefix = 'dbox_';						// to avoid id issues, prefix all our elements

DarkBox.prototype = {

	// we need to define these as member variables because we set the width / height manaually.
	// plus, the position is calculated.
	// also, effects.
	
																																			
	id_overlay : elementPrefix + 'overlay',															// this saves us having messy shit later on.
	id_frame : elementPrefix + 'frame',
	id_content : elementPrefix + 'content',
	id_loader : elementPrefix + 'loader',
	
	yPos : 0,
	xPos : 0,
	width: 0,
	height: 0,
	
	pane : null,
	overlay : null,
	contentFrame : null,

	// placeholder reference to the actual content pane
	
	// constructor... 
	initialize: function() 
	{
		if ( !document.getElementsByTagName ) return;
		
		// add event handlers to all 'rel=darkbox' anchors.		
		$A(document.getElementsByTagName('a')).each( function(_anchor) {

			relValue = String(_anchor.getAttribute('rel')).toLowerCase();

			if ( _anchor.getAttribute('href') && (relValue.match('darkbox')) )
			{
				_anchor.onclick = function () 
				{ 
					dbox.showFrame(this); 
					return false; 
				}
			}
			
		}); // end a.tags.each

	

	},
	

	addMarkup : function() {
		// add markup
		var bodyElement = document.getElementsByTagName('body').item(0);

			// create our elements...
			var overlayElement = document.createElement('div'); 
			var frameElement = document.createElement('div'); 
			var contentElement = document.createElement('div'); 
			var loaderElement = document.createElement('div');
			
			
			overlayElement.setAttribute('id', this.id_overlay);
			overlayElement.style.display = 'none';			
			overlayElement.onclick = function () { dbox.hideFrame() };

			loaderElement.setAttribute('id', this.id_loader);
			loaderElement.innerHTML = "<p>Loading.</p>";

			contentElement.setAttribute('id', this.id_content);

			frameElement.setAttribute('id', this.id_frame);
			frameElement.style.display = 'none';

			frameElement.appendChild(loaderElement);			
			frameElement.appendChild(contentElement);			


			bodyElement.appendChild(overlayElement);
			bodyElement.appendChild(frameElement);

			this.pane = frameElement;
			this.overlay = overlayElement;
	},
	
	
	
	/**
	 * Handles the display of the frame.
	 * 
	 * Flow:
	 * - Displays the overlay (using effect.appear)
	 * - Displays the frame (using effect.appear), displays the 'loading' div
	 * - Uses Ajax.Updater to load the content into the content div (which is hidden by the 'overflow: hidden' CSS property)
	 * 	 : onComplete 
	 * 		-- calculates the final size of the content div
	 * 		-- calculates expected size of the frame
	 * 		-- hides the loader, shows the content
	 * 		-- adjusts the size
	 */
	
	showFrame : function (source_element) {

		this.addMarkup();

		dbox.overlay.style.height = getViewportDimensions().pageHeight + 'px';
		dbox.overlay.style.display = 'block';



		// show the overlay			
		// Effect.Appear(this.id_overlay, {
		// 	beforeStart : function () {  },			
		// 	duration : 0.2,
		// 	from : 0.0,	
		// 	to: 1.0
		// });
		
				
		// show the frame
		Effect.Appear(this.id_frame, {
			beforeStart : function () {
				// re-size to the appropriate size...
				dbox.sizeToLoader();
				
				$(dbox.id_content).setStyle({ opacity: 0 });				
				$(dbox.id_content).innerHTML = '';				
			},
			
			
			duration : 0.2,
			from : 0.0,	
			to: 0.8,

			afterFinish : function () {
				// load in our ajax shitznit
				$(dbox.id_frame).setStyle({ opacity: 1 });
				
				new Ajax.Updater(dbox.id_content, source_element.href, 
					{ evalScripts: true,
					  method : 'get', 
					  onComplete : function () { dbox.hideLoader(); dbox.sizeToContent(); } 
				});
				
			}
		});
			
	},
	
	
	hideLoader : function () {
		$(this.id_loader).style.display = 'none';
	},
	
	
	sizeToLoader : function () {
		loader = $(this.id_loader);

		this.pane.style.width = '180px';
		this.pane.style.height = '30px';
		
		this.pane.style.left = ( getViewportDimensions().windowWidth - 180 ) / 2 + 'px';
		this.pane.style.top = getPageScroll() + ( getViewportDimensions().windowHeight - 30 ) / 3 + 'px';		
	},


	sizeToContent : function () {
			
		content = $(this.id_content);
		
		this.contentFrame = content;
		
		firstDiv = content.getElementsByTagName('div')[0];
		metaOffsetHeight = $('dbox_meta').offsetHeight;
		d_box_height = metaOffsetHeight;

		_targetWidth = parseInt(firstDiv.style.width) + 20;
    _targetHeight = parseInt(firstDiv.style.height) + 18 + metaOffsetHeight + 5;
    
		_targetLeft = ( getViewportDimensions().windowWidth - _targetWidth ) / 2;
		_targetTop = getPageScroll() + ( getViewportDimensions().windowHeight - _targetHeight + metaOffsetHeight) / 3;

		deltaLeft = _targetLeft - parseInt(this.pane.style.left);
		deltaTop = _targetTop - parseInt(this.pane.style.top);

		deltaWidth = _targetWidth - ( this.pane.offsetWidth );
		deltaHeight = _targetHeight - ( this.pane.offsetHeight ) - metaOffsetHeight;

		// woooooooo, complex effect
		new Effect.Parallel([
			new Effect.MoveBy(this.pane, deltaTop, deltaLeft, { sync: true, transition: Effect.Transitions.sinoidal }),
      new Effect.ResizeBy(this.pane, deltaWidth, deltaHeight, { sync: true, transition: Effect.Transitions.sinoidal }),    
			new Effect.Opacity(this.pane, { from: 0.8, to: 1.0, sync : true, transition: Effect.Transitions.sinoidal})
		], { duration: 0.5, afterFinish : function() {
			
			$(dbox.id_frame).style.opacity = 1;
			
			new Effect.Opacity(dbox.contentFrame, { 
				beforeStart : function () { dbox.contentFrame.style.visibility = 'visible' },
				from: 0.0, to: 1.0, 
				duration : 0.6, 
				afterFinish : function () { 

					metaOffsetHeight = $('dbox_meta').offsetHeight;
          new Effect.ResizeBy($(dbox.id_frame), 0, metaOffsetHeight, { duration: 0.5, transition: Effect.Transitions.sinoidal });
          

				} 
			});
			
			
		} });
		
		

	},

	
	hideFrame : function () {

		dbox.overlay.style.opacity = 0;
		

		Effect.Fade(this.id_frame, {
			duration : 0.2,
			from : 0.6,
			to: 0.0,
			
			afterFinish : function () {
				// add markup
				var bodyElement = document.getElementsByTagName('body').item(0);

				var overlayElement = document.getElementById(dbox.id_overlay);
				var paneElement = document.getElementById(dbox.id_frame);
				
				paneElement.innerHTML = '';
				
				bodyElement.removeChild(overlayElement);
				bodyElement.removeChild(paneElement);
				
				dbox.pane = null;
				dbox.overlay = null;

				document.getElementsByTagName('body')[0].style.width = '1px';
				document.getElementsByTagName('body')[0].style.width = 'auto';

			}
		
		});

	},
	

		
	
	// Ie requires height to 100% and overflow hidden or else you can scroll down past the lightbox
	_prepareIE: function(height, overflow){
		bod = document.getElementsByTagName('body')[0];
		bod.style.height = height;
		bod.style.overflow = overflow;
  
		htm = document.getElementsByTagName('html')[0];
		htm.style.height = height;
		htm.style.overflow = overflow; 
	},
	
	// In IE, select elements hover on top of the lightbox
	_hideSelects: function(visibility) {
		selects = document.getElementsByTagName('select');
		for(i = 0; i < selects.length; i++) {
			selects[i].style.visibility = visibility;
		}
	},
	
	// Taken from lightbox implementation found at http://www.huddletogether.com/projects/lightbox/
	_getScroll: function(){
		if (self.pageYOffset) {
			this.yPos = self.pageYOffset;
		} else if (document.documentElement && document.documentElement.scrollTop){
			this.yPos = document.documentElement.scrollTop; 
		} else if (document.body) {
			this.yPos = document.body.scrollTop;
		}
	},
	
	_setScroll: function(x, y){
		window.scrollTo(x, y); 
	}
	
	
}
