    var Q = jQuery;
	var FT_COUNT_INTERVAL;
	var FT_COUNT_FREQUENCY = 5000;
	var FT_DATA_INTERVAL;
	var FT_DATA_FREQUENCY = 15000;

    function UnescapeStarListHTML(list)
    {
	    var resp = list.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g, "\"");
	    //get rid of the trailing line break.
	    resp = resp.replace("<br/>","");
	    
	    //swap out the big stars for small ones
	    resp = resp.replace(/\/images\/icons\/stars_blue.gif/g,"/images/FavoriteTutorsList/tiny-blue-star.gif");
	    resp = resp.replace(/\/images\/icons\/stars_white.gif/g,"/images/FavoriteTutorsList/tiny-empty-star.gif");
	    
	    return resp;
	}

	function QuickNotifcationMessage(message)
	{
		if (message.length > 5) 
		{
			//[1] set/overwrite a cookie
			document.cookie = "FTLastKnownStates=" + message +"; path=/";

			//[2] determine if we have to display a message to the user
			var TutorStatesData = message.split(",");
			var pattern = /{(([\w'-]*\s*)*)}/gi;
			var response = "";
			var tokens;
			var tutorAlert = "";
			
			for (var n=0; n< TutorStatesData.length; n++)
			{
				//{guid}{statusid}{gender}{displayname}{alert?}
				tokens = TutorStatesData[n].match(pattern);
				
				//If we 'alert?' is true AND the tutor is available
				if (tokens[4] == "{1}" && tokens[1] == "{1}")
				{
					var displayname = tokens[3].substr(1,tokens[3].length-2);
					
					tutorAlert = "<div class='TutorAvailable'>"+tokens[2]; //nab the gender here
					tutorAlert = tutorAlert + "<p>Favorite tutor, <b>"+displayname+"</b>, is now available for an Algebra session!</p>";
					tutorAlert = tutorAlert + "</div>";
					
					//Add avatar based on gender
					tutorAlert = tutorAlert.replace("{m}","<img src='/images/FavoriteTutorsList/male-available-avatar.png' class='avatar' ");
					tutorAlert = tutorAlert.replace("{f}","<img src='/images/FavoriteTutorsList/female-available-avatar.png' class='avatar' ");
					
					response = response + tutorAlert;
				}
			}

			//This allows us to display a quick notifcation to the user right above the favorite tutors list
			if (response.length > 5)
			{
				Q("#FavoriteTutorNotifcation .Content").html(response);
				Q("#FavoriteTutorNotifcation").fadeIn();
				setTimeout(function() {
					Q("#FavoriteTutorNotifcation").fadeOut("slow");
				}, 4000);
			}
		}
    }
    
	function SetClass(StatusId)
	{
		var StatusClass = "";
		
		if (StatusId == 1)
		{
			StatusClass = "AFavoriteTutorAvailable";
		}
		else if (StatusId > 1)
		{
			StatusClass = "AFavoriteTutorBusy";
		}
		else
		{
			StatusClass = "AFavoriteTutorOffline";
		}
		
		return StatusClass;
	}

    function UpdateFavoriteTutorsData(YourTutors) 
    {
    
		//[0] the previous call displays the loading image.
		//[1] get the height of the FTL content area and set the loading image div appropriately
		//[2] update content under the loading image area.
		
		var contentHeight = Q("#FavTutorContent").height();
		
		// ie6 doesn't calculate this correctly (insert shock here);
		if (Q.browser.msie && Q.browser.version < 7)
		{
			contentHeight = contentHeight + 300;
		}
		
		Q("#FavoriteTutorLoadingImage").css("height",( contentHeight + "px" ));
		
	    if (YourTutors.d.length > 0)
	    {
			Q("#YourFavoriteTutorsAreEmpty").hide();
			Q("#RecommendedTutors .WhyWait").hide();
			Q("#RecommendedTutors .LetUsPick").show();
			Q("#FavoriteTutorListControls").show();
            
            //Set up the visible favorite tutor list
		    var template_online = Q("#TemplateFavoriteTutorOnline").html();
		    Q("#YourFavoriteTutorsOnline").setTemplate(template_online);
		    Q("#YourFavoriteTutorsOnline").setParam('UnescapeStarListHTML',UnescapeStarListHTML);
		    Q("#YourFavoriteTutorsOnline").setParam('SetClass',SetClass);
		    Q("#YourFavoriteTutorsOnline").processTemplate(YourTutors);
		    
		    
		    var template_offline = Q("#TemplateFavoriteTutorOffline").html();
		    Q("#YourFavoriteTutorsOffline").setTemplate(template_offline);
		    Q("#YourFavoriteTutorsOffline").setParam('UnescapeStarListHTML',UnescapeStarListHTML);
		    Q("#YourFavoriteTutorsOffline").setParam('SetClass',SetClass);
		    Q("#YourFavoriteTutorsOffline").processTemplate(YourTutors);    
		    
		    
		    //Fill the details.  You MUST create a new template object.  You can't just overwrite the other template object.
		    //Only update/refresh the data in this area if it's not visible.
		    if ( Q("#FavoriteTutorDetails").is(":hidden") )
		    {
				var template2 = Q("#TemplateTutorDetail").html();
				Q("#FavoriteTutorDetails .Content").setTemplate(template2);
				Q("#FavoriteTutorDetails .Content").setParam('UnescapeStarListHTML',UnescapeStarListHTML);
				Q("#FavoriteTutorDetails .Content").processTemplate(YourTutors);
		    }
    		
		    //re-attach the mouse click events
		    Q("#FavTutorContent .DetailLink").click(OpenDetailDiv);  //toggle(OpenDetailDiv, CloseDetailDiv); //click(function() { CloseDetailDiv(); OpenDetailDiv(); });
		    
			Q("#FavTutorContent .FavoriteTutorRemove").click(DeleteFavoriteTutor);
	    }
	    else
	    {
			Q("#YourFavoriteTutorsAreEmpty").show();
			Q("#FavoriteTutorListControls").hide();
			Q("#YourFavoriteTutorsOnline").html(""); /*clearing out the html here*/
			Q("#YourFavoriteTutorsOffline").html(""); /*clearing out the html here*/
			Q("#RecommendedTutors .WhyWait").hide();
			Q("#RecommendedTutors .LetUsPick").show();
	    }
    }
    
    function DeleteFavoriteTutor() {
        if (confirm('Are you sure you want to remove this tutor for your favorite tutors?')) {
            
            //Get the tutor's guid
            var tutorGUID = Q(this).parents("div.AFavoriteTutor").find("input[type=hidden]").val();

            Q.ajax({
                type: "POST",
                url: "/WebServices/FavoriteTutors.asmx/RemoveFavoriteTtuor",
                data: "{'TutorGUID': '" + tutorGUID + "'}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                error: function(xhr, msg, e) {
                    AjaxLogErrors();
                },
                success: function(msg) {
                    //We'll stop the current tick, then restart it again
                    clearInterval(FT_DATA_INTERVAL);

                    //perform the update now
                    GetFavoriteTutorsData();

                    //restart the tick
                    FT_DATA_INTERVAL = setInterval(GetFavoriteTutorsData, FT_DATA_FREQUENCY);
                }
            });
        }
    }

    function OpenDetailDiv() {
    
    	/*We need to move the pointer appropriately*/
	    Q("#FavoriteTutorDetailsPointer").show();
	    Q("#FavoriteTutorDetailsPointer").css("top",( Q(this).position().top + 0 )+"px" );
    	
	    /*ie6 is slightly off the mark here when posisioning the arrow.  Here's how we'll fix it.*/
	    if (Q.browser.msie && Q.browser.version < 7)
	    {
		    Q("#FavoriteTutorDetailsPointer").css("left",(Q(this).position().left - 87 )+"px");
	    }
	    else
	    {
		    Q("#FavoriteTutorDetailsPointer").css("left",(Q(this).position().left - 84 )+"px");
	    }
    	
	    /*We need to move the details box if the list is too tall.*/
	    Q("#FavoriteTutorDetails").show();
	    var pp = Q("#FavoriteTutorDetailsPointer").position().top;
	    var pp_min = 140; /*Arbitrary value for what the min should be.*/
	    if (pp < pp_min)
	    {
		    Q("#FavoriteTutorDetails").css("bottom", (20+ (pp_min - pp))+"px");
	    }
	    else
	    {
		    Q("#FavoriteTutorDetails").css("bottom", "20px");
	    }
	    
	    /*Now we have to display the correct div*/
	    //[1] get the div that corresponds to the appropriate tutor
	    var TutorIndex = Q(this).parents("div.AFavoriteTutor").find("input[type=hidden]").val();
	    
	    //[2] hide any/all of the possibly displayed divs
	    Q("#FavoriteTutorDetails div.AFavoriteTutorDetail").hide();
	    
	    //[3] show the div we want
	    Q("#Detail_"+TutorIndex).show();
    }

    function CloseDetailDiv() {
	    Q("#FavoriteTutorDetailsPointer").hide();
	    Q("#FavoriteTutorDetails div.AFavoriteTutorDetail").hide();
	    Q("#FavoriteTutorDetails").hide();
    }
    
    function ConnectToYourFavoriteTutor(TutorGUID, SubjectId)
    {
	   //Initiate classroom connection
    	doStartASession('FavoriteTutorListTutor', '?SubjectId=' + SubjectId + '&Fave=' + TutorGUID);

    	//Close Fav Tutor Window
    	CloseFavoriteTutorMenu();
    }

    function OpenFavoriteTutorMenu() 
    {
    	if (Q("#FlashOdometer") != null) {
    		Q("#FlashOdometer").hide();
    	}
	    Q("#FavoriteTutorsListContainerBG").show();
	    Q("#FavoriteTutorsListContainerBG").css({ "opacity": "0.7" }); //settting this value here allows jQuery to deal with IE6 opacity for us
	    Q("#FavoriteTutorListContainer").slideDown("slow");
	    Q("#FavTutorsHandleInner").addClass("active");
	    
	    //Since this menu is open, turn the favorite tutor list count "tick" off
	    clearInterval(FT_COUNT_INTERVAL);
	    
	    //Get an update of the favorite tutors menu
	    GetFavoriteTutorsData();
	    
	    //Turn the favorite tutor list data "tick" on
	    FT_DATA_INTERVAL = setInterval(GetFavoriteTutorsData, FT_DATA_FREQUENCY);
    }

    function CloseFavoriteTutorMenu()
    {
    	if (Q("#FlashOdometer") != null) {
    		Q("#FlashOdometer").show();
    	}
	    Q("#FavoriteTutorListContainer").slideUp("slow");
	    Q("#FavoriteTutorsListContainerBG").hide();
	    Q("#FavTutorsHandleInner").removeClass("active");
	    CloseDetailDiv();
	    
	    //Turn the favorite tutor list data "tick" off
	    clearInterval(FT_DATA_INTERVAL);
	    
	    //Turn the favorite tutor list count "tick" on
	    FT_COUNT_INTERVAL = setInterval(GetFavoriteTutorNotifications, FT_COUNT_FREQUENCY);
    }

    function ToggleFavoriteTutorMenuState()
    {
	    if (Q("#FavTutorsHandleInner").hasClass("active"))
	    {
		    CloseFavoriteTutorMenu();
	    }
	    else
	    {
		    OpenFavoriteTutorMenu();
	    }
    }
    
	function AddFavoriteTutor(tutorGuid) 
	{
	    Q.ajax({
	        type: "POST",
	        url: "/WebServices/FavoriteTutors.asmx/AddFavoriteTutor",
	        data: "{'TutorUserGUID': '" + tutorGuid + "'}",
	        contentType: "application/json; charset=utf-8",
	        dataType: "json",
		    error: function(xhr, msg, e) 
		    {
				AjaxLogErrors();
		    },
	        success: function(msg) {
	            $$('.isFavTutor_' + tutorGuid).each(function(item) {
	            item.innerHTML = FAVORITE_HEART_IMG;  //this should be set server side by previous sessions control or anything else that uses it
	            });
	        }
	    });
	    
	    //Since we're adding people now, let's make sure the label is set to display
	    Q("#FavoriteTutorListControls .editFavorites").hide();
	    Q("#FavoriteTutorListControls .connectFavorites").show();
	    
	    //...and it's displaying the connection controls
	    Q("#YourFavoriteTutorsOnline .ftConnect").show();
	    Q("#YourFavoriteTutorsOnline .ftRemove").hide();
	    
	}
	
	function GetFavoriteTutorNotifications() 
	{
		var pattern = /;?\s*FTLastKnownStates=(.*})/gi
		var tokens = document.cookie.match(pattern);
		var states = (tokens != null)? RegExp.$1 : "{}";
		
	    Q.ajax({
		    type: "POST",
		    url: "/WebServices/FavoriteTutors.asmx/FavoriteTutorsStatusUpdatesLK",
		    data: "{'LKTutorStates': '" + states + "'}",
		    contentType: "application/json; charset=utf-8",
		    dataType: "json",
		    error: function(xhr, msg, e) 
		    {
				//simply swallow this error
		    },
		    success: function(msg) { QuickNotifcationMessage(msg.d); }
	    });
	}
	
	function GetFavoriteTutorsData()
	{
	    Q.ajax({
			beforeSend: function(){ Q("#FavoriteTutorLoadingImage").show(); },
			complete: function(){Q("#FavoriteTutorLoadingImage").hide();},
		    type: "POST",
		    url: "/WebServices/FavoriteTutors.asmx/UpdateFavoriteTutorsData",
		    data: "{}",
		    contentType: "application/json; charset=utf-8",
		    dataType: "json",
		    error: function(xhr, msg, e) 
		    {
				//swallow this error otherwise things could get annoying
		    },
		    success: function(msg)
		    {
				UpdateFavoriteTutorsData(msg); 
				//Let's also set this mode correctly after we get our data.
				SetTutorDisplayMode();
		    }
	    });
	}
	
	function SetTutorDisplayMode() {

	    //close details div if open
	    CloseDetailDiv();
	    
		//This is a little counter-intuitive, but if the edit link is visible, it means we're in connect mode since it's a toggle.
		if (Q("#FavoriteTutorListControls .editFavorites").is(":visible"))
		{
			//flip the controls
			Q("#YourFavoriteTutorsOnline .ftRemove").hide();
			Q("#YourFavoriteTutorsOffline .ftRemove").hide();
			Q("#YourFavoriteTutorsOnline .ftConnect").show();
			Q("#YourFavoriteTutorsOffline .ftConnect").show();
		}
		else
		{
			//flip the controls
			Q("#YourFavoriteTutorsOnline .ftConnect").hide();
			Q("#YourFavoriteTutorsOffline .ftConnect").hide();
			Q("#YourFavoriteTutorsOnline .ftRemove").show();	
			Q("#YourFavoriteTutorsOffline .ftRemove").show();
		}
		
		//We do the same thing for hiding/showing the offline tutors
		if (Q("#FavoriteTutorListControls .hideOffline").is(":visible"))
		{
			Q("#YourFavoriteTutorsOffline").show();
		}
		else
		{
			Q("#YourFavoriteTutorsOffline").hide();
		}
	}

	Q(document).ready(function() {
		Q("#FavTutorsHandleInner").click(ToggleFavoriteTutorMenuState);
		Q("#hlkFavTutorClose").click(CloseFavoriteTutorMenu);
		Q("#FavTutorsHeader").click(CloseFavoriteTutorMenu);

		//We hide this control if certain cases.  If it's hidden, there's no need to perform the rest of this JS
		if (Q("#FavoriteTutorList").length > 0) {
		
			//reveal the bar
			Q("#FavTutorsHandleContainer").show();
			
			//If you're not logged in, show the message to get you to log in
			//AEM: Handling the 0 minutes case as well
			if (CLASSROOM_CAN_CONNECT == 'undefined' || (CLASSROOM_CAN_CONNECT == 'False' && CLASSROOM_MINUTES !=0) )
			{
				Q("#FavTutorContent").hide();
				Q("#RecommendedTutors").hide();
				Q("#FavTutorsFooter").css("height", "25px");
				Q("#FavTutorContentPreview").show();
			}
			//otherwise, start the real functionality
			else
			{
				//this get the first count
				GetFavoriteTutorNotifications();

				//setup the tick to every 5 seconds.
				FT_COUNT_INTERVAL = setInterval(GetFavoriteTutorNotifications, FT_COUNT_FREQUENCY);

				//for flipping between the edit and connect states
				Q("#FavoriteTutorListControls .editFavorites").click(function() {

					//flip the labels
					Q("#FavoriteTutorListControls .editFavorites").hide();
					Q("#FavoriteTutorListControls .connectFavorites").show();

					//Set display
					SetTutorDisplayMode();
				});

				Q("#FavoriteTutorListControls .connectFavorites").click(function() {

					//flip the labels
					Q("#FavoriteTutorListControls .connectFavorites").hide();
					Q("#FavoriteTutorListControls .editFavorites").show();

					//set display
					SetTutorDisplayMode();
				});

				//for flipping between seeing offline tutors and hiding them
				Q("#FavoriteTutorListControls .hideOffline").click(function() {
					//flip labels
					Q("#FavoriteTutorListControls .hideOffline").hide();
					Q("#FavoriteTutorListControls .showOffline").show();

					//set display
					SetTutorDisplayMode();
				});

				Q("#FavoriteTutorListControls .showOffline").click(function() {
					//flip labels
					Q("#FavoriteTutorListControls .showOffline").hide();
					Q("#FavoriteTutorListControls .hideOffline").show();

					//set display
					SetTutorDisplayMode();
				});
				
				Q("#FavoriteTutorDetails .Close").click(function(){
					CloseDetailDiv();
				});
			}
		}
		else {
			//There nothing else to worry about. :-)
		}
	});
