//Setup shortcuts for YUI objects
var Dom = YAHOO.util.Dom;
var Event = YAHOO.util.Event;
var Connect = YAHOO.util.Connect;
var Lang = YAHOO.lang;

//Create base namespace for OurTown
var OurTown = YAHOO.namespace("OurTown");

//Create the base namespace for modules
YAHOO.namespace("OurTown.modules");

//Create the base namespace for utility functions
YAHOO.namespace("OurTown.util");

(function(){
	//Setup shortcuts for YUI objects
	var ua = YAHOO.env.ua;

	/**
	 * Utility Class
	 * Useful static functions used around the site by different pages.
	 */
	OurTown.util = {
		/**
		 *	Gets the base url for the current page (i.e. prefix.ourtown.com/area).
		 *	@method getBaseUrl
		 */
		getBaseUrl: function(){
			var sUrl = "http://";
			sUrl += window.location.hostname;
			if (window.location.pathname){
				sUrl += window.location.pathname.replace(/^(\/[^\/]+).*$/, "$1");
			}
			return sUrl;
		},

		/**
		 *	Gets the base url for the modules (i.e. modules.ourtown.com/area).
		 *	@method getBaseModuleUrl
		 */
		getBaseModuleUrl: function(){
			var sUrl = "http://modules.ourtown.com";
			if (window.location.pathname){
				sUrl += window.location.pathname.replace(/^(\/[^\/]+).*$/, "$1");
			}
			return sUrl;
		},

		/**
		 *	Makes an AJAX request to the URL specified and updates the element specified or element
		 *	with the ID specified's contents with the HTML returned.
		 *	@method makeRequestAndUpdate
		 */

		makeRequestAndUpdate: function(sUrl, sElOrId){
			//See if we got an element or an id
			var oEl;
			if (YAHOO.lang.isString(sElOrId)){
				oEl = Dom.get(sElOrId);
			} else {
				oEl = sElOrId;
			}

			if (oEl && YAHOO.lang.isString(sUrl)){
				//Send request with a callback function that replaces the HTML of element specified
				Connect.asyncRequest("GET", sUrl, {
					cache: false,
					success: function(oResponse){
						oEl.innerHTML = oResponse.responseText;
						//Now walk the tree for the element just updated and execute any scripts
						OurTown.util.runScripts(oEl);
					},
					failure: function(oResponse){
						//Show alert on failure
						alert("There was a server error while trying to perform that operation.  Please try again.");
					}
				});
			}
		},

		/**
		 *	Makes an AJAX request to the URL specified and refreshes the browser on success.  Includes
		 *	a custom callback object to execute custom success/failure code before the standard code
		 *	is executed.
		 *	@method makeRequestAndRefresh
		 */
		makeRequestAndRefresh: function(sUrl, oCallback){
			if (YAHOO.lang.isString(sUrl)){
				//Set callback to an empty object if not specified
				if (!oCallback){
					oCallback = {};
				}

				//Send request
				Connect.asyncRequest("GET", sUrl, {
					success: function(oResponse){
						//Make sure we were successful
						if (oResponse.responseText.indexOf("Error:") === 0){
							//Do custom failure
							if (Lang.isFunction(oCallback.failure)){
								oCallback.failure();
							}
							//Alert error
							alert(oResponse.responseText);
						} else {
							//Do custom success
							if (Lang.isFunction(oCallback.success)){
								oCallback.success();
							}
							//Refresh browser
							window.location.reload(true);
						}
					},
					failure: function(oResponse){
						//Do custom failure
						if (Lang.isFunction(oCallback.failure)){
							oCallback.failure();
						}
						//Show alert on failure
						alert("There was a server error while trying to perform that operation.  Please try again.");
					}
				});
			}
		},
		/**
		 *	Submits the form data for the given form id to the URL specified in its action attribute
		 *	and refreshes the browser on success.  Includes an optional callback object for performing
		 *	custom success/failure code in addition to the standard.
		 *	@method submitFormDataAndRefresh
		 */
		submitFormDataAndRefresh: function(sFormId, oCallback){
			//Set callback to an empty object if not specified
			if (!oCallback){
				oCallback = {};
			}

			//Get the form
			var oForm = Dom.get(sFormId);
			if (oForm && Lang.isString(oForm.action)){
				//Get the action attribute
				var sUrl = oForm.action;

				Connect.setForm(oForm);
				Connect.asyncRequest("POST", sUrl, {
					success: function(oResponse){
						//Make sure we were successful
						if (oResponse.responseText.indexOf("Error:") === 0){
							//Do custom failure
							if (Lang.isFunction(oCallback.failure)){
								oCallback.failure();
							}
							//Alert error
							alert(oResponse.responseText);
						} else {
							//Do custom success
							if (Lang.isFunction(oCallback.success)){
								oCallback.success();
							}
							//Refresh browser
							window.location.reload(true);
						}
					},
					failure: function(oResponse){
						//Do custom failure
						if (Lang.isFunction(oCallback.failure)){
							oCallback.failure();
						}
						//Show alert on failure
						alert("There was a server error while trying to perform that operation.  Please try again.");
					}
				});
			}

			//Return false to prevent any regular submission
			return false;
		},

		/**
		 *	Shows a DOM element.
		 *	@method showElement
		 */
		showElement: function(sElOrId){
			//See if we got an element or an id
			var oEl;
			if (YAHOO.lang.isString(sElOrId)){
				oEl = Dom.get(sElOrId);
			} else {
				oEl = sElOrId;
			}

			if (oEl){
				Dom.removeClass(oEl, "ourtown-hide");
			}
		},

		/**
		 *	Hides a DOM element.
		 *	@method hideElement
		 */
		hideElement: function(sElOrId){
			//See if we got an element or an id
			var oEl;
			if (YAHOO.lang.isString(sElOrId)){
				oEl = Dom.get(sElOrId);
			} else {
				oEl = sElOrId;
			}

			if (oEl){
				Dom.addClass(oEl, "ourtown-hide");
			}
		},

		/**
		 *	Toggles whether an element is visble or not and returns a boolean indicating
		 *	whether it is visible.
		 *	@method toggleElementVisible
		 */
		toggleElementVisible: function(sElOrId){
			//See if we got an element or an id
			var oEl;
			if (YAHOO.lang.isString(sElOrId)){
				oEl = Dom.get(sElOrId);
			} else {
				oEl = sElOrId;
			}

			if (oEl){
				if (Dom.hasClass(oEl, "ourtown-hide")){
					this.showElement(oEl);
					return true;
				} else {
					this.hideElement(oEl);
					return false;
				}
			}
		},

		/**
		 *	Toggles a +/- icon panel.  Pass the panel's contents element id as the first parameter
		 *	and the icon (image) element's id as the second parameter.
		 *	@method togglePanel
		 */
		togglePanel: function(sContentsEl, sIconEl){
			//Toggle the panel's contents visibility
			var isVisible = OurTown.util.toggleElementVisible(sContentsEl);
			if (isVisible){
				Dom.get(sIconEl).src = "/images/minus.gif";
			} else {
				Dom.get(sIconEl).src = "/images/plus.gif";
			}
			return isVisible;
		},

		/**
		 *	Runs any script tags found in the given element (recursively walks elements DOM tree).
		 *	@method runScripts
		 */

		runScripts: function(oElement){
			//if it's not an element node, return
			if (oElement.nodeType != 1) return;
 
			if (oElement.tagName.toLowerCase() == "script") {
				//Run the script
				eval(oElement.text);
			} else {
				var n = oElement.firstChild;
				while (n) {
					//if it's an element node, recurse
					if (n.nodeType == 1){
						OurTown.util.runScripts(n);
					}
					n = n.nextSibling;
				}
			}

		}
	};


	/**
	 * Menu Class
	 * Used for flyout menus on OurTown area pages.
	 */
	
	//Create the namespace for our menu
	YAHOO.namespace("OurTown.Menu");
	var oAnim;
	OurTown.Menu = function(sElementId){
		//Make sure the element passed in exists
		var oEl = document.getElementById(sElementId);
		if (oEl){
			//Set properties and initialize
			this.menuContainerEl = oEl;
			this.init();
		}
	};
	
	OurTown.Menu.prototype = {
		menuBar: null,

		menuContainerEl: null,

		init: function(){
			//Create the menu widget using the container specified when initialized
			this.menuBar = new YAHOO.widget.MenuBar(this.menuContainerEl, {
				lazyload: true,
				autosubmenudisplay: true,
				hidedelay:250
			});

			//Render it to the page
			this.menuBar.render();

			//Listen for events
			this.menuBar.subscribe("beforeShow", this.handleSubmenuBeforeShow);
			this.menuBar.subscribe("show", this.handleSubmenuShow, this);

			//Show it
			this.menuBar.show();
		},

		/*
			 "beforeshow" event handler for each submenu of the MenuBar
			 instance, used to setup certain style properties before
			 the menu is animated.
		*/
		handleSubmenuBeforeShow : function(p_sType, p_sArgs){
			var oBody,
				oElement,
				oShadow,
				oUL;


			if (this.parent) {
				oElement = this.element;
				
				/*
					 Get a reference to the Menu's shadow element and 
					 set its "height" property to "0px" to syncronize 
					 it with the height of the Menu instance.
				*/
				oShadow = oElement.lastChild;
				oShadow.style.height = "0px";
				
				/*
					Stop the Animation instance if it is currently 
					animating a Menu.
				*/ 
				if (oAnim && oAnim.isAnimated()) {
					oAnim.stop();
					oAnim = null;
				}

				/*
					Set the body element's "overflow" property to 
					"hidden" to clip the display of its negatively 
					positioned <ul> element.
				*/ 
				oBody = this.body;

				//  Check if the menu is a submenu of a submenu.
				if (this.parent && !(this.parent instanceof YAHOO.widget.MenuBarItem)) {
					/*
						There is a bug in gecko-based browsers where 
						an element whose "position" property is set to 
						"absolute" and "overflow" property is set to 
						"hidden" will not render at the correct width when
						its offsetParent's "position" property is also 
						set to "absolute."  It is possible to work around 
						this bug by specifying a value for the width 
						property in addition to overflow.
					*/

					if (ua.gecko) {
						oBody.style.width = oBody.clientWidth + "px";
					}
					
					/*
						Set a width on the submenu to prevent its 
						width from growing when the animation 
						is complete.
					*/
					if (ua.ie == 7) {
						oElement.style.width = oElement.clientWidth + "px";
					}
				}

				oBody.style.overflow = "hidden";

				/*
					Set the <ul> element's "marginTop" property 
					to a negative value so that the Menu's height
					collapses.
				*/ 
				oUL = oBody.getElementsByTagName("ul")[0];
				oUL.style.marginTop = ("-" + oUL.offsetHeight + "px");
			}
		},

		/*
			"tween" event handler for the Anim instance, used to 
			syncronize the size and position of the Menu instance's 
			shadow and iframe shim (if it exists) with its 
			changing height.
		*/
		handleTween : function(p_sType, p_aArgs, p_oShadow){	
			if (this.cfg.getProperty("iframe")) {
				this.syncIframe();
			}

			if (p_oShadow) {
				p_oShadow.style.height = this.element.offsetHeight + "px";
			}
		},

		/*
			"complete" event handler for the Anim instance, used to 
			remove style properties that were animated so that the 
			Menu instance can be displayed at its final height.
		*/
		handleAnimationComplete : function(p_sType, p_aArgs, p_oShadow) {
			var oBody = this.body,
				oUL = oBody.getElementsByTagName("ul")[0];

			if (p_oShadow) {
				p_oShadow.style.height = this.element.offsetHeight + "px";
			}

			oUL.style.marginTop = "";
			oBody.style.overflow = "";

			//  Check if the menu is a submenu of a submenu.
			if (this.parent && !(this.parent instanceof YAHOO.widget.MenuBarItem)) {
				// Clear widths set by the "beforeshow" event handler
				if (ua.gecko) {
					oBody.style.width = "";
				}

				if (ua.ie == 7) {
					this.element.style.width = "";
				}
			}
		},


		/*
			"show" event handler for each submenu of the MenuBar 
			 instance - used to kick off the animation of the 
			 <ul> element.
		*/
		handleSubmenuShow : function(p_sType, p_sArgs, oOurTownMenu){
			var oElement,
				oShadow,
				oUL;

			if (this.parent) {
				oElement = this.element;
				oShadow = oElement.lastChild;
				oUL = this.body.getElementsByTagName("ul")[0];

				/*
					 Animate the <ul> element's "marginTop" style 
					 property to a value of 0.
				*/
				oAnim = new YAHOO.util.Anim(oUL, 
					{ marginTop: { to: 0 } },
					.5, YAHOO.util.Easing.easeOutStrong);

				oAnim.onStart.subscribe(function () {
					oShadow.style.height = "100%";
				});

				oAnim.animate();

				/*
					Subscribe to the Anim instance's "tween" event for 
					IE to syncronize the size and position of a 
					submenu's shadow and iframe shim (if it exists)  
					with its changing height.
				*/
				if (YAHOO.env.ua.ie) {
					oShadow.style.height = oElement.offsetHeight + "px";
					/*
						Subscribe to the Anim instance's "tween"
						event, passing a reference Menu's shadow 
						element and making the scope of the event 
						listener the Menu instance.
					*/
					oAnim.onTween.subscribe(oOurTownMenu.handleTween, oShadow, this);
				}

				/*
					Subscribe to the Anim instance's "complete" event,
					passing a reference Menu's shadow element and making 
					the scope of the event listener the Menu instance.
				*/
				oAnim.onComplete.subscribe(oOurTownMenu.handleAnimationComplete, oShadow, this);
			}
		}
	};
})();