/**
 * @name: reBox!
 * @version: .9 beta
 * @description: A mooTools Lightbox Alternative
 * @author: Tim Wickstrom - AT Web Results
 * @website: http://atwebresults.com/mootools_lightbox_rebox/
 * @copyright: 2009 to present AT Web Results, Inc.
 * @License: http://www.gnu.org/licenses/lgpl.txt
 *
 * This library is free software; you can redistribute
 * it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the
 * Free Software Foundation; either  Version 3, 29 June 
 * 2007 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser
 * General Public License along with this library;
 * Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
**/

var reBox = new Class({
	Implements: [Options, Events],
	options: {
		// Element Attributes
		link_class: 'rebox',
		form_class: 'rebox',
		useTitle: true,
		reBoxZindex: false,
		useReBoxOverlay: true,
		allowedImgTags: ["jpg","jpeg","gif","png"],
		resizeTransition: 'sine:in:out',
		defaultReBoxWidth: 300,
		defaultReBoxHeight: 110,
		
		// Transitions and Timing Controls
		ajaxDelay: 500,
		resizeDuration: 250,
		
		// Element Sugar and Spice
		reBoxCorners: true,
		cornerRadius: '6px',
		reBoxShadow: true,
		shadowOpacity: '0.60',
		titleFontSize: '11px',
		titleFontColor: '#ffffff',
		titleTextIndent: '5px',
		titleHeight: 25,
		closeTop: '12px',
		closeRight: '12px',
		closeH: '11px',
		closeW: '11px',
		reboxWindowBorderSize: '6px',
		reboxWindowBorderColor: '#e2e2e2',
		reboxWindowFontColor: '#000000',
		reboxWindowBGColor: '#ffffff',
		reboxWindowOpacity: 1,
		reboxWindowFontFamily: 'Verdana, Geneva, Tahoma, Arial, sans-serif',
		reBoxOverlayOpacity: '.60',
		reBoxOverlayColor: '#cccccc',
		
		// Loading Block
		loadTitle: 'Loading...',
		loadMessage: '<p style="text-align:center;font-size:9px;padding-top:12px;margin:0px;">Loading...</p>',
		loadWidth: 250,
		loadHeight: 100,
		
		// Utility Functions
		windowOpen: $empty,
		windowClose: $empty,
		
		// Image Paths
		loadIcon: 'elements/spinner.gif',
		titleBGimage: 'url(elements/default_bg.png) repeat-x top left',		
		closeImage: 'url(elements/popup_close.png) no-repeat top left',
		
		// Element Class and ID names
		reBoxOverlayId: 'rebox_overlay',
		reBoxWindowId: 'rebox_window',
		reBoxTitleWrapId: 'rebox_title_wrap',
		reBoxTitleId: 'rebox_title',
		reBoxCloseId: 'rebox_close',
		reBoxContentId: 'rebox_content',
		reBoxLoadId: 'rebox_load',
		
		// Error Handling
		ajaxErrorTitle: 'Transport Error (404)',
		ajaxErrorMessage: '<p style="text-align:center;font-size:9px;padding-top:12px;margin:0px;">The requested file is either unavailable or does not exist, please try your request again later.</p>',
		ajaxErrorW: '205px',
		ajaxErrorH: '90px',
		sytaxErrorTitle: 'reBox Sytax Error',
		sytaxErrorMessage: '<p style="font-size:9px;padding-top:12px;margin:0px 12px;">The reBox element that was clicked is missing required attributes. <br /><br />Please confirm that the <strong>url/action</strong> attribute, <strong>title</strong> attribute and <strong>tag type</strong> is either a &lt;a&gt; or &lt;form&gt; element.<br /><br />For other elements plese see the documentation for the use of <strong>reBoxForce()</strong>.</p>',
		syntaxErrorW: '325px',
		syntaxErrorH: '150px',
		formErrorTitle: 'reBox Form Error',
		formErrorMessage: '<p style="text-align:center;font-size:9px;padding-top:12px;margin:0px;">The Selected form does not have the required ID attribute or the (x)HTML syntax is incorrect. Please correct these errors to prevent this error.</p>',
		formErrorW: '200px',
		formErrorH: '100px'
	},
	initialize: function(options){
		this.setOptions(options);
		var tags = null;
		var caption = null;
		var reBoxRequest = null;
		var reBoxBGClick = false;
		var reBoxOpen = false;
		var reBoxWidth = null;
		var reBoxHeight = null;
		var currentRequest = false;
		this.reBoxInit();
	},
	getTags: function(){
		return tags = $$("a."+this.options.link_class,"form."+this.options.form_class);
	},
	reBoxInit: function(){
		tags = this.getTags();
		tags.removeEvents();
		tags.each(function(element){
			var thisTag = element.get('tag');
			switch(thisTag){
				case 'a':
					element.addEvent('click', function(e){
						e.stop();
						this.openReBox(element);
					}.bind(this));
				break;
				case 'form':
					element.addEvent('submit', function(e){
						e.stop();
						this.openReBox(element);
					}.bind(this));
				break;
			}
		}.bind(this));
		if(!this.options.reBoxZindex){
			var allTags = $(document.body).getElements('*');
			var baseZindex = 1;
			allTags.each(function(element){
				var thisZindex = element.getStyle('z-index').toInt();
				if(thisZindex!='NaN'&&thisZindex>baseZindex){
					baseZindex = thisZindex;
				}
			});
			this.options.reBoxZindex = baseZindex+1;
		}
	},
	openReBox: function(element){
		tagType = element.get('tag');
		caption = element.get('title');
		switch(tagType){
			case 'a':
				url = element.get('href');
			break;
			case 'form':
				url = element.get('action');
			break;
		}
		if(!caption || !url || !tagType){
			this.reBoxForce(this.options.sytaxErrorTitle,this.options.sytaxErrorMessage, this.options.syntaxErrorW, this.options.syntaxErrorH)
		}else{
			var baseURL = url.split('?')[0];
			var queryString = url.split('?').getLast();
			var params = this.parseReBoxQuery(queryString);
			if($defined(params['width'])){
				reBoxWidth = params['width'].toInt();
			}else{
				reBoxWidth = this.options.defaultReBoxWidth;
			}
			if($defined(params['height'])){
				reBoxHeight = params['height'].toInt();
			}else{
				reBoxHeight = this.options.defaultReBoxHeight;
			}
			var fileType = this.getFileType(url);
			switch(fileType){
				case 'swf':
					this.prepReBoxHTML(caption);
					this.reBoxHandlers();
					this.reBoxBGClick = false;
					this.reBoxForce(caption, false, reBoxWidth, reBoxHeight);
					$(this.options.reBoxContentId).setStyle('overflow','hidden');
					(function(){
						var swfObj = new Swiff(url,{
							width: reBoxWidth,
							height: reBoxHeight,
							container: $(this.options.reBoxContentId),
							params:{
								wMode:'opaque',
								swLiveConnect:'false'
							}
						});
						this.options.windowOpen.attempt();
					}.bind(this)).delay(this.options.ajaxDelay+this.options.resizeDuration+600);
				break;
				case 'img':
					this.prepReBoxHTML(caption);
					this.reBoxHandlers();
					this.reBoxBGClick = false;
					var myImages = new Asset.images([url], {
						onComplete: function(){
							var mwidth = $$('body').getLast().getStyle('width').toInt()*.85;
							var mheight = window.getHeight().toInt()*.85;
							var width_orig = myImages[0].get('width').toInt();
							var height_orig = myImages[0].get('height').toInt();
							if(width_orig <= mwidth && height_orig <= mheight){
								reBoxHeight = height_orig;
								reBoxWidth = width_orig;
							}else{
								if(width_orig > mwidth){
									var ratio = (width_orig / mwidth);
									reBoxWidth = mwidth;
									reBoxHeight = (height_orig / ratio);
									if(reBoxHeight > mheight){
										ratio = (reBoxHeight / mheight);
										reBoxHeight = mheight;
										reBoxWidth = (reBoxWidth / ratio);
									}
								}
								if(height_orig > mheight){
									var ratio = (height_orig / mheight);
									reBoxHeight = mheight;
									reBoxWidth = (width_orig / ratio);
									if(reBoxWidth > mwidth){
										ratio = (reBoxWidth / mwidth);
										reBoxWidth = mwidth;
										reBoxHeight = (reBoxHeight / ratio);
									}
								}
							}
							myImages[0].setProperties({
								'width': reBoxWidth.round(),
								'height': reBoxHeight.round(),
								'alt': caption,
								'border': 0
							});
							this.reBoxForce(caption, false, reBoxWidth.round(), reBoxHeight.round());
							(function(){
								$(this.options.reBoxContentId).set('html','');
								myImages[0].setStyle('opacity','0');
								myImages[0].inject($(this.options.reBoxContentId));
								myImages[0].set('tween', {
									duration: this.options.resizeDuration,
									onComplete: function(){
										this.options.windowOpen.attempt();
									}.bind(this)
								});
								myImages[0].tween('opacity','1');
							}.bind(this)).delay(this.options.ajaxDelay+this.options.resizeDuration+500);
						}.bind(this)
					});
				break;
				default:
					switch(tagType){
						case 'a':
							this.sendRebox(caption, url, tagType, queryString);
						break;
						case 'form':
							this.sendRebox(caption, url, tagType, element);
						break;
					}
				break;
			}
		}
	},
	reBoxForceAjax: function(caption,url,reboxW,reboxH){
		var baseURL = url.split('?')[0];
		var queryString = url.split('?').getLast();
		if($defined(reboxW)){
			reBoxWidth = reboxW.toInt();
		}else{
			reBoxWidth = this.options.defaultReBoxWidth;
		}
		if($defined(reboxH)){
			reBoxHeight = reboxH.toInt();
		}else{
			reBoxHeight = this.options.defaultReBoxHeight;
		}
		this.sendRebox(caption, url, 'a', queryString);
	},
	sendRebox: function(caption, url, tagType, data){
		reBoxRequest = new Request.HTML({
			method: 'post',
			url: url,
			onRequest: function() {
				this.prepReBoxHTML(caption);
				this.reBoxHandlers();
				this.reBoxBGClick = false;
			}.bind(this),
			onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
				(function(){
					this.createReboxWindow(caption, responseHTML);
				}.bind(this)).delay(this.options.ajaxDelay);
			}.bind(this),
			onCancel: function() {
				this.removeReBox();
			}.bind(this),
			onFailure: function() {
				this.reBoxForce(this.options.ajaxErrorTitle,this.options.ajaxErrorMessage,this.options.ajaxErrorW, this.options.ajaxErrorH);
			}.bind(this)
		});
		switch(tagType){
			case 'a':
				reBoxRequest.send({
					data: data
				});
			break;
			case 'form':
				if($defined(data)){
					reBoxRequest.post(data);
				}else{
					this.reBoxForce(this.options.formErrorTitle,this.options.formErrorMessage,this.options.formErrorW, this.options.formErrorH);
				}
			break;
		}
		this.currentRequest = reBoxRequest;
	},
	reBoxForce: function(caption,content,reboxW,reboxH){
		reBoxWidth = reboxW.toInt();
		reBoxHeight = reboxH.toInt();
		if(!$defined($(this.options.reBoxWindowId))){
			this.prepReBoxHTML(caption);
			this.reBoxHandlers();
		}
		(function(){
			this.reBoxBGClick = true;
			this.createReboxWindow(caption, content);
		}.bind(this)).delay(this.options.ajaxDelay+500);
	},
	getFileType: function(url){
		var returnVal = '';
		var temp = url.split('?')['0'];
		temp = temp.split('.').getLast();
		if(this.options.allowedImgTags.contains(temp)){
			returnVal = "img";
		}else if(temp=="swf"){
			returnVal = "swf";
		}else{
			returnVal = "file"
		}
		return returnVal;
	},
	reBoxHandlers: function(){
		if(this.options.useReBoxOverlay){
			$(this.options.reBoxOverlayId).addEvent('click', function(){
				if(this.reBoxBGClick){
					this.removeReBox();
				}else{
					if($defined(this.currentRequest)){
						this.currentRequest.cancel();
					}
				}
			}.bind(this));
		}
		window.addEvents({
			'scroll': function(){
				this.positionReBox();
			}.bind(this),
			'resize': function(){
				this.positionReBox();
			}.bind(this)
		});
		document.addEvent('keydown', function(event){
			if(event.key=='esc'){
				this.removeReBox();
			}
		}.bind(this));
	},
	removeReBox: function(){
		if($defined($(this.options.reBoxOverlayId))){
			$(this.options.reBoxOverlayId).removeEvents();
		}
		if($defined($(this.options.reBoxCloseId))){
			$(this.options.reBoxCloseId).removeEvents();
		}
		if($defined($(this.options.reBoxLoadId))){
			$(this.options.reBoxLoadId).removeEvents();
			$(this.options.reBoxLoadId).destroy();
		}
		if($defined($(this.options.reBoxWindowId))){
			$(this.options.reBoxWindowId).set('tween', {
				duration: this.options.resizeDuration*.8,
				transition: this.options.resizeTransition,
				onComplete: function(){
					if($defined($(this.options.reBoxContentId))){
						$(this.options.reBoxContentId).destroy();
					}
					if($defined($(this.options.reBoxTitleWrapId))){
						$(this.options.reBoxTitleWrapId).destroy();
					}
					$(this.options.reBoxWindowId).destroy();
					this.options.windowClose.attempt();
				}.bind(this)
			});
			$(this.options.reBoxWindowId).tween('opacity', '0');
		}
		if($defined($(this.options.reBoxOverlayId))){
			$(this.options.reBoxOverlayId).set('tween', {
				duration: this.options.resizeDuration,
				transition: this.options.resizeTransition,
				onComplete: function(){
					$(this.options.reBoxOverlayId).destroy();
				}.bind(this)
			});
			$(this.options.reBoxOverlayId).tween('opacity', '0');
		}
		this.reBoxOpen = false;
		window.removeEvents('scroll','resize','keyup');
		document.removeEvent('keydown');
		this.reBoxInit();
	},
	positionReBox: function(){
		if(this.options.useReBoxOverlay){
			this.reBoxOverlaySize();
		}
		if(this.reBoxOpen){
			var pbt = this.options.resizeDuration;
			var widthTo = reBoxWidth;
			var heightTo = reBoxHeight;
		}else{
			var pbt = 10;
			var widthTo = this.options.loadWidth;
			var heightTo = this.options.loadHeight;
		}
		if($defined($(this.options.reBoxWindowId))){
			$(this.options.reBoxWindowId).set('morph', {
				duration: pbt,
				transition: this.options.resizeTransition
			});
			$(this.options.reBoxContentId).set('morph', {
				duration: pbt,
				transition: this.options.resizeTransition,
				onComplete: function(){
					if($defined($(this.options.reBoxContentId))){
						$(this.options.reBoxContentId).setStyles({
							'width': widthTo,
							'height': heightTo
						});
						this.showReBoxWindow();
					}
				}.bind(this)
			});
			var posOffSet = this.calculateOffset();
			var posOffSetX = posOffSet['X'];
			var posOffSetY = posOffSet['Y'];
			if(this.options.useTitle){
				var titleWrapH = $(this.options.reBoxTitleWrapId).getStyle('height').toInt();
				var titleOffset = titleWrapH/2;
			}else{
				var titleWrapH = 0;
				var titleOffset = 0;
			}
			$(this.options.reBoxContentId).morph({
				'width': widthTo,
				'height': heightTo
			});
			$(this.options.reBoxWindowId).morph({
				'left': (($$('body').getLast().getStyle('width').toInt() - widthTo) / 2)-posOffSetX + 'px',
				'top': ((window.getScrollTop() + (window.getHeight() - heightTo) / 2)-titleOffset)-posOffSetY + 'px',
				'width': widthTo,
				'height': heightTo+titleWrapH
			});
		}
	},
	showReBoxWindow: function(){
		if(!this.reBoxOpen){
			$(this.options.reBoxWindowId).set('tween', {
				duration: this.options.resizeDuration,
				transition: this.options.resizeTransition
			});
			$(this.options.reBoxWindowId).tween('opacity', 0, this.options.reboxWindowOpacity);
			this.reBoxOpen = true;
		}
	},
	reBoxOverlaySize: function(){
		if($($(this.options.reBoxOverlayId))){
			$(this.options.reBoxOverlayId).setStyles({
				"height": window.getScrollHeight() + 'px',
				"width": $$('body').getLast().getStyle('width')
			});
		}
	},
	parseReBoxQuery: function(query){
		if(!query){
			return {};
		}
		var params = {};
		var pairs = query.split(/[;&]/);
		for (var i = 0; i < pairs.length; i++) {
			var pair = pairs[i].split('=');
			if (!pair || pair.length != 2) 
			continue;
			params[unescape(pair[0])] = unescape(pair[1]).replace(/\+/g, ' ');
		}
		return params;
	},
	calculateOffset: function(){
		var params = {};
		params['X'] = ($(this.options.reBoxWindowId).getStyle('margin-left').toInt()+$(this.options.reBoxWindowId).getStyle('margin-right').toInt()+$(this.options.reBoxWindowId).getStyle('padding-left').toInt()+$(this.options.reBoxWindowId).getStyle('padding-right').toInt()+$(this.options.reBoxWindowId).getStyle('borderLeftWidth').toInt()+$(this.options.reBoxWindowId).getStyle('borderRightWidth').toInt())/2;
		params['Y'] = ($(this.options.reBoxWindowId).getStyle('margin-top').toInt()+$(this.options.reBoxWindowId).getStyle('margin-bottom').toInt()+$(this.options.reBoxWindowId).getStyle('padding-top').toInt()+$(this.options.reBoxWindowId).getStyle('padding-bottom').toInt()+$(this.options.reBoxWindowId).getStyle('borderTopWidth').toInt()+$(this.options.reBoxWindowId).getStyle('borderBottomWidth').toInt())/2;
		return params;
	},
	prepReBoxHTML: function(){
		if(this.options.useReBoxOverlay){
			if(!$defined($(this.options.reBoxOverlayId))){
				this.overlay = new Element('div').setProperty('id', this.options.reBoxOverlayId).inject(document.body,'bottom');
				this.overlay.setStyles({
					'position': 'absolute',
					'top': '0px',
					'left': '0px',
					'z-index': this.options.reBoxZindex,
					'opacity': '0',
					'background': this.options.reBoxOverlayColor
				});
				this.reBoxOverlaySize();
				this.overlay.set('tween', {
					duration: this.options.resizeDuration,
					transition: this.options.resizeTransition
				});
				this.overlay.tween('opacity',this.options.reBoxOverlayOpacity);
			}
		}
		if(!$defined($(this.options.reBoxWindowId))){
			this.reboxWindow = new Element('div').setProperty('id', this.options.reBoxWindowId).inject(document.body,'bottom');
			this.reboxWindow.setStyles({
				'position': 'absolute',
				'top': '-5000px',
				'left': '-5000px',
				'background': this.options.reboxWindowBorderColor,
				'padding': this.options.reboxWindowBorderSize,
				'color': this.options.reboxWindowFontColor,
				'font-family': this.options.reboxWindowFontFamily,
				'text-align': 'left',
				'opacity': '0',
				'z-index': (this.options.reBoxZindex+2),
				'overflow': 'hidden'
			});
			if(this.options.reBoxCorners){
				this.reboxWindow.setStyles({
					'-moz-border-radius': this.options.cornerRadius,
					'-webkit-border-radius': this.options.cornerRadius,
					'border-radius': this.options.cornerRadius
				});
			}
			if(this.options.reBoxShadow){
				this.reboxWindow.setStyles({
					'-moz-box-shadow': '0px 10px 40px rgba(0,0,0,'+this.options.shadowOpacity+')',
					'-webkit-box-shadow': '0px 10px 40px rgba(0,0,0,'+this.options.shadowOpacity+')',
					'box-shadow': '0px 10px 40px rgba(0,0,0,'+this.options.shadowOpacity+')'
				});
			}
		}
		if(this.options.useTitle){
			if(!$defined($(this.options.reBoxTitleWrapId))){
				this.reboxTitleWrap = new Element('div').setProperty('id', this.options.reBoxTitleWrapId).inject(this.options.reBoxWindowId,'bottom');
				this.reboxTitleWrap.setStyles({
					'background': this.options.titleBGimage,
					'line-height': this.options.titleHeight,
					'margin': '0px',
					'padding': '0px',
					'font-size': this.options.titleFontSize,
					'text-indent': this.options.titleTextIndent,
					'height': this.options.titleHeight,
					'color': this.options.titleFontColor,
					'font-weight': 'bold',
					'z-index': (this.options.reBoxZindex+3)
				});
			}
			if(!$defined($(this.options.reBoxTitleId))){
				this.reboxTitle = new Element('div').setProperty('id', this.options.reBoxTitleId).inject(this.reboxTitleWrap,'bottom');
				this.reboxTitle.setStyles({
					'float': 'left',
					'z-index': (this.options.reBoxZindex+4)
				});
			}
		}
		if(!$defined($(this.options.reBoxContentId))){
			this.reBoxContent = new Element('div').setProperty('id', this.options.reBoxContentId).inject(this.options.reBoxWindowId,'bottom');
			this.reBoxContent.setStyles({
				'background': this.options.reboxWindowBGColor,
				'clear': 'both',
				'border': 'none',
				'margin': '0px',
				'padding': '0px',
				'overflow': 'auto',
				'display': 'block',
				'width': this.options.loadWidth,
				'height': this.options.loadHeight,
				'z-index': (this.options.reBoxZindex+4)
			});
		}
		this.buildLoader();
		this.positionReBox();
	},
	buildLoader: function(){
		if($defined($(this.options.reBoxContentId))){
			if(!$defined($(this.options.reBoxLoadId))){
				if(this.options.useTitle){
					$(this.options.reBoxTitleId).set('html', this.options.loadTitle);
				}
				$(this.options.reBoxContentId).set('html',this.options.loadMessage);
				this.loader = new Element('img').setProperties({
					'id': this.options.reBoxLoadId,
					'src': this.options.loadIcon
				})
				this.loader.inject($(this.options.reBoxContentId),'bottom');
				this.loader.setStyles({
					'margin': '12px auto',
					'display': 'block',
					'clear': 'both'
				});
			}
		}
	},
	createReboxWindow: function(caption, html){
		this.positionReBox();
		if($defined($(this.options.reBoxWindowId))){
			this.reBoxClose = new Element('div').setProperty('id', this.options.reBoxCloseId);
			this.reBoxClose.setStyles({
				'position': 'absolute',
				'top': this.options.closeTop,
				'right': this.options.closeRight,
				'overflow': 'hidden',
				'display': 'block',
				'width': this.options.closeW,
				'height': this.options.closeH,
				'background': this.options.closeImage,
				'cursor': 'pointer',
				'z-index': (this.options.reBoxZindex+4)
			});
			(function(){
				if($defined($(this.options.reBoxWindowId))){
					this.options.windowOpen.attempt();
					if(html){ 
						$(this.options.reBoxContentId).set('html',html);
					}
					if(this.options.useTitle){
						$(this.options.reBoxTitleId).set('html',caption);
					}
					this.reBoxClose.inject($(this.options.reBoxWindowId),'top');
					this.reBoxClose.addEvent('click', function(){
						this.removeReBox();
					}.bind(this));
				}
				this.reBoxBGClick = true;
				this.reBoxInit();
			}.bind(this)).delay(this.options.resizeDuration);
		}
	}
});