(function(){
	
	var Popup = function(options){
		//set configuration options
		this.setOptions(options);
		
		//constants
		this.HIDEPOPUP = 1;
		this.SHOWPOPUP = 1;
		
		//object to cache loaded content
		this.popupContents = {};
		this.popupFooterContents = {};
		this.popupWidths = {};
		this.popupXs = {};
		this.popupYs = {};
		
		//timers object
		this.timers = {};
		
		//initialize
		this.init();
	};
	
	Popup.prototype = {
		/**
		* The class's construction function
		* @property constructor
		* @return void
		*/
		constructor: Popup,
		
		/**
		* I initialize everything after the Constructor is called
		* @return void
		*/
		init: function(){
			//create dialog panel
			this.popupDialog = new YAHOO.widget.Panel('popupDialog', {
				visible: false,
				draggable: false,
				constraintoviewport:true,
				close: false,
				width: '300px',
				effect:{effect:YAHOO.widget.ContainerEffect.FADE, duration:0.25}
			});
			var html = '<table cellpadding="0" cellpadding="0" border="0" height="100%" width="100%"><tbody><tr><td valign="top"><div id="popupContents"></div></td></tr></tbody></table>';
			this.popupDialog.setBody(html);
			this.popupDialog.setFooter('');
			this.popupDialog.render(document.body);
			
			//align knob when the dialog is moved / rendered
			//this.popupDialog.beforeShowEvent.subscribe(function(){}, this, true);
			this.popupDialog.moveEvent.subscribe(function(){this.alignKnob(arguments[1][0])}, this, true);
			
			//get all popup elements, and ensure they have an ID
			var popupNodes = YAHOO.util.Selector.query('a.popup');
			YAHOO.util.Dom.generateId(popupNodes);
			
			//attach events to each popup element
			for (var i=0; i<popupNodes.length; i++){
				var popupNode = popupNodes[i];
				var popupEl = new YAHOO.util.Element(popupNode);
				var popupId = popupEl.get('id');
				var popupRel = popupEl.get('rel');
				var popupTitle = popupEl.get('title');
				var popupName = popupNode.innerHTML;
				
				YAHOO.util.Event.on(popupNode, 'mouseover', function(e, params){
					this.show(params);
				}, {id:popupId, rel:popupRel, title: popupTitle, name:popupName}, this);
				
				YAHOO.util.Event.on(popupNode, 'mouseout', this.hide, this, true);
				
				YAHOO.util.Event.on('popupDialog', 'mouseover', this.clearTimeouts, this, true);
				
				YAHOO.util.Event.on('popupDialog', 'mouseout', this.hide, this, true);
			}
		},
		
		/**
		* I set the Class configuration options object
		* @param options <Object> (optional) If present, it will be used to set the options for the current class.
		* @return void
		*/
		setOptions: function(options){
			this.options = {
				showDelay: 250,
				hideDelay: 400,
				defaultWidth: 300
			};
			YAHOO.lang.augmentObject(this.options, options || {}, true);
		},
		
		/**
		* I align the knob to point to the popup context
		* @param positions <Array> Where the first member is the x coordinates and the second member is the y coordinates.
		* @return void
		*/
		alignKnob: function(positions){
			var x = positions[0];
			var y = positions[1];
			var difference = Math.abs(y - this.popupYs[this.lastPopupElement]);
			if (YAHOO.env.ua.ie > 0){
				difference += 4;
			}else{
				difference += 10;
			}
			$('popupDialogKnob').style.top = difference +  'px';
		},
		
		/**
		* I clear all popup timeouts
		* @return void
		*/
		clearTimeouts: function(){
			if (this.timers[this.HIDEPOPUP] != null){
				window.clearTimeout(this.timers[this.HIDEPOPUP]);
			}
			if (this.timers[this.SHOWPOPUP] != null){
				window.clearTimeout(this.timers[this.SHOWPOPUP]);
			}
		},
		
		/**
		* I am called to hide the popup
		* @param positions <Array> Where the first member is the x coordinates and the second member is the y coordinates.
		* @return void
		*/
		hide: function(){
			this.clearTimeouts();
			this.setTimer('HIDEPOPUP');
		},
		
		/**
		* I set the timeouts for hiding and showing the popup
		* @return void
		*/
		setTimer: function(type, params){
			var self = this;
			switch (type.toUpperCase()){
				case 'HIDEPOPUP':
					var callback = function(){
						self.popupDialog.hide();
					};
					this.timers[this[type]] = window.setTimeout(callback, this.options.hideDelay);
				break;
				case 'SHOWPOPUP':
					//var callback = "YAHOO.webucator.popupShowCallback('"+params.id+"')";
					var callback = function(){
						self.showCallback(params);
					};
					this.timers[this[type]] = window.setTimeout(callback, this.options.showDelay);
				break;
			}
		},
		
		/**
		* I show a popup
		* @param params <Object> Paramaters that are passed to the showCallback method
		* @return void
		*/
		show: function(params){
			this.clearTimeouts();
			this.setTimer('SHOWPOPUP', params);
		},
		
		showCallback: function(params){
			this.lastPopupElement = params.id;
			var popupY = YAHOO.util.Dom.getY(params.id) - 10;
			this.popupYs[params.id] = popupY;
			
			if (typeof this.popupContents[params.id] != 'undefined') {
				
				//use cached information
		  	$('popupContents').innerHTML = this.popupContents[params.id];
				this.popupDialog.setFooter(this.popupFooterContents[params.id]);
				this.popupDialog.cfg.setProperty('width', this.popupWidths[params.id]);
				this.popupDialog.cfg.setProperty('Y', popupY);
				
				if (YAHOO.util.Dom.hasClass(params.id, 'popupright')){
					var popupX = YAHOO.util.Dom.getRegion(params.id).left - 10 - parseInt(this.popupWidths[params.id]);
				}else{
					var popupX = YAHOO.util.Dom.getRegion(params.id).right + 10;
				}
				this.popupDialog.cfg.setProperty('X', popupX);
				this.popupDialog.show();
				this.showHandler();
			
			}else{
				
				//set width
				var popupWidth = this.options.defaultWidth;
				if ($(params.rel+'-width')){
					popupWidth = $(params.rel+'-width').value + 'px';
				}else if (parseInt(YAHOO.util.Dom.getStyle(params.rel,'width')) > 0){
					popupWidth = YAHOO.util.Dom.getStyle(params.rel,'width');
				}
				this.popupWidths[params.id] = popupWidth;
				
				//set positioning info and add pointer
				if (YAHOO.util.Dom.hasClass(params.id, 'popupright')) {
					var html = '<img id="popupDialogKnob" src="/images/sitedesign/dialog-pointer-right.gif" class="dialog-pointer-right" />';
					var popupX = YAHOO.util.Dom.getRegion(params.id).left - 10 - parseInt(popupWidth);
				}else{
					var html = '<img id="popupDialogKnob" src="/images/sitedesign/dialog-pointer-left.gif" class="dialog-pointer-left" />';
					var popupX = YAHOO.util.Dom.getRegion(params.id).right + 10;
				}
				
				if (params.title.toString().length > 0){
	
					//use title string as popup contents
					var contents = YAHOO.lang.trim(html + '<p>' + params.title + '</p>');
					$('popupContents').innerHTML = contents;
					this.popupDialog.cfg.setProperty('width', popupWidth);
					this.popupDialog.cfg.setProperty('Y', popupY);
					this.popupDialog.cfg.setProperty('X', popupX);
					this.popupDialog.show();
					this.showHandler();
	
					//cache information
					this.popupContents[params.id] = contents;
	
				}else if (params.rel.toString().length > 0){
				
					//determine if the rel attribute is a URL
					if (params.rel.toString().indexOf('.cfm') == -1){
						
						//the rel attibute is not a url, so lets check if it points to an existing element
						if ($(params.rel)){
							var contents = html + $(params.rel).innerHTML;
							$('popupContents').innerHTML = contents;
							if ($(params.rel+'-footer')){
								var footer = $(params.rel+'-footer').innerHTML;
								this.popupDialog.footer.style.display='block';
								this.popupDialog.setFooter(footer);	
							}else{
								var footer = '';
								this.popupDialog.footer.style.display='none';
							}
							this.popupDialog.cfg.setProperty('width', popupWidth);
							this.popupDialog.cfg.setProperty('Y', popupY);
							this.popupDialog.cfg.setProperty('X', popupX);
							this.popupDialog.show();
							this.showHandler();
							
							//cache information
							this.popupContents[params.id] = contents;
							this.popupFooterContents[params.id] = footer;
						}
						
					}else{
						
						// the rel attribute is a URL, lets get the contents
						YAHOO.util.Connect.asyncRequest('GET', rel, {
			  			success: function(t){
								var contents = html + '<p>' + YAHOO.lang.trim(t.responseText) + '</p>';
								$('popupContents').innerHTML = contents;
								this.popupDialog.cfg.setProperty('width', popupWidth);
								this.popupDialog.cfg.setProperty('Y', popupY);
								this.popupDialog.cfg.setProperty('X', popupX);
								this.popupDialog.show();
								this.showHandler();
								
								//cache information
								this.popupContents[params.id] = contents;
							},
							failure: function(){
								this.notificationHide();
								window.alert('There was an error obtaining the data');
							},
							scope: this
						});
						
					}
				}
			}
		},
		
		showHandler: function(){
			//called after a popup is shown
			//this.cityFooterInit();
		}
		
	};
	
	YAHOO.com.webucator.Popup = Popup;
})();
