var FlexBox = Class.create();

FlexBox.prototype = {
	initialize: function(element, options) {
		
		this.isIE6 = typeof document.body.style.maxHeight === 'undefined';
		
		if (typeof element == 'string') {
			this.element = ( (element.indexOf('.') < 0) && (element.indexOf('#') < 0) ) ? $(element) : $$(element);
		}
		else {
			if (typeof element == 'object') {
				this.element = element;
			}
			else {
				options = element;
			}
		}
		
		this.options = {
			/* you can set these in the instantiation or the CSS */
			fade: true, // whether the overlay fades or not //
			overlayColor: '#666',
			opacity: .6,
			speed: .2,
			width: 850, // the width of the popup //
			height: 200, // the height of the popup //
			popupContentClass: 'popup-content'
		}
		
		Object.extend(this.options, options || {});
	
		this._init();
	
		if (this.element.length) {
			this.element.each(function(element) {
				this.setupShowTarget(element);
			}.bind(this));
		}
		else {
			this.setupShowTarget(this.element);
		}
		
	},
	
	_init : function() {
		
		// build the overlay and popup frame if they are not on the page yet //
		if ( !$('overlay') ) {
			new Insertion.Bottom(document.body, '<div id="overlay"></div>');
			new Insertion.Bottom(document.body, '<div id="popup-frame"></div>');
			new Insertion.Bottom($('popup-frame'), '<div id="popup-content"></div>');
		
		}
		
		// IE6 needs to be tweaked to hide select boxes and such //
		if ( this.options.hideSelects ) {
			if (this.isIE6) {
				new Insertion.Bottom(document.body, "<iframe id='hide-selects'></iframe>");
				$('hide-select').style.display = 'none';
			}
		}
		
		this.overlay = $('overlay');
		this.popupFrame = $('popup-frame');
		this.popupContent = $('popup-content');
	
		$('overlay').style.display = 'none';	
		$('popup-frame').style.display = 'none';	
		$('popup-content').style.display = 'none';	
		
		// cache the events so we can unbind //
		this.watchKeyEvent = this.watchKeyPress.bindAsEventListener(this)
		this.deactivateEvent = this.deactivate.bindAsEventListener(this)
		this.activateEvent = this.activate.bindAsEventListener(this)
	
		this._init = true;
	},
	
	setupShowTarget: function(element) {
		
		var link = element.href;
			
		if ( (link.indexOf('#') < 0) ) {
			this.remote = true;
		}
		else {
			link = link.split('#')[1];
			$(link).style.display = 'none';
		}
		
		// used to generate inside clickable links for ajax pages //
		this.popupClass = this.options.popupClass || $(element).classNames();

		Event.observe(element, 'click', this.activateEvent);
		
	},
	
	watchKeyPress : function(e) {
	
		if (e.keyCode == Event.KEY_ESC) {
			this.deactivate();
		}
		
	},
	
	activate: function(e) {
	
	
		// makes sure that the anchor text isn't in a span or em or something //
		if (Event.element(e)) {
			// makes sure that the anchor text isn't in a span or em or something //
			var group = Event.element(e).getAttribute('rel') ? Event.element(e).getAttribute('rel') : Event.element(e).parentNode.getAttribute('rel');
		
			var link = Event.element(e).readAttribute('href') ? Event.element(e).readAttribute('href') : Event.element(e).parentNode.readAttribute('href');
		}
		
		//programatic//
		else { 
		 	var link = e;
		}
		
		
		if (typeof this.options.beforeActivate == 'function') {
			this.options.beforeDisplay.apply(this, arguments);
		}
		
		if (!this.observing) {		
			// add the event listeners to turn off the windows //
			if (!this.options.modal) {
				Event.observe(document, 'keypress', this.watchKeyEvent);
				Event.observe('overlay', 'click', this.deactivateEvent);
			}
			this.toggleOverlay();
			this.observing = true;
		}
		
		// ugh.  IE6 problems are fixed here //
		if (this.isIE6) {
			this.overlay.setStyle({ 'position':'absolute' });
			this.popupFrame.setStyle({ 'position': 'absolute' });
			$(document.body).setStyle({ 'height': '100%' } );
			$(document.getElementsByTagName('html')[0]).setStyle({ 'height':'100%' });
		}
		
		var pageToOpen = (link.indexOf('#') < 0) ? link : link.split('#')[1];
		
		// if the link isn't to a bookmark, we're in ajax mode //
		if( this.remote ) {
			this.getData( pageToOpen );
		}
		else {
			this.display( $(pageToOpen).innerHTML );
		}	
		
		if(e) Event.stop(e);
	
	},
	
	toggleOverlay: function() {
	
		var bg = this.options.overlayColor || $('overlay').getStyle('background');
		$('overlay').setStyle({'background': bg });
	
		if (this.options.fade && bg != 'none') {
			$('overlay').style.display == 'block' ? 
			new Effect.Fade('overlay', { duration: this.options.speed, from: this.options.opacity, to: 0 }) : 
			new Effect.Appear('overlay', { duration: this.options.speed, from: 0.0, to: this.options.opacity });
		}
		
		else {
			if(bg != 'none') $('overlay').setStyle({'opacity' : this.options.opacity } );
			$('overlay').style.display == 'block' ? $('overlay').style.display = 'none' : $('overlay').style.display = 'block';
		}
		
	}, 
	
	display: function(content){
	
		// set up the dom if not ready //
		if(!this._init) {
			this._init()
		}
	
		this.popupContent.update(content);
		this.popupContent.addClassName(this.options.popupContentClass);
		
		var popupWidth = ( this.options.width + 'px' ) || this.popupContent.getStyle('width');
		this.popupContent.style.width = popupWidth;
		
		if (this.options.height) {
			var popupHeight = (this.options.height == 'auto') ? this.options.height : this.options.height + 'px';
			this.popupFrame.style.display = 'block';
			popupHeight = this.popupContent.getHeight();
		
		}
		else {
			var popupHeight = this.popupContent.getStyle('height');
			this.popupFrame.style.display = 'block';
		}

		// get all close targets //
		var pageCloseTargets = this.popupContent.getElementsByClassName(this.options.popupCloseClass);
		
		for(var x=0; x<pageCloseTargets.length; x++)
			Event.observe(pageCloseTargets[x], 'click', this.deactivateEvent);	
		
		// frame setup //
		
		var scrollPosition = self.pageYOffset ? self.pageYOffset : document.documentElement.scrollTop || document.body.scrollTop;
		var pageHeight = self.innerHeight ||  document.documentElement.clientHeight || document.body.clientHeight || 0;
		
		this.popupFrame.style.position = (this.options.position == 'absolute') ? 'absolute' : 'fixed';
		this.popupFrame.style.left = '50%';
		this.popupFrame.style.marginLeft = '-' + parseInt(popupWidth) / 2 + 'px';
		
		if (this.options.align == 'top') {
			this.popupFrame.style.top =  (this.options.position == 'absolute') ? scrollPosition + 'px' : 0;
			this.popupFrame.style.marginTop = '0';
		}
		else {	
		
			var viewportCenter = parseInt( (pageHeight - parseInt(popupHeight)) / 2);
			var absCenter = scrollPosition + viewportCenter;
		
			this.popupFrame.style.top =  (this.options.position == 'absolute') ? (absCenter + 'px') : '50%';
			this.popupFrame.style.marginTop = (this.options.position == 'absolute') ? '0' : '-' + parseInt(popupHeight) / 2 + 'px';
		}
		
		// ugh.  IE6 problems are fixed here //
		if (this.isIE6) {
			this.popupFrame.style.top = scrollPosition;
			this.popupFrame.style.position = 'absolute';
			this.popupFrame.style.marginTop =  (this.options.align == 'top') ? '0' : ( ( ( pageHeight - parseInt(popupHeight) ) / 2) + 'px' );
		}
			
		if (!this.remote) {
		
			if (this.popupClass != '') {
				var insideTargets = this.popupContent.getElementsByClassName(this.popupClass);
				insideTargets.each(function(element) {
					this.setupShowTarget(element);
				}.bind(this));		
			}
		}
		
		this.popupContent.style.display = 'block';

	},
	
	deactivate: function(e) {
	
		if (!this.options.modal) {
			Event.stopObserving(document, 'keypress', this.watchKeyEvent);
			Event.stopObserving('overlay', 'click', this.deactivateEvent);
		}
		this.observing = false;
		
		this.toggleOverlay();
		
		this.popupContent.removeClassName(this.options.popupContentClass);
		
		this.hidePage();
		
		if(e) Event.stop(e);
	},
	
	hidePage: function() {
	
		// remove the event listeners on any close mechanisms in the content page itself //
		var pageCloseTargets = this.popupContent.getElementsByClassName(this.options.popupCloseClass);
		for(var x=0; x<pageCloseTargets.length; x++)
			Event.stopObserving(pageCloseTargets[x], 'click', this.deactivateEvent);	
	
		this.popupContent.style.display = 'none';
		this.popupContent.style.zIndex = '-10';
		this.popupFrame.style.display = 'none';
		
		// ugh.  IE6 problems are fixed here //
		if (typeof document.body.style.maxHeight === "undefined") { //if IE 6 from thickbox //
			$(document.body).setStyle( { 'height': 'auto' } );
			$(document.getElementsByTagName('html')[0]).setStyle( { 'height':'auto', 'overflow':'auto' } );
		}	
	
	}
	
}


FlexBox.AJAX = { 

			/*todo*/ setRemoteStructure: function(el, structure) {
				el = $(el);
				
				// if there is already something in the HTML to hold the slide, put the slide there //
				if (el) {
					return el;
				}
				else {
					// build the wrapper to hold the slide or the slide itself //
				}
			},
			
			indicateLoad : function(state) {
				
				
				if (state == 'load') {
					// show spinner //
					var loading = '<p class=\"loading\">';
					loading += this.options.spinner ? '<img src=\"' + this.options.spinner + '\ " />' : 'Loading...'
					loading += '</p>';
					
					this.display(loading);
				}
				
			},
			
			getData: function(url) {
					
				this.remoteLoading = true;	
				var cacheNum = new Date().getTime();
				
				this.indicateLoad('load');
				
				var req = new Ajax.Request(url, 
					  {
					  	method: 'get',
						parameters: { 
										ms: cacheNum 
									},
						onSuccess: this.update.bind(this),
						onComplete: function() {
													if (typeof this.options.afterRemote == 'function')
														this.options.afterRemote.apply(this);
												
												}.bind(this),
						onFailure: function() { alert('I in ur page messing up ur ajax'); }
					  });
	
			},
			
			update: function(transport) { 
			
					window.setTimeout(function() {
						
						this.display(transport.responseText); 
						
						this.indicateLoad('done');
						
						this.remoteLoading = false;
					
						var insideTargets = this.popupContent.getElementsByClassName(this.popupClass);
						insideTargets.each(function(element) {
							this.setupShowTarget(element);
						}.bind(this));
					
					}.bind(this), 
					
					this.options.delay || 0);
					
							
			}
			

};
	
// add the add-on methods to the main tab prototype //
Object.extend(FlexBox.prototype, FlexBox.AJAX)


// -----------------helper functions -----------------
// ---------------------------------------------------

function showSelectBoxes(){
	var selects = document.getElementsByTagName("select");
	for (i = 0; i != selects.length; i++) {
		selects[i].style.visibility = "visible";
	}
}

// ---------------------------------------------------

function hideSelectBoxes(){
	var selects = document.getElementsByTagName("select");
	for (i = 0; i != selects.length; i++) {
		selects[i].style.visibility = "hidden";
	}
}

// ---------------------------------------------------

function showFlash(){
	var flashObjects = document.getElementsByTagName("object");
	for (i = 0; i != flashObjects.length; i++) {
		flashObjects[i].style.visibility = "visible";
	}

	var flashEmbeds = document.getElementsByTagName("embeds");
	for (i = 0; i != flashEmbeds.length; i++) {
		flashEmbeds[i].style.visibility = "visible";
	}
}

// ---------------------------------------------------

function hideFlash(){
	var flashObjects = document.getElementsByTagName("object");
	for (i = 0; i != flashObjects.length; i++) {
		flashObjects[i].style.visibility = "hidden";
	}

	var flashEmbeds = document.getElementsByTagName("embeds");
	for (i = 0; i != flashEmbeds.length; i++) {
		flashEmbeds[i].style.visibility = "hidden";
	}

}
// overwrite prototype's show method to specifically add block -- necessary if we want to use Effect.Appear and hide the background with CSS display: none; //

var newShow = { show : function(element) {
	$(element).style.display = 'block';
	return element;
  	}
  }
// 
Element.addMethods(newShow);


