/*
 * JavaScript Debug Wrapper
 */
if(window.console && console.log)
	window.debug = window.console;
else
{
	window.debug=(function(){var i=this,b=Array.prototype.slice,d=i.console,h={},f,g,m=9,c=["error","warn","info","debug","log"],l="assert clear count dir dirxml exception group groupCollapsed groupEnd profile profileEnd table time timeEnd trace log".split(" "),j=l.length,a=[];while(--j>=0){(function(n){h[n]=function(){m!==0&&d&&d[n]&&d[n].apply(d,arguments)}})(l[j])}j=c.length;while(--j>=0){(function(n,o){h[o]=function(){var q=b.call(arguments),p=[o].concat(q);a.push(p);e(p);if(!d||!k(n)){return}d.firebug?d[o].apply(i,q):d[o]?d[o](q):d.log(q)}})(j,c[j])}function e(n){if(f&&(g||!d||!d.log)){f.apply(i,n)}}h.setLevel=function(n){m=typeof n==="number"?n:9};function k(n){return m>0?m>n:c.length+m<=n}h.setCallback=function(){var o=b.call(arguments),n=a.length,p=n;f=o.shift()||null;g=typeof o[0]==="boolean"?o.shift():false;p-=typeof o[0]==="number"?o.shift():n;while(p<n){e(a[p++])}};return h})();
}

/*
 * Create Application Namespace
 */
if(!MFS) var MFS={};
if(!MFS.p) MFS.p={}; // Popup
if(!MFS.a) MFS.a={}; // Authentication
if(!MFS.h) MFS.h={}; // Hash

/*
 * Hash Pages and Events
 */
MFS.h = {
	siteActionStore: {}, // Map of nice names to ugly names
	pageActionStore: {}, // Map of nice names to ugly names
	curPage: window.location.pathname,
	curActions: new Array(),
	waitingActions: new Array(),

	//add a page specific action to data store
	addPageActions: function(page, map)
	{
		if (typeof(MFS.h.pageActionStore[page]) == "undefined")
			MFS.h.pageActionStore[page]= {}
		
		$.each(map, function(key, value) { 
			MFS.h.pageActionStore[page][key] = value;
	 	});
	},

	//add a site wide action to data store, page specific will take precedence
	addSiteActions: function(map)
	{
		$.each(map, function(key, value) { 
			MFS.h.siteActionStore[key] = value;
	 	});
	},
	
	//do action from link, in hash
	hashAction: function(event)
	{
		event.preventDefault();
		MFS.h.addHashAction($(event.target).attr('href'), true);
	},
	
	//change page from hash
	hashPage: function(event)
	{
		event.preventDefault();
		MFS.h.curActions = new Array();
		MFS.h.waitingActions = new Array();
		MFS.h.doPageChange($(event.target).attr('href'), new Array());
		MFS.h.buildHash($(event.target).attr('href'));
	},
	
	//do action from link, not in hash
	action: function(event)
	{
		event.preventDefault();
		MFS.h.doAction($(event.target).attr('href'));
	},
	
	//add an action to the hash
	addHashAction: function(action, doAction)
	{
		if($.inArray(action, MFS.h.curActions) == -1)
		{
			if(doAction)
			{
				if($.inArray(action, MFS.h.waitingActions) == -1)
					MFS.h.waitingActions.push(action);
				MFS.h.buildHash(MFS.h.curPage);
			}
			else
			{
				MFS.h.curActions.push(action);
				MFS.h.buildHash(MFS.h.curPage);
			}
			return true;
		}
		else
			return false;
	},
	
	//remove an action to the hash
	removeHashAction: function(action){
		var i = $.inArray(action, MFS.h.curActions)
 		if(i != -1)
 		{
 			MFS.h.curActions.splice(i, 1);
 			MFS.h.buildHash(MFS.h.curPage);
 		}
 		
 		var i = $.inArray(action, MFS.h.waitingActions)
 		if(i != -1)
 		{
 			MFS.h.waitingActions.splice(i, 1);
 			MFS.h.buildHash(MFS.h.curPage);
 		}
	},
	
	//remove all action and add this one
	replaceHashActions:function(action, doAction)
 	{
 		while(MFS.h.curActions.lenght > 0)
		{
			if(action == MFS.h.curActions[0])
				MFS.h.curActions = MFS.h.curActions.splice(0,1);
			else
				MFS.H.removeAction(MFS.h.curActions[0]);
		}
			
		if(action == '')
		{
			MFS.h.waitingActions = new Array();
			MFS.h.curActions = new Array();
		}
		else if(doAction)
		{
			MFS.h.waitingActions = new Array(action);
			MFS.h.curActions = new Array();
		}
		else
		{
			MFS.h.curActions = new Array(action);
			MFS.h.waitingActions = new Array();
		}

		MFS.h.buildHash(MFS.h.curPage);
		return true;
 	},
	
	//do multiple actions - run functions
	doActions: function(map)
	{
		$.each(map, function(key, value) { 
			MFS.h.doAction(value);
	 	});
	},
	
	//do an action - run function
	doAction: function(action)
	{
		var parts = action.split("/");
		 	
		if(!parts[0]) //if starts with "/" lets skip the empty element
			parts.shift();
		if(!parts[parts.length-1]) //if ends with "/" lets skip the empty element
			parts.pop();
	 	
		var func = parts.shift(); //function call
		
		if(MFS.h.pageActionStore[MFS.h.curPage] && MFS.h.pageActionStore[MFS.h.curPage][func] && MFS.h.pageActionStore[MFS.h.curPage][func].go)
		{
			if($.inArray(action, MFS.h.curActions) == -1)
				MFS.h.curActions.push(action);
			var i = $.inArray(action, MFS.h.waitingActions)
	 		if(i != -1)
	 			MFS.h.waitingActions.splice(i, 1);
	 			
	 		MFS.h.pageActionStore[MFS.h.curPage][func].go.apply(this, parts);
		}
		else if(MFS.h.siteActionStore[func] && MFS.h.siteActionStore[func].go)
		{
			if($.inArray(action, MFS.h.curActions) == -1)
				MFS.h.curActions.push(action);
			var i = $.inArray(action, MFS.h.waitingActions)
	 		if(i != -1)
	 			MFS.h.waitingActions.splice(i, 1);
	 			
	 		MFS.h.siteActionStore[func].go.apply(this, parts);
		}
		else
			MFS.h.waitingActions.push(action);
			
		return true;
	},
	
	//remove multiple actions - run functions
	removeActions: function(map)
	{
		$.each(map, function(key, value) { 
			MFS.h.removeAction(value);
	 	});
	},
	
	//do an action - run function
	removeAction: function(action)
	{
		var parts = action.split("/");
		 	
		if(!parts[0]) //if starts with "/" lets skip the empty element
			parts.shift();
		if(!parts[parts.length-1]) //if ends with "/" lets skip the empty element
			parts.pop();
	 	
		var func = parts.shift(); //function call
		
		//remove from curActions
		var i = $.inArray(action, MFS.h.curActions)
 		if(i != -1)
 			MFS.h.curActions.splice(i, 1);
 		//remove from waitingActions	
		var i = $.inArray(action, MFS.h.waitingActions)
 		if(i != -1)
 			MFS.h.waitingActions.splice(i, 1);
		
		
		if(MFS.h.pageActionStore[MFS.h.curPage] && MFS.h.pageActionStore[MFS.h.curPage][func] && MFS.h.pageActionStore[MFS.h.curPage][func].end)
			MFS.h.pageActionStore[MFS.h.curPage][func].end.call(this);
		else if(MFS.h.siteActionStore[func] && MFS.h.siteActionStore[func].end)
			MFS.h.siteActionStore[func].end.call(this);
		
		return true;
	},
	
	//build the actual hash
	buildHash: function(page)
 	{
 		var actions = MFS.h.curActions.slice();
		actions = actions.concat(MFS.h.waitingActions.slice());
 		
 		var newHash = "";
 		if(page != window.location.pathname)
 			newHash = "#"+page;
 		for(var i=0; i < actions.length; i++)
 			newHash = newHash+"#!"+actions[i];
 		window.location.hash = newHash;
 	},
	
	//checks hash and processes if needed
	observer: function()
	{
		//Retrive Hash, build temp storage
		var hashArrTmp = window.location.href.replace( /^[^#]*#?(.*)$/, '$1' ).split("#"),
			page="",
			hashArr = new Array(),
			actions = new Array(),
			curActions= new Array(),
			newActions = new Array(),
			oldActions = MFS.h.curActions.slice();
		
		for(var i=0; i<hashArrTmp.length; i++)
		{
			hashArr = hashArr.concat(hashArrTmp[i].split("%23"));
		}
		
		//build page and actions	
		for(var i=0; i<hashArr.length; i++)
		{
			if(hashArr[i] != "")
			{
				if(hashArr[i][0] == "!")
				{
					var tmp = hashArr[i].substr(1);
					if(tmp[0] != "/")
						tmp = "/"+tmp;

					if($.inArray(tmp, MFS.h.curActions) != -1)
		 			{
						var j = $.inArray(tmp, oldActions);
						oldActions.splice(j, 1);
		 				curActions.push(tmp);
		 			}
		 			else
		 				newActions.push(tmp);
				}
				else
				{
					if(hashArr[i][0] != "/")
						page = "/"+hashArr[i];
					else
						page = hashArr[i];
				}
			}
		}
		
		//console.log("observer2", oldActions.slice(), curActions.slice(), newActions.slice());
		
		// add check to show default home page if at root and no hash
		//check if no page in hash
		if(page=="")
		{
			if(window.location.pathname == "" || window.location.pathname == "/")
				page = "/home/";
			else
				page = window.location.pathname;
		}
		
		//those left in curActions are no longer valid so lets run the remove
		MFS.h.curActions = curActions;
		MFS.h.waitingActions = new Array();
		
		MFS.h.removeActions(oldActions);
		
		// handle page then actions
		if(MFS.h.curPage != page)
			MFS.h.doPageChange(page, newActions);
		else
			MFS.h.doActions(newActions);
		return true;
	},
	
	//change the page and update the hash
	doPageChange: function(page, actions)
	{
		$.ajax({
			url: page,
			data: {
				noFrames: true
			},
			dataType: 'html',
			success: function (data, textStatus, XMLHttpRequest) { ajaxOnSuccess(data, actions) },
			error: function (XMLHttpRequest, textStatus, errorThrown) { ajaxOnError(textStatus, errorThrown) }
		});
		
		var ajaxOnSuccess = function(data, actions) {
			$(document).ready(function(){	
				// Set content
				$('#content_area').html(data);
				
				// Fix Menu Activ
				$('#menu').find('.menuactive').removeClass('menuactive');
				$('a[href="'+page+'"]').parents('li').children('a').addClass('menuactive');
				
				//Worked so let set the current page in hash tracking
				MFS.h.curPage = page;
				MFS.h.doActions(actions);
			});
		};
		
		var ajaxOnError = function(textStatus, errorThrown) {
			debug.log('ajax Error', errorThrown);
		};
	}
};


/*
 * Authentication and Session Control
 */
MFS.a = {
	login: function()
	{
		MFS.a.p = new MFS.p({
			hash: "/login/"
		});
		MFS.a.contentObj = MFS.a.p.getContentObj();
		MFS.a.contentObj.html('<h3>Login</h3><form id="login_popup" action="/session/submit_login/" method="post" name="login" onsubmit="return MFS.a.login_submit()"><label for="login_email">Email Address</label><br /><input id="login_email" name="login_email" type="text" size="20" maxlength="40" title="Email" tabIndex="1" /><br /><label for="login_password">Password</label><br /><input id="login_password" name="login_password" type="password" size="20" maxlength="40" tabIndex="2" /><br /><a href="#" onclick="return MFS.a.reset_password()">Click here to reset your password.</a><br /><br /><input id="submit" name="Login" type="submit" value="Login" />&nbsp;&nbsp;<input id="cancel_login" name="Cancel" type="submit" value="Cancel" onclick="this.parentNode.parentNode.close.call(this.parentNode.parentNode.MFSpopupObj, event);"/></form>');
		MFS.a.p.show();
		MFS.a.contentObj.find('#login_email').focus();
		return false;
	},
	
	logout: function()
	{
		MFS.a.p = new MFS.p({
			hash: "/logout/"
		});
		MFS.a.contentObj = MFS.a.p.getContentObj();
		MFS.a.contentObj.html('<h3>Logout</h3><form id="logout_popup" action="/session/submit_logout/" method="post" name="login" onsubmit="return MFS.a.logout_submit()">Are you sure you want to log out?<br /><input id="submit" name="Logout" type="submit" value="Log Out" />&nbsp;&nbsp;<input id="cancel_login" name="Cancel" type="submit" value="Cancel" onclick="this.parentNode.parentNode.close.call(this.parentNode.parentNode.MFSpopupObj, event);"/></form>');
		MFS.a.p.show();
		return false;
	},
	
	login_submit: function()
	{
		MFS.a.p.addWait();
		$(".popup_error").remove();
		var emailReg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/,
			hasError = false,
			login_email = $("#login_email").val();
		if(login_email == '') {
			$("#login_email").after('<span class="popup_error"><br />You forgot to enter your email address.</span>');
			hasError = true;
		} else if(!emailReg.test(login_email)) {
			$("#login_email").after('<span class="popup_error"><br />Enter a valid email address.</span>');
			hasError = true;
		}
		if($("#login_password").val() == '') {
			$("#login_password").after('<span class="popup_error"><br />You forgot to enter your password.</span>');
			hasError = true;
		}
		if(hasError == false) {	
			$.getJSON('/ajax/session/submit_login/', $('#login_popup').serialize() ,function(data) {
				if(data.success)
				{
					MFS.a.contentObj.html('<h3>Welcome '+data.userDisplayName+'!</h3><br /><img src="/images/spinner_32px_f3f5f5.gif" /><br />Thank you for visiting, your page will refresh shortly.<br />');
					MFS.a.p.removeHash();
					MFS.a.p.removeWait();
					setTimeout("location.reload();",1250);
				}
				else if(data.reason == "wrong")
				{
					$("#login_password").after('<span class="popup_error"><br />Oops! It looks like you might have made a mistake, that combination does not work.</span>');
					MFS.a.p.removeWait();
				}
				else if(data.reason == "disabled")
				{
					MFS.a.contentObj.html('<h3>Account Disabled</h3>'+data.userDisplayName+', your account has been disabled please contact the appropriate person if you believe this is in error.<br /><br />');
					MFS.a.p.removeWait();
				}
				else
				{
					alert('An unknown error has occurred, please reload the page.');
					MFS.a.p.removeWait();
				}
			});
		}
		else
			MFS.a.p.removeWait();
		return false;
	},
	
	logout_submit: function()
	{
		MFS.a.p.addWait();
		$.getJSON('/ajax/session/submit_logout/', $('#logout_popup').serialize() ,function(data) {
			if(data.success)
			{
				MFS.a.contentObj.html('<h3>'+data.userDisplayName+'</h3><br/><img src="/images/spinner_32px_f3f5f5.gif" /><br />Thank you for visiting, your page will refresh shortly.');
				MFS.a.p.removeHash();
				MFS.a.p.removeWait();
				setTimeout("location.reload();",1250);
			}
			else
			{	
				alert('An unknown error has occurred, please reload the page.');
				MFS.a.p.removeWait();
			}
		});
		return false;
	},
	
	reset_password: function()
	{
		MFS.a.p.addWait();
		MFS.a.contentObj.html('<div id="pop_content" class="pop_content loading"><br /><img src="/images/spinner_32px_f3f5f5.gif" /><br />Loading...<br /><br /></div>');
		$.getScript('http://api.recaptcha.net/js/recaptcha_ajax.js', function(){
			MFS.a.contentObj.html('<h3>Reset Password</h3><form id="login_popup" action="/session/password_reset/" method="post" name="login" onsubmit="return MFS.a.submit_reset_password()"><label for="login_email">Email Address</label><br /><input id="login_email" name="login_email" type="text" size="20" maxlength="40" title="Email"/><br /><div id="recaptcha_div" style="padding-top:10px; margin-left:auto; margin-right:auto;" align="center"></div><br /><input id="submit" name="Login" type="submit" value="Login" />&nbsp;&nbsp;<input id="cancel_login" name="Cancel" type="submit" value="Cancel" onclick="this.parentNode.parentNode.close.call(this.parentNode.parentNode.MFSpopupObj, event);" /></form>');
			Recaptcha.create(recaptcha_public_key, "recaptcha_div", { theme: "white", callback: Recaptcha.focus_response_field });
			MFS.a.p.removeWait();
		});
		return false;
	},
	
	submit_reset_password: function()
	{
		MFS.a.p.addWait();
		var emailReg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;
		$(".popup_error").remove();
		var hasError = false;
		var login_email = $("#login_email").val();
		if(login_email == '') {
			$("#login_email").after('<span class="popup_error"><br />You forgot to enter your email address.</span>');
			hasError = true;
		} else if(!emailReg.test(login_email)) {
			$("#login_email").after('<span class="popup_error"><br />Enter a valid email address.</span>');
			hasError = true;
		}
		if($("#recaptcha_response_field").val() == '') {
			$("#recaptcha_div").after('<span class="popup_error"><br />You forgot to enter a reCaptcha response.<br /></span>');
			hasError = true;
		}
		if(hasError == false) {
			$.getJSON('/ajax/session/password_reset/', $('#login_popup').serialize() ,function(data) {
				if(data.success) {
					$('.pop_content').html('<h3>Password Reset Sent</h3><p>We have sent an email to '+data.email+' with with instructions to reset your password. Please click the link in the body of that email to reset your password.</p><p>If you do not receive an email it is likely that we do not have this email account in our records. If you are valid user please try a different email address or contact your system administrator for assistance.</p><input id="cancel_login" name="Close" type="submit" value="Close" onclick="this.parentNode.close.call(this.parentNode.MFSpopupObj, event);"/>');
					MFS.a.p.removeWait();
				} else {
					$("#recaptcha_div").after('<span class="popup_error"><br />The reCaptcha response is incorrect please try again.<br /></span>');
					$("#login_email").val("");
					Recaptcha.create(recaptcha_public_key, "recaptcha_div", { theme: "white", callback: Recaptcha.focus_response_field });
					MFS.a.p.removeWait();
				}
			});
		}
		else
			MFS.a.p.removeWait();
		return false;
	},
	kill: function()
	{
		MFS.a.p.kill();
	}
};

/*
 * jQuery hashchange event - v1.3 - 7/21/2010
 * http://benalman.com/projects/jquery-hashchange-plugin/
 * 
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */
(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){r||l(a());n()}).attr("src",r||"javascript:0").insertAfter("body")[0].contentWindow;h.onpropertychange=function(){try{if(event.propertyName==="title"){q.document.title=h.title}}catch(s){}}}};j.stop=k;o=function(){return a(q.location.href)};l=function(v,s){var u=q.document,t=$.fn[c].domain;if(v!==s){u.title=h.title;u.open();t&&u.write('<script>document.domain="'+t+'"<\/script>');u.close();q.location.hash=v}}})();return j})()})(jQuery,this);

/*
 * Popups
 */
MFS.p = function(param)
{
	//MFS.p.
	// parameters object
	this.param = param ? param : {};
	
	var def = {
		width: "556px",
		containerID: "popup",
		disableScreen: true,
		hash: "",
		autoCenter: false,
		maxHeight: '90%'
	};
	
	for (var k in def)
	{
		if (typeof(this.param[k]) != typeof(def[k]))
			this.param[k] = def[k];
	}
	this.container = $('<div class="generic_dialog" id="'+this.param.containerID+'"></div>');
	this.popup = $('<div class="generic_dialog_popup" style="top: 250px; width: '+this.param.width+'"></div>').appendTo(this.container);
	this.containerAdvanced = $('<div class="pop_container_advanced"><span class="pop_container_exit"><a onclick="this.parentNode.parentNode.parentNode.parentNode.close.call(this.parentNode.parentNode.parentNode.parentNode.MFSpopupObj, event); return false;"><img class="s16Cancel" src="/images/img_trans.png" /></a></span></div>').appendTo(this.popup)
	
	this.popupContent = $('<div id="pop_content" class="pop_content"><br /><img src="/images/spinner_32px_f3f5f5.gif" /><br />Loading...<br /><br /></div>').appendTo(this.containerAdvanced);
	
	this.popupContent[0].MFSpopupObj = this;
	this.popupContent[0].close = this.kill;
	this.container[0].MFSpopupObj = this;
	this.container[0].close = this.kill;

	
	return;
}
MFS.p.prototype.resizeActionEvent = function(e)
{
	var pointer = this;
	clearTimeout(this.resizeActionTimeoutID);
	this.resizeActionTimeoutID = setTimeout( function() { pointer.resizeAction() }, 200 );
}
MFS.p.prototype.resizeAction = function(data)
{	
	//unbind DOMSubtreeModified
	this.popupContent.unbind("DOMSubtreeModified");
	
	var data = this;
	data.popupContent.css("max-height", '');
	var newDivHeight = data.containerAdvanced.height();
	var newWindowHeight = $(window).height();


	if(data.param.maxHeight.search("%") > -1)
	{
		newMaxHeight = Math.round(newWindowHeight * (data.param.maxHeight.substring(0,data.param.maxHeight.search("%"))/100));
	}
	else
	{
		if(data.param.maxHeight.search("px") > -1)
			newMaxHeight = Math.round(data.param.maxHeight.substring(0,data.param.maxHeight.search("px")));
		else
			newMaxHeight = Math.round(data.param.maxHeight);
		if(newMaxHeight > newWindowHeight)
			newMaxHeight = newWindowHeight;
	}
	
	if(data.param.autoCenter)
	{
		data.popupContent.css("overflow", "auto");
		var top_bottomSpacing = (newWindowHeight-newMaxHeight)/2;
				
		if(newMaxHeight > newDivHeight)
		{
			data.popupContent.css("max-height", '');			
			data.popup.stop();
			data.popup.animate({"top": ((newWindowHeight-newDivHeight)/2)});
		}
		else
		{
			newTop = top_bottomSpacing - 20;
			if(newTop<0)
			{
				newMaxHeight = newMaxHeight+newTop-20;
				newTop =0;
			}
			data.popupContent.css("max-height", newMaxHeight);
			data.popup.stop();
			data.popup.animate({"top": newTop});
		}
	}
	else
	{
		bottomSpacing = newWindowHeight - (newMaxHeight + 250);
		if(bottomSpacing < 0)
			bottomSpacing = 0
		data.popupContent.css("max-height", (newWindowHeight - 250 -bottomSpacing-40));
	}

	//rebind DOMSubtreeModified
	var pointer = this;
	this.popupContent.bind("DOMSubtreeModified", pointer, function() {pointer.resizeActionEvent()});
}

MFS.p.prototype.show = function()
{
	this.container.hide();
	if(this.param.disableScreen)
	{
		this.grey = $('<div id="greyout"></div>').css({height:$(window).height(), width:$(window).width()});
		this.grey.hide();
		$('body').append(this.grey);
	}
	$('body').append(this.container);
	
	this.lastDivHeight = this.containerAdvanced.height();
	this.lastWindowHeight = $(window).height();
	
	//handlers for 
	var pointer = this;
	this.popupContent.bind("DOMSubtreeModified", pointer, function() {pointer.resizeActionEvent()});
	$(window).bind("resize",pointer, function(){pointer.resizeActionEvent()});
	
	this.container.fadeIn('slow');
	this.grey.fadeIn('slow');
	
	pointer.resizeActionEvent();
	
	if(this.param.hash)
		MFS.h.addHashAction(this.param.hash, false);
	
}

MFS.p.prototype.getContentObj = function()
{
	return this.popupContent;
}

MFS.p.prototype.kill = function(event)
{
	if('undefined' !== typeof(event))
		event.preventDefault();
	
	var cont = this.container;
	
	cont.fadeOut('slow', function(){
		cont.remove();
	});
	$('#greyout').fadeOut('slow', function(){
		$('#greyout').remove();
	});
	
	this.popupContent.unbind("DOMSubtreeModified");
	
	if(this.param.hash)
		MFS.h.removeHashAction(this.param.hash);
	return false;
}

MFS.p.prototype.removeHash = function()
{
	if(this.param.hash)
		MFS.h.removeHashAction(this.param.hash);
}
MFS.p.prototype.addWait = function()
{
	var height = this.popupContent.height() / 2 - 30;
	this.popupContent.append('<div class="ajaxWait" style="height:'+this.popupContent.height()+'px"><div style="margin-top:'+height+'px;"><img src="/images/spinner_32px_f3f5f5.gif" /><br />Please Wait</div></div>');
}
MFS.p.prototype.removeWait = function()
{
	this.popupContent.find('.ajaxWait').remove();
}


/*
 * AutoSuggest
 */
if (typeof(MFS.AutosuggestUsers) == "undefined")
	MFS.AutosuggestUsers = {};
else
	alert("AutosuggestUsers is already set!");

MFS.AutoSuggestUsers = function (id, param)
{
	this.inputObj = $('#'+id);
	this.suggestDivId = id+'-AutoSuggestUserMenu';
	//this.suggestDivId = "as_"+this.inputObj.attr('id');
	
	// init variables
	this.previousVal = "";
	this.userOptionObjs = [];
	this.txtLength = 0;
	this.highlightedItem = -1;
	
	// parameters object
	this.param = param ? param : {};

	// defaults	
	var def = {
		showIcon:false,
		minchars:1,
		ajaxType:"get",
		data: {},
		dataType: "json",
		varname:"input",
		className:"autosuggest",
		timeout:2500,
		delay:0,
		offsety:-5,
		shownoresults:true,
		noresults: "No results!",
		cache: true,
		maxresults: 10,
		exclude:[]
	};
	/*
	//defaults that we are not implementing yet
	var def-notUsed = {
		maxheight: 250,
	};
	//params that are used but not set by default
	var noDefault = {
		url: null,
		fetchMax:10,
		displayMain: "userDisplayName",
		displayLine2: null,
		callback: function() {},
		searchin:null,
	};
	*/
		
	for (var k in def)
	{
		if (typeof(this.param[k]) != typeof(def[k]))
			this.param[k] = def[k];
	}
	
	// set keyup handler for field
	var pointer = this;
	
	if(typeof(this.param.defaultText) != "undefined" && this.param.defaultText != "")
	{
		if (Modernizr.input.placeholder)
		{
			this.inputObj.prop('placeholder', this.param.defaultText);
		}
		else
		{
			if(this.inputObj.val() == "")
			{
				this.inputObj.css('color', '#999');
				this.inputObj.val(this.param.defaultText);
			}
			this.inputObj.focus( function(eventObject){ return pointer.focusHandler(eventObject); });
			this.inputObj.blur( function(eventObject){ return pointer.blurHandler(eventObject); });
		}
	}
	
	this.inputObj.keypress( function(eventObject){ return pointer.KeyPressHandler(eventObject); });
	this.inputObj.keyup( function(eventObject){ return pointer.KeyUpHandler(eventObject); });
	this.inputObj.click( function(eventObject){ return pointer.ClickHandler(eventObject); });
	
	//prevent autocomplete from client
	this.inputObj.attr('autocomplete', 'off');
}

MFS.AutoSuggestUsers.prototype.focusHandler = function(eventObject)
{
	if(this.inputObj.val() == this.param.defaultText)
	{
		this.inputObj.css('color', '');
		this.inputObj.val('');
	}
};
MFS.AutoSuggestUsers.prototype.blurHandler = function(eventObject)
{
	if(this.inputObj.val() == "")
	{
		this.inputObj.css('color', '#999');
		this.inputObj.val(this.param.defaultText);
	}
};

MFS.AutoSuggestUsers.prototype.KeyPressHandler = function(eventObject)
{
	//var key = (window.event) ? window.event.keyCode : eventObject.keyCode;
	var key = eventObject.keyCode;
	var bubble = true;
	switch(key)
	{
		case Event.KEY_RETURN:
			eventObject.stopPropagation();
			this.setHighlightedValue();
			bubble = false;
			break;
			
		case Event.KEY_TAB:
			eventObject.stopPropagation();
			this.setHighlightedValue();
			bubble = false;
			break;

		case Event.KEY_ESC:
			eventObject.stopPropagation();
			this.clearSuggestions();
			break;
	}

	return bubble;
};

MFS.AutoSuggestUsers.prototype.KeyUpHandler = function(eventObject)
{
	//var key = (window.event) ? window.event.keyCode : eventObject.keyCode;
	var key = eventObject.keyCode;
	var bubble = 1;
	eventObject.stopPropagation();
	switch(key)
	{
		case Event.KEY_UP:
			this.changeHighlight(key);
			bubble = 0;
			break;

		case Event.KEY_DOWN:
			this.changeHighlight(key);
			bubble = 0;
			break;
			
		default:
			if (this.inputObj.val() == this.previousVal)
				return 0;
			else
				this.getSuggestions(this.inputObj.val());
	}

	return bubble;
};


MFS.AutoSuggestUsers.prototype.ClickHandler = function(eventObject)
{
	if ($('div#'+this.suggestDivId+' #as_ul').length==0)
		this.getSuggestions(this.inputObj.val());
};


MFS.AutoSuggestUsers.prototype.getSuggestions = function (val)
{
	// kill list
	$('div#'+this.suggestDivId).remove()
	
	this.previousVal = val;
	
	// input length is less than the min required to trigger a request
	// do nothing
	if (val.length < this.param.minchars)
	{
		this.userOptionObjs = [];
		this.txtLength = val.length;
		return 0;
	}
	
	var oldLength = this.txtLength; // old length
	this.txtLength = val.length ? val.length : 0;
	
	// if caching enabled, and user is typing (ie. length of input is increasing)
	// filter results out of aSuggestions from last request
	var numUsers = this.userOptionObjs.length;
	
	var doAjax= true;
	if (numUsers && (numUsers>0) && this.param.cache && (this.param.searchin != undefined && this.param.searchin != "" && this.param.searchin != null) && (this.txtLength > oldLength) )
	{
		var searchin = this.param.searchin;
		var arr= [];
		if($.isArray(searchin))
		{
			var stacks=Array();
			var temp= [];
			for (var i=0; i<searchin.length; i++)
			{
				var searchfor = searchin[i];
				
				for (var j=0;j<numUsers;j++)
				{
					if(this.param.excludeOn && $.inArray(this.userOptionObjs[j][this.param.excludeOn], this.param.exclude) == -1)
						if(this.userOptionObjs[j][searchfor].substr(0,val.length).toLowerCase() == val.toLowerCase())
							temp.push(this.userOptionObjs[j]);
				}
			}
			
			//Remove duplicates		
			for (var i=0; i<temp.length; i++)
			{
				var found = false
				for(var j=0; j<arr.length; j++)
				{
					if($.param(arr[j]) == $.param(temp[i]))
					{
						found=true;
						break;
					}
				}
				if(!found)
					arr.push(temp[i]);
			}
		}
		else
		{
			for (var i=0; i<numUsers; i++)
			{
				if(this.param.excludeOn && $.inArray(this.userOptionObjs[i][this.param.excludeOn], this.param.exclude) == -1)
					if (this.userOptionObjs[i][searchin].substr(0,val.length).toLowerCase() == val.toLowerCase())
						arr.push(this.userOptionObjs[i]);
			}
		}
		
		
		
		this.userOptionObjs = arr;
		this.createList(this.userOptionObjs);
		
		if(arr.length < this.param.maxresults)
			doAjax = true;
	}
	
	if(doAjax)
	{
		var pointer = this;
		var input = this.previousVal;
		clearTimeout(this.ajaxTimeoutID);
		this.ajaxTimeoutID = setTimeout( function() { pointer.doAjaxRequest(input) }, this.param.delay );
	}

	return false;
};

MFS.AutoSuggestUsers.prototype.doAjaxRequest = function (input)
{
	// check that saved input is still the value of the field
	if (input != this.inputObj.val())
		return false;
	
	var input = this.previousVal;
	var data = this.param.data;
	data[this.param.varname] = this.previousVal;
	if(this.param.exclude)
	{
		data.excludeOn = this.param.excludeOn;
		data.exclude = this.param.exclude;
	}
	if(this.param.fetchMax != undefined)
		data['limit'] = this.param.fetchMax;
		
	var pointer = this;
	
	if (!this.param.url)
		return false;
	
	$.ajax({
	  url: this.param.url,
	  ajaxType: this.param.ajaxType,
	  data: data,
	  dataType: this.param.dataType,
	  success: function (data, textStatus, XMLHttpRequest) { pointer.setSuggestions(data, input) },
	  error: function (XMLHttpRequest, textStatus, errorThrown) { alert("AJAX error: "+textStatus); }
	});

};

MFS.AutoSuggestUsers.prototype.setSuggestions = function (data, input)
{
	
	this.userOptionObjs = data;
	// if field input no longer matches what was passed to the request rerun getSuggestions

	if (input != this.inputObj.val())
		
		this.getSuggestions(this.inputObj.val());
	else
		this.createList(this.userOptionObjs);
};

MFS.AutoSuggestUsers.prototype.createList = function(arr)
{
	var pointer = this;
	
	// get rid of old list and clear the list removal timeout
	$('div#'+this.suggestDivId).remove();
	clearTimeout(this.divTimeoutID);
	
	// if no results, and shownoresults is false, do nothing
	if (arr.length == 0 && !this.param.shownoresults)
		return false;
	
	var holdingDiv = $('<div id="'+this.suggestDivId+'" class="'+this.param.className+'"></div>');
	var ul = $('<ul id="as_ul"></ul>');
	
	// loop throught arr of suggestions creating an LI element for each suggestion
	for (var i=0;i<arr.length && i<this.param.maxresults;i++)
	{
		// format output with the input enclosed in a EM element
		var text = arr[i][this.param.displayMain];
		
		var display = new String("");
		
		if(text.indexOf(" ") == -1)
		{
			var start = text.toLowerCase().indexOf( this.previousVal.toLowerCase() );
			display = text.substring(0,start) + "<em>" + text.substring(start, start+this.previousVal.length) + "</em>" + text.substring(start+this.previousVal.length);
		}
		else
		{
			if(text.indexOf(" ") > -1)
				var strArr = text.split(" ");
			else
				var strArr = new Array(text);
			
			for (var j=0; j<strArr.length; j++)
			{
				var str = strArr[j];
				var start = str.toLowerCase().indexOf( this.previousVal.toLowerCase() )
				if(start >= 0)
					display += " " + str.substring(0, start) + "<em>" + str.substring(start, start+this.previousVal.length) + "</em>" + str.substring(start+this.previousVal.length);
				else
					display += " " + str;
				
			}
			//remove leading space
			display = display.slice(1);
		}
		
		//get icon
		var iconClass = "";
		if(this.param.showIcon)
		{
			re = new RegExp('(^|,)\\s*\\.'+arr[i]['icon']+'\\s*(\\,|$)');
			$.each(document.styleSheets, function(){
				$.each(this.cssRules || this.rules, function() {
					if (re.test(this.selectorText))
						iconClass = arr[i]['icon'];
				});
			});
		}
		
		if(iconClass != "")
			var span = $('<img class="'+iconClass+'" src="/images/img_trans.png" style="margin-left:5px;"  /><span style="margin-top:-29px;padding:5px 5px 5px 34px">'+display+'</span>');
		else
			var span = $('<span>'+display+'</span>');
		
		//if we have second line of data
		if (typeof(this.param.displayLine2) == "string" && typeof(arr[i][this.param.displayLine2]) != "undefined" &&  arr[i][this.param.displayLine2] != "" &&  arr[i][this.param.displayLine2] != "null")
		{
			// format output with the input enclosed in a EM element
			var text = arr[i][this.param.displayLine2];
			
			var display = new String("");
			
			if(text.indexOf(" ") == -1)
			{
				var start = text.toLowerCase().indexOf( this.previousVal.toLowerCase() );
				display = text.substring(0,start) + "<em>" + text.substring(start, start+this.previousVal.length) + "</em>" + text.substring(start+this.previousVal.length);
			}
			else
			{
				if(text.indexOf(" ") > -1)
					var strArr = text.split(" ");
				else
					var strArr = new Array(text);
				
				for (var j=0; j<strArr.length; j++)
				{
					var str = strArr[j];
					var start = str.toLowerCase().indexOf( this.previousVal.toLowerCase() )
					if(start >= 0)
						display += " " + str.substring(0, start) + "<em>" + str.substring(start, start+this.previousVal.length) + "</em>" + str.substring(start+this.previousVal.length);
					else
						display += " " + str;
					
				}
				//remove leading space
				display = display.slice(1);
			}
			
			span.append('<br /><small>'+display+'</small>');
		}
			
		var a = $('<a style="cursor:pointer"></a>')
			.attr('name',i)
			.click(function () { pointer.setHighlightedValue(); return false; })
			.mouseover(function () { pointer.setHighlight(Number(this.name)); });

		span.appendTo(a).parent()
			.appendTo('<li></li>').parent()
				.appendTo(ul);
		
			}
	
	// no results
	if (arr.length == 0 && this.param.shownoresults)
		ul.append('<li class="as_warning"><span><img class="s24Alert" src="/images/img_trans.png" style="margin-left:5px;"  /><span style="margin-top:-29px;padding:5px 5px 5px 34px">'+this.param.noresults+'</span></span></li>');
		//ul.append('<li class="as_warning">'+this.param.noresults+'</li>');

	holdingDiv.append( ul );
	
	// get position of target textfield position holding div below it set width of holding div to width of field
	var pos = this.inputObj.offset();
	holdingDiv.css({
		'left': pos.left + "px",
		'top':  (pos.top + this.inputObj.outerHeight() + this.param.offsety ) + "px",
		'width': this.inputObj.outerWidth() + "px"
	});
	
	// set mouseover functions for div
	// when mouse pointer leaves div, set a timeout to remove the list after an interval
	// when mouse enters div, kill the timeout so the list won't be removed
	holdingDiv.mouseover(function(){ clearTimeout(pointer.divTimeoutID); });
	holdingDiv.mouseleave(function(){ pointer.resetTimeout() });

	holdingDiv.hide();
	$('body').append(holdingDiv);
	holdingDiv.fadeIn('fast');
	
	// currently no item is highlighted
	this.highlightedItem = -1;
	
	// remove list after an interval
	var pointer = this;
	this.divTimeoutID = setTimeout(function () { pointer.clearSuggestions() }, this.param.timeout);

};

MFS.AutoSuggestUsers.prototype.changeHighlight = function(key)
{
	if ($('div#'+this.suggestDivId+' #as_ul').length=0)
		return false;
	
	var newHighlight;

	if (key == Event.KEY_DOWN)
		newHighlight = this.highlightedItem + 1;
	else if (key == Event.KEY_UP)
		newHighlight = this.highlightedItem - 1;
	
	if (newHighlight > $('div#'+this.suggestDivId+' #as_ul li').length-1)
		newHighlight = $('div#'+this.suggestDivId+' #as_ul li').length-1;
	if (newHighlight < 0)
		newHighlight = 0;
	
	this.setHighlight(newHighlight);
};

MFS.AutoSuggestUsers.prototype.setHighlight = function(newHighlight)
{
	if ($('div#'+this.suggestDivId+' #as_ul').length=0)
		return false;
			
	if (this.highlightedItem > -1)
		this.clearHighlight();
	
	this.highlightedItem = Number(newHighlight);
	
	$('div#'+this.suggestDivId+' #as_ul li:eq('+this.highlightedItem+')').addClass('as_highlight');
	
	clearTimeout(this.divTimeoutID);
};

MFS.AutoSuggestUsers.prototype.clearHighlight = function()
{
	if ($('div#'+this.suggestDivId+' #as_ul').length=0)
		return false;
	
	if (this.highlightedItem > -1)
	{
		$('div#'+this.suggestDivId+' #as_ul li:eq('+this.highlightedItem+')').removeClass('as_highlight');
		this.highlightedItem = -1;
	}
};

MFS.AutoSuggestUsers.prototype.setHighlightedValue = function ()
{
	if (this.highlightedItem>-1)
	{
		this.previousVal = this.inputObj.val(this.userOptionObjs[ this.highlightedItem ][this.param.displayMain]);
		
		// move cursor to end of input (safari)
		this.inputObj.focus();
		if (this.inputObj.get(0).selectionStart)
			this.inputObj.get(0).setSelectionRange(this.previousVal.length, this.inputObj.val().length);
	
		this.clearSuggestions();
		
		// pass selected object to callback function, if exists
		if (typeof(this.param.callback) == "function")
			this.param.callback( this.userOptionObjs[this.highlightedItem] );
	}
};

MFS.AutoSuggestUsers.prototype.resetTimeout = function()
{
	clearTimeout(this.divTimeoutID);
	var pointer = this;
	this.divTimeoutID = setTimeout(function () { pointer.clearSuggestions() }, this.param.timeout);
};

MFS.AutoSuggestUsers.prototype.clearSuggestions = function ()
{
	clearTimeout(this.divTimeoutID);
	$('div#'+this.suggestDivId).fadeOut('slow', function() { $(this).remove(); });
};

var Event = {
    KEY_BACKSPACE: 8,
    KEY_TAB:       9,
    KEY_RETURN:   13,
    KEY_ESC:      27,
    KEY_LEFT:     37,
    KEY_UP:       38,
    KEY_RIGHT:    39,
    KEY_DOWN:     40,
    KEY_DELETE:   46,
    KEY_HOME:     36,
    KEY_END:      35,
    KEY_PAGEUP:   33,
    KEY_PAGEDOWN: 34,
    KEY_INSERT:   45
	
};
/*
 * Helper Functions
 */
function sortArray(arr, sort, desc) {
	arr.sort(function (a,b) {
		var answer = 0;
		if(isNaN(a[sort]))
		{
			var valA=a[sort].toLowerCase(), valB=b[sort].toLowerCase();
			if(valA < valB)
				answer = -1;
			else if(valA > valB)
				answer = 1;
		}
		else
			answer = a[sort] -b[sort];
		
		if(desc == true)
			answer = -1 * answer;
		
		return answer;
	});
	return arr;
};



/*
 * BootStrap
 */
MFS.h.addSiteActions({
	login: {go:MFS.a.login, end:MFS.a.kill},
	logout: {go:MFS.a.logout, end:MFS.a.kill}
});

/*
 * Document Ready Calls
 */
$(document).ready(function(){
	$('.hashAction').live("click", function(event) {
		MFS.h.hashAction(event);
		return false;
	});

	$('.hashPage').live("click", function(event) {
		return MFS.h.hashPage(event);
	});	

	$('.action').live("click", function(event) {
		return MFS.h.action(event);
	});
	
});

$(function(){
	$(window).hashchange( function(){
		MFS.h.observer();
	});
	$(window).hashchange();
});


/**
 * Gets the width of the OS scrollbar
 */
(function($) {
	var scrollbarWidth = 0;
	$.getScrollbarWidth = function() {
		if ( !scrollbarWidth ) {
			if ( $.browser.msie ) {
				var $textarea1 = $('<textarea cols="10" rows="2"></textarea>')
						.css({ position: 'absolute', top: -1000, left: -1000 }).appendTo('body'),
					$textarea2 = $('<textarea cols="10" rows="2" style="overflow: hidden;"></textarea>')
						.css({ position: 'absolute', top: -1000, left: -1000 }).appendTo('body');
				scrollbarWidth = $textarea1.width() - $textarea2.width();
				$textarea1.add($textarea2).remove();
			} else {
				var $div = $('<div />')
					.css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: -1000 })
					.prependTo('body').append('<div />').find('div')
						.css({ width: '100%', height: 200 });
				scrollbarWidth = 100 - $div.width();
				$div.parent().remove();
			}
		}
		return scrollbarWidth;
	};
})(jQuery);
