/**
 * @author rtimoshenko
 */

var Dialog = new Class({
	
	/*
	* ===========================================
	*     Public Class Fields / Properties
	* ===========================================
	*/
	
	selects								: null,
	overlay								: null,
	dialogElement						: null,
	
	
	/* --- Exceptions --- */
	
	EXCEPTION_FAILED_ACCESS	 			: 'EWDE001',
	
	
	
	/**
	 * Class Constructor Function
	 */
	initialize							: function(dialogLinks)
	{
		this.enhanceDialogLinks(dialogLinks);
		this.selects = $$('select');
	},
	
	/**
	 * Shows dialog
	 * @param {Object} html				HTML Object to inject into dialog element.
	 */
	show								: function(html, width, height, topmargin, func)
	{
		var thisClass = this;
		
		this.hideSelects();
		
		if (!this.overlay)
		{
			this.overlay = this.generateOverlay();
			$('root').adopt(this.overlay);
		}
		
		this.overlay.set('morph',
		{
			'duration'		: 500,
			onComplete		: function()
			{
				var innerDialog, innerContent;
				var windowHeightHalf = window.getSize().y * 0.5;
				
				thisClass.dialogElement = thisClass.generateDialog(html, width, height, topmargin);
				$('root').adopt(thisClass.dialogElement);
				
				
				innerDialog = thisClass.dialogElement.getElement('#dialog');
				
				innerContent = innerDialog.getElement('#dialog_content');
				
				// Quit
				if (!innerContent && $type(innerContent) != "element")
				{
					thisClass.hide();
					return;
				}

				innerDialog.setStyle('margin-top', windowHeightHalf - (innerDialog.getSize().y * 0.5));
				innerDialog.setStyle('margin-left', -(innerDialog.getSize().x * 0.5));
				
				topmargin = thisClass.getTopMargin(height);
				leftmargin = -(width * 0.5);
				
				// Verify that topmargin does not go into negative
				if (topmargin < 10) topmargin = 10;
				
				innerDialog.set('morph', 
				{
					'duration' 		: 450,
					'link'			: 'chain',
					'transition'	: Fx.Transitions.Expo.easeOut,
					onChainComplete	: function()
					{						
						innerContent.set('morph', 
						{
							'duration'	: 100
						});
						innerContent.morph({'opacity' : '1'});
						
						if (func)
						{
							try 
							{
								eval(func)();
							}
							catch(e)
							{
								thisClass.hide();
								throw 'Error calling custom function';
							}
						} 
					}
				});
				innerDialog.morph({
					'width' : width + 'px',
					'margin-left' : leftmargin + 'px',
					'height' : height + 'px',
					'margin-top' : topmargin + 'px'
				});
				
				var closelinks = innerDialog.getElements('.close_link');
				closelinks.each(function(closelink, i)
				{
					closelink.addEvent('click', function(e)
					{
						e.stop();
						this.hide();
					}.bind(thisClass));
				}.bind(thisClass));
			}
		});
		
		this.overlay.morph({'opacity' : '0.9'});
	},
	
	/**
	 * 
	 * @param {Object} e
	 */
	hide								: function(e)
	{
		// Cancel event, if applicable
		if (e) e.stop();
		
		var innerDialog;
		var overlay = this.overlay;
		var thisClass = this;
		
		if (this.dialogElement) innerDialog = this.dialogElement.getElement('#dialog');
		
		if (overlay)
		{
			var delay = 100;
			
			overlay.set('morph', {
				'duration': delay,
				'transition': Fx.Transitions.Quad.easeIn,
				onComplete: function(overlay)
				{
					overlay.destroy();
					thisClass.overlay = null;
				}
			});
			
			// destructor fallback
			var destroyOverlay = function(overlay)
			{
				overlay.destroy();
				this.overlay = null;
			};
			
			destroyOverlay.delay(delay, this, overlay);
		}
		
		if (innerDialog) 
		{
		
			innerDialog.set('morph', {
				'duration': 100,
				'transition': Fx.Transitions.Quad.easeIn,
				onComplete: function(innerDialog)
				{
					innerDialog.destroy();
					thisClass.dialogElement.destroy();
					overlay.morph({
						'opacity': '0.1'
					});
					thisClass.showSelects();
				}
			});
			innerDialog.morph({
				'opacity': '0.1'
			});
		}
	},
	
	getTopMargin						: function(height)
	{
		return window.getScroll().y + ((window.getSize().y * 0.5) - (height * 0.5)) - 30; // offset value a bit
	},
	
	/**
	 * 
	 * @param {Object} width
	 * @param {Object} height
	 */
	generateDialog						: function(html,
												   width,
												   height,
												   topmargin)
	{
		var thisClass = this;
		
		var dialogHeader = new Element('div',
		{
			'class'		: 'dialogHeader'
		});
		
		var dialogFooter = new Element('div',
		{
			'class'		: 'dialogFooter'
		});
		
		var tl = new Element('span',{'class':'tl'});
		var tr = new Element('span',{'class':'tr'});
		var bl = new Element('span',{'class':'bl'});
		var br = new Element('span',{'class':'br'});
		
		var dialogWrapper = new Element('div',
		{
			'id'		: 'dialogWrapper'
		});
		
		var close = new Element('a',
		{
			'id'		: 'close_link',
			'href'		: '#',
			'events'	: {
				'click'	: function(e)
				{
					e.stop();
					thisClass.hide();
				}
			}
		});
		
		var dialogElement = new Element('div', 
		{
			'id'		: 'dialog',
			'styles'	: {
				'width'		: '100px',
				'height'	: '100px',
				'overflow'	: 'hidden'
			}
		});
		
		if (topmargin) dialogElement.setStyle('margin-top', topmargin + 'px');
		
		var dialogContent = new Element('div',
		{
			'id'		: 'dialog_content',
			'opacity'	: '0'
		});
		
		dialogWrapper.adopt(dialogElement);
		dialogElement.adopt(dialogContent);
		dialogContent.adopt(html);
		
		if (!dialogContent.get('html') && $type(dialogContent) != "element")
			dialogContent.adopt(html); // Try again
		
		if (!dialogContent.get('html') && $type(dialogContent) != "element")
		{
			this.hide(); // Fail
			return;
		}
		
		close.inject(dialogElement, 'top');
		dialogHeader.inject(dialogElement, 'top');
		dialogFooter.inject(dialogElement, 'bottom');
		
		dialogHeader.adopt(tl);
		dialogHeader.adopt(tr);
		
		dialogFooter.adopt(bl);
		dialogFooter.adopt(br);
		
		return dialogWrapper;
	},
	
	/**
	 * 
	 */
	generateOverlay						: function()
	{
		var overlay = new Element('div',
		{
			'id'		: 'overlay',
			'styles'	: {
				'height'	: window.getScrollSize().y,
				'opacity'	: '0.1'
			}
		});
		
		overlay.set('morph', { onComplete : null });
		
		overlay.addEvent('click', function(e)
		{
			this.hide(e);
		}.bind(this));
		
		return overlay;
	},
	
	/**
	 * 
	 */
	hideSelects							: function()
	{
		if (Browser.Engine.name !== 'trident') return;
		 
		var selects = $$('select');
		 
		selects.each(function(select)
		{
			select.setStyle('opacity', '0');
		});
	},
	
	/**
	 * 
	 */
	showSelects							: function()
	{
		if (Browser.Engine.name !== 'trident') return;
		 
		var selects = $$('select');
		 
		selects.each(function(select)
		{
			select.setStyle('opacity', '1');
		});
	},
	
	/**
	 * 
	 */
	enhanceDialogLinks					: function(dialogLinks)
	{
		if (!dialogLinks || !dialogLinks.length) return;
		
		dialogLinks.each(function(dialogLink, i)
		{
			dialogLink.addEvent('click', function(e)
			{
				this.eventDialogLinkClick(e);
			}.bind(this));
		}.bind(this));
	},
	
	/**
	 * 
	 * @param {Object} e
	 */
	eventDialogLinkClick				: function(e)
	{
		// Cancel event, if applicable
		if (e) e.stop();
		
		var width = 354;
		var height = 142;
		var topmargin;
		var func;
		
		var target = $(e.target);
		var targetParent = target.getParent();
		
		// No href?  Assume image link
		if (targetParent.href) target = targetParent;
		
		try {
			var dimensions = target.rel;
			var uri = target.href;
			
			
			if (dimensions)
			{
				var a = dimensions.split('|');
				if (a.length)
				{
					width = a[0];
					height = a[1];
					
					if (a[2]) topmargin = a[2];
					if (a[3]) func = a[3];
				}
			}
			
			this.pageRequestGeneric(uri, width, height, topmargin, func);
		}
		catch(error) {}
	},
	
	/**
	 * Generic page request.
	 * @param {String} requestURI		The URI to request.
	 */
	pageRequestGeneric					: function(requestURI, width, height, topmargin, func)
	{
		var thisClass	= this;
		var request;
		
		if (requestURI.contains('.jpg') || requestURI.contains('.gif') || requestURI.contains('.png'))
		{
			var padding = 20;
			request = new Asset.image(requestURI,
			{
				onload		:function(img)
				{
					thisClass.show(img, img.width + (padding * 2), img.height + (padding * 2), topmargin, func);
				}
			});
		}
		else
		{
			// Create Generic HTML Request
			request = new Request.HTML({
				link		: 'ignore',
				url			: requestURI,
				onSuccess		: function(html)
				{
					// Show address form
					thisClass.show(html, width, height, topmargin, func);
				},
				onFailure	: function()
				{
					thisClass.throwException(thisClass.EXCEPTION_FAILED_ACCESS);
				}
				
			}).send();
		}
	
	},
	
	/**
	 * Throw new Address Exception
	 * @param {String} type 			"Constant" representing the exception type.
	 */
	throwException						: function(type)
	{
		var errorMessage;
		
		switch (type)
		{			
			case this.EXCEPTION_FAILED_ACCESS :
				errorMessage = "Dialog page could not be accessed.";
				break;
				
			default : errorMessage = "An error has occured.";
		}
		
		throw new Error(errorMessage);
	}
});
