/**
 * Overview: This plugin is included on any page where VOW features exist. When a registered user is logged in, 
 * all VOW services are available to the user. If a registered user is not signed in and clicks on a VOW-only link, 
 * this module will process the request and interupt the request with the signin process. Once the 
 * signin/registration process has completed the user will continue on as usual. 
 *
 * usage: $(<selector>).csVOWPanel() - can be used on the CS VOW panel or the legacy RPM3 VIP Panel.
 *
 * usage: used on all website pages that have VIP features
 * dependencies: jQuery, jquery.rpm.js, jquery.form.js
 */
(function() {
	$.fn.csVOWPanel = $.csVOWPanel = function(method) {
		var csVOWAjaxActive = false; 	// stores any active VOW AJAX sessions
		
		var SIGNEDINMESSAGE = "You are now signed in.";
		var SIGNEDOUTMESSAGE = "You are now signed out.";
		var SIGNOUTCONFIRMMESSAGE = "Are you sure you want to Sign Out?";
		var SIGNEDOUTPANELHTML = 'Not Logged In. <a href="#" id="csVOWSignIn">Sign In Now</a> | <a href="#" id="csVOWRegister">Register</a>';
		//var SIGNEDOUTPANELHTML = 'Not Logged In. <a id="csVOWSignIn" href="#">Sign In Now</a> | <a id="csVOWRegister" href="#">Register</a>';

		// public jQuery methods (work when the plugin is called on an element)
		var methods = {
			/**
			* Initializes the dashboard
			*
			* @param options options used to configure the plygin
			*/
			init : function(opts){
				
				// this if for legacy RPM3 support - to work with the legacy dashboard.
				if(this.size() == 0) return $('#dashboard').csVOWPanel(opts);

				return this.each(function() {
					var $this = $(this);  // create a quick-reference jQuery object with this DOM element
					
					var options = {};
					
					$.extend(options, opts);
					
					options.infoWindowTabsInitiated = false;	// determines whether we need to initiate the tabs
					
					//helpers.vOWAdminInit();
					//helpers.vIPPanelLoginInit();
					
					//Use below instead of above after testing is complete
					if(options.plugin){
						// initialize the VOW Panel admin features
						helpers.vOWAdminInit();
					}else{
						// support for legacy RPM3 VIP panel
						helpers.vIPPanelLoginInit();
					}
					
					// assign sign out event if logged in
					helpers.bindToSignOut();
				
					if(options.plugin)
						// for some fucked reason in WordPress when the ajax target is passed in it gets automagically urlencoded so we need to escape it or 
						// we lose one of the required params used in the request
						options.vipAjaxTarget = options.vipAjaxTarget.replace("&#038;", "&");
				
					// assign VOW features click event(s)
					function featureClick(feature){
						$.csVOWPanel('csVOWAjax', {
							type: "GET",
							url: options.vipAjaxTarget,
							data: "pathway=173&"+feature+"=true&modletId=" + $.clickSoldUtils('getNextAvailableModuleId'),
							dataType: "html",							
							beforeSend: function(jqXHR, settings){
								$.clickSoldUtils('infoBoxCreate', {cb_his_control: "log"});
							},
							success: function(data){
								var infoBoxOptions = {
									html: data,
									scrolling : false,
									cb_his_control: "log",
									onComplete: function(){
										$.clickSoldUtils('infoBoxResize');
										if(feature == "instantHomeEval"){
											helpers.plotMarketAnalyzerResults();
										}else if(feature == "marketWatch"){
											vipPanelMethods.initMarketWatchForm();
										}
									}
								};
								$.clickSoldUtils('infoBoxCreate', infoBoxOptions);
							}
						}, function(){}, function(){}, true);
						
						return false;
					};
					
					$("#csVOWAccount", this).click(function(){return featureClick("myAccount");});
					$("#myAccount", '#vipMenu').click(function(){return featureClick("myAccount");});	// support for RPM3 VIP panels.

					// assign saved searches click event
					$("#csVOWSearches", this).click(function(){return featureClick("savedSearches");});
					$("#savedSearches", '#vipMenu').click(function(){return featureClick("savedSearches");});	// support for RPM3 VIP panels.

					// assign favorite listings click event
					$("#csVOWFavorites", this).click(function(){return featureClick("favoriteListings");});
					$("#favoriteListings", '#vipMenu').click(function(){return featureClick("favoriteListings");});	// support for RPM3 VIP panels.

					// assign market analyzer click event
					$("#csVOWAnalyzer", this).click(function(){return featureClick("instantHomeEval");});
					$("#instantHomeEval", '#vipMenu').click(function(){return featureClick("instantHomeEval");});	// support for RPM3 VIP panels.

					
					// The following are only for RPM3
					if(!options.plugin){
						$("#marketWatch", '#vipMenu').click(function(){return featureClick("marketWatch");});	// support for RPM3 VIP panels.
						$("#investorTools", '#vipMenu').click(function(){return featureClick("investorTools");});	// support for RPM3 VIP panels.
					}
					
					// store the config for external calls
					$this.data('options', options);
					
				});
			},
			
			/**
			 *  Permits access to VIP functionality in current view after successful registration
			 */
			completeRegistration : function(){
				return this.each(function() {
					var self = this;  // initialize a pointer to the context for the plugin
					var $this = $(this);  // create a quick-reference jQuery object with this DOM element
					$.clickSoldUtils('infoBoxClearHistory'); 
					$.clickSoldUtils('infoBoxClearOnRPMClosed');

					// load the "logout" panel into the VOW/VIP area and close the infobox
					helpers.vOWAdminGetLogout.call(self, function(){$(self).clickSoldUtils('infoBoxClose');});
					
					// if we're on the listing details page, make sure all VOW features are exposed
					helpers.initListingDetails();
					var options = helpers["loadOptions"].call(this);
					(options.onSuccessfulLogin || function() {}) ();
				});
			},
			
			/**
			 * Initializes the VOW Registration Infobox
			 */
			initSignIn : function(options){
				var self = this;
				return this.each(function() {
					// highlight the correct tab
					helpers.selectTab('#csVOWTabSignIn');
					
					// initiate the tabs
					helpers.initTabs.call(self);
				});
			},
			
			showVIPSignUp : function(opts){
				var options = helpers.loadOptions.call(this);
				$.extend(options, opts);
				$(this).data('options', options);
				helpers.showSignIn(options.vipAjaxTarget, function() {}, function(){alert("This information or feature is only available for registered users"); window.history.back();}, 'log');
			}
		}

		/**
		 * Methods that are considered "static" but require the presence of a VIP panel/dashboard to pull options from.
		 */
		var vipPanelMethods = {

			/** This function deletes a saved search
			  * 
			  * @param searchNum the unique ID for the saved search
			  */
			csVOWDeleteSavedSearch : function(searchNum) {
				var options = helpers.loadOptions.call(this);
			
				if(confirm('Are you sure you want to permanently delete this search?')){
					$.csVOWPanel('csVOWAjax', {
						type: "GET",
						url: options.vipAjaxTarget,
						data: "pathway=173&deleteSavedSearch=true&id="+searchNum,
						error: function(data, error){
							//alert("Error: displayListingStatistics(): " + error + " " + data);
						},
						success: function(data){
							// remove the saved search from the display
							$('#savedSearch'+searchNum).remove();
							if($(".cs-saved-searches-search").size() == 0)
								$('.cs-saved-searches-container').html('No searches found.');
							$.clickSoldUtils('infoBoxResize');
						}
					}, function(){}, function(){}, false);
				}
				return false;
			},

			/** Initializes the saved searches page
			  * 
			  */
			csVOWInitSavedSearches : function() {
				var options = helpers.loadOptions.call(this);
				// bind to the inputs
				$('#savedSearchesNotification', '#savedSearchesForm').change(function(){
					$.csVOWPanel('csVOWAjax', {
						type: "GET",
						dataType: "html",
						url: options.vipAjaxTarget,
						data: "pathway=173&savedSearchesToggleNotification=true&savedSearchesNotification="+this.checked,
						beforeSend: function(){
							$('#savedSearchesForm').block({message: "Saving..."});
						},
						error: function(data, error){
							alert("Error: " + error + " " + data);
						},
						success: function(data){
						},
						complete: function (XMLHttpRequest, textStatus) {
							setTimeout(function(){$('#savedSearchesForm').unblock();}, 500);
						}
					}, function(){}, function(){}, false);
					return false;
				});
			},

			/** This function saves a listing into the Favorite Listings
			  * 
			  * @param element elem that this save function is in
			  *
			  */
			csVOWSaveFavoriteListing : function(elem) {
				var options = helpers.loadOptions.call(this);
				
				// get the listnum
				var elemId = $(elem).attr("id");
				var listNum = elemId.substring(elemId.indexOf('_')+1, elemId.length);
				$.csVOWPanel('csVOWAjax', {
					type: "GET",
					url: options.ajaxTarget,
					data: "pathway=6&saveFavoriteListing=true&listingNumber="+listNum,
					error: function(data, error){
						alert("Error: displayListingStatistics(): " + error + " " + data);
					},
					beforeSend: function(){
						if($(elem).closest("#cboxLoadedContent").length == 0) $('#listingDetailsAddToFavorites_'+listNum).removeClass("cs-listing-details-button-save").addClass("cs-listing-details-button-loading");
					},
					success: function(data){},
					complete: function (XMLHttpRequest, textStatus) {
						// replace any applicable links on listing details
						$('#listingDetailsAddToFavorites_'+listNum).parent().html('<a href="#" class="cs-listing-details-button-delete" id="listingDetailsDeleteFromFavorites_'+listNum+'" onclick="return $.csVOWPanel(\'csVOWDeleteFavoriteListing\', '+listNum+', null);">Remove from Favorites</a>');

						// replace any applicable links on listing summaries
						$('#listingSummaryAddToFavorites_'+listNum).parent().html('<a id="listingSummaryDeleteFromFavorites_'+listNum+'" href="#" onclick="return $.csVOWPanel(\'csVOWDeleteFavoriteListing\', '+listNum+', null);" class="cs-listings-results-result-buttons-button-link cs-icon-save">Remove from favorites</a>');

					}
				}, function(){}, function(){
					// rollback the loading icon
					$('#listingDetailsAddToFavorites_'+listNum).removeClass("cs-listing-details-button-loading").addClass("cs-listing-details-button-save");
					}, true);
				return false;
			},

			/** This function deletes a favorite listing, updating any applicable areas on the page.
			  * 
			  * @param listNum Listing Number of listing to save
			  * @param callback callback to make once listing is deleted
			  *
			  */
			csVOWDeleteFavoriteListing : function(listNum, callback) {
				var options = helpers.loadOptions.call(this);
				
				$.csVOWPanel('csVOWAjax', {
					type: "GET",
					url: options.ajaxTarget,
					data: "pathway=6&deleteFavoriteListing=true&listingNumber="+listNum,
					error: function(data, error){
						alert("Error: displayListingStatistics(): " + error + " " + data);
					},
					beforeSend: function(){
						$('#listingDetailsDeleteFromFavorites_'+listNum).removeClass("cs-listing-details-button-delete").addClass("cs-listing-details-button-loading");
					},
					success: function(data){},
					complete: function (XMLHttpRequest, textStatus) {
						// run any applicable callbacks
						if(callback != null && typeof(callback) == "function")
							callback();

						// replace any applicable links on listing details
						$('#listingDetailsDeleteFromFavorites_'+listNum).parent().html('<a href="#" class="cs-listing-details-button-save" onclick="return $.csVOWPanel(\'csVOWSaveFavoriteListing\', this);" id="listingDetailsAddToFavorites_'+listNum+'">Add to Favorites</a>');

						// remove listing from the favorite listing panel if displayed
						$('#listingSummaryDeleteFromFavorites_'+listNum, '#csFavoriteListingsContent').closest(".cs-listings-results-result").remove();
						if($(".cs-listings-results-result", '#csFavoriteListingsContent').size() == 0)
							$('.cs-listing-results-container', '#csFavoriteListingsContent').html('No Listings Found.');
						$.clickSoldUtils('infoBoxResize');

						// replace any applicable links on listing summaries
						$('#listingSummaryDeleteFromFavorites_'+listNum).parent().html('<a id="listingSummaryAddToFavorites_'+listNum+'" href="#" onclick="return $.csVOWPanel(\'csVOWSaveFavoriteListing\', this);" class="cs-listings-results-result-buttons-button-link cs-icon-save">Add to Favorites</a>');
					}
				}, function(){}, function(){}, false);

				return false;
			},

			/** 
			  * initializes the favorite listings VOW panel
			  *
			  * @param modletId id of the modlet containing the favorite listings
			  * @param onSortCallback function to be run after the "sort" event has been run
			  *
			  */
			csVOWInitFavoriteListings: function(modletId, onSortCallback){
				$('#sortBy', '#csFavoriteListings').change(function(){
					helpers.reloadFavoriteListings(this.value, modletId, onSortCallback);
				});
				$('#favoriteListingsNotification', '#csFavoriteListings').change(function(){
					helpers.favoriteListingsToggleNotification(this.checked);
				});	
			},

			/** 
			  * runs market-analyzer forms if the city element is toggled.
			  *
			  */
			csVOWInitMarketAnalyzer: function(){
				$("#city", '#csMarketAnalyzer').change(function(){helpers.marketAnalyzerReloadNeighborhoods($(this).val());});
				$("#neigh, #prop", '#csMarketAnalyzer').change(function(){
					helpers.runMarketAnalyzer();
				});
			},
			/** Initializes the VOW Registration forms. Will highlight the selected tab. Works by
			  * attempting to initialize all three of the forms that will be present in the registration panel.
			  *
			  * @param activeTabId - the tab that needs to be displayed as active
			  */
			initRegistrationPanel : function(activeTabId){
				// highlight the correct tab
				helpers.selectTab('#'+activeTabId);

				var options = helpers["loadOptions"].call(this);
				
				// init the "register" form if available
				$('#csVOWRegisterForm').clickSoldUtils("csBindToForm", {
					updateDivId: "csVOWRegisterUpdateModule",
					loadingDivId: "csVOWRegisterLoadingOverlay",
					message: "Validating, please wait...",
					plugin: options.plugin,
					complete: function(){
						// bind to the confirmation form if it's present (necessary on successful vip signup).
						if($('#csVOWConfirmForm').size() > 0){
							// bind to registration form
							$('#csVOWConfirmForm').clickSoldUtils("csBindToForm", {
								updateDivId: "csVOWRegisterUpdateModule",
								loadingDivId: "csVOWRegisterLoadingOverlay",
								message: "Validating, please wait...",
								plugin: options.plugin,
								success: function(){
									$.clickSoldUtils('infoBoxResize');
								}
							});
							helpers.selectTab('#csVOWTabVerify');
						}
						
						//init the Terms of Service link
						$("#vIPTOSLink").click(function(){
							$("#csVOWTabTermsOfService").click();
						});

						$.clickSoldUtils('infoBoxResize');
					}
				});

				// init the "forgot password" form
				$('#csVOWForgotPasswordForm').clickSoldUtils("csBindToForm", {
					updateDivId: "csVOWForgotPasswordUpdateModule",
					loadingDivId: "csVOWForgotPasswordLoadingOverlay",
					plugin: options.plugin,
					message: "Validating, please wait..."
				});
				
				// init the "verify" form if available (RPM 3 Only)
				$('#csVOWConfirmForm').clickSoldUtils("csBindToForm", {
					updateDivId: "csVOWConfirmUpdateModule",
					loadingDivId: "csVOWConfirmLoadingOverlay",
					plugin: options.plugin,
					message: "Validating, please wait...",
					success: function(){
						$.clickSoldUtils('infoBoxResize');
					}
				});

				// init the "sign in" form if available
				$('#csVOWSignInForm').clickSoldUtils("csBindToForm", {
					updateDivId: "csVOWSignInModule",
					loadingDivId: "csVOWSignInOverlay",
					message: "Validating, please wait...",
					plugin: options.plugin,
					success: function(){
						// Re-bind the forgot password link.
						$("#csVOWForgotPasswordLink").click(function(){
							var options = helpers.loadOptions.call(this);
							return helpers.showForgotPassword(options.ajaxTarget, function(){$.clickSoldUtils('infoBoxResize');}, function(){}, "log");
						});
					},
					onRPMSuccessCallback: function(responseText){ 
						$.clickSoldUtils('infoBoxClearHistory'); 
						$.clickSoldUtils('infoBoxClearOnRPMClosed');
						$.clickSoldUtils('infoBoxClose', function(){helpers.vOWAdminGetLogout(function(){alert(SIGNEDINMESSAGE);});});
						(options.onSuccessfulLogin || function() {}) ();
					}
				});

				//init the Terms of Service link
				$("#vIPTOSLink").click(function(){
					$("#csVOWTabTermsOfService").click();
				});
				
				$("#csVOWForgotPasswordLink").click(function(){
					var options = helpers.loadOptions.call(this);
					return helpers.showForgotPassword(options.ajaxTarget, function(){$.clickSoldUtils('infoBoxResize');}, function(){}, "log");
				});
				
			},

			/** This function attempts to access a VOW feature of the site. If the environment does not
			  * permit this VOW feature to be accessible then false is returned, otherwise this function
			  * will run the AJAX call as it would a normal jQuery AJAX call and return true.
			  *
			  * @param options same options as for a normal AJAX call
			  * @param onSuccess a function to call if the VIP Registration/login does proceed
			  * @param onFailure a function to call if the VIP Registration/login does not proceed
			  * @param showRegistration boolean determining whether to show the registration on failure or not
			  * @return returns AJAX request
			  */
			csVOWAjax : function(ajaxOptions, onSuccess, onFailure, showRegistration){
				var self = this;
				
				if(csVOWAjaxActive)
					csVOWAjaxActive.abort();
				
				var VOWAjaxOptions = $.extend(true, {}, ajaxOptions);	// store the original functions
				var csVOWAjaxComplete = false;
				ajaxOptions.cache = false;

				ajaxOptions.success = function(data){
					var temp;
					if(ajaxOptions.dataType == "json"){
						if(data.VIPACCESSONLY == null)
							temp = "";
						else
							temp = data.VIPACCESSONLY;
					}
					if(ajaxOptions.dataType == "json" && temp == "VIPACCESSONLY" || 
					   ajaxOptions.dataType != "json" && $.trim(data).search(/^{\"VIPACCESSONLY\":\"VIPACCESSONLY\"}$/g) >= 0){
						// do signup, if successful re-run call
						if(showRegistration){
							var options = helpers.loadOptions.call(this);
							//saved AjaxRequest 
							$.extend(options, {onSuccessfulLogin: function() {$.ajax(ajaxOptions);}});
							$(this).data('options', options);
							onFailure = function () {alert("This information or feature is only available for registered users"); window.history.back();};
							helpers.showSignIn(options.vipAjaxTarget, function(){
								//helpers.initTabs(self);
							}, onFailure, "log");
							
							// if previously logged in, bring back login functionality to the dashboard
							if(options.plugin && $.trim($('.cs-vip-panel-status').html()) != SIGNEDOUTPANELHTML){
								// replace VOW panel login area
								$('.cs-vip-panel-status').html(SIGNEDOUTPANELHTML);
								helpers.vOWAdminInit();
							}
						}
					}else{
						// run normal success function
						VOWAjaxOptions.success(data);
						csVOWAjaxComplete = true;
					}
					return;
					
				};
				ajaxOptions.complete = function(XMLHttpRequest, textStatus){
					if(csVOWAjaxComplete){
						// run normal success function
						if(VOWAjaxOptions.complete != null && typeof(VOWAjaxOptions.complete) == "function")
							VOWAjaxOptions.complete(XMLHttpRequest, textStatus);
					}else{
						// run VOW login fail function
						if(VOWAjaxOptions.failComplete != null && typeof(VOWAjaxOptions.failComplete) == "function")
							VOWAjaxOptions.failComplete(XMLHttpRequest, textStatus);
					}

				};
				ajaxOptions.error = function(XMLHttpRequest, textStatus, errorThrown){
					alert("csVOWAjax error: " + textStatus + "\n" + errorThrown);
				};
		
				// run the AJAX function
				csVOWAjaxActive = $.ajax(ajaxOptions);
				return false;
			},
			csVOWInvokeAccountConfirm : function(email){
				var options = helpers.loadOptions.call(this);
				return helpers.showVerify(options.ajaxTarget, function(){
					$.clickSoldUtils('infoBoxResize');
					if(email != null){
						$("#email_addr").val(email);
					}
				}, function(){}, "log");
			},
			/**
			 *  Initializes the sorting drop down and email checkbox events
			 */
			initMarketWatchForm : function(){
				$("#sort").change(function(){
					//alert("SORT CHANGE");
					helpers.marketWatchSearch(this.value);
				});
				
				$("#email").change(function(){
					//alert("EMAIL CHECKED");
					helpers.marketWatchToggleNotification(this.checked);
				});
			},
			/**
			*  Legacy function to show VIP signup form via js call: $.showVIPRegistration();
			*/
			initLegacyShowVIPRegistration : function(){
				var options = helpers.loadOptions.call(this);
				return helpers.showRegistration(options.vipAjaxTarget, function(){}, function(){}, "log");
			}
		};

		// quickly check there we don't have duplicate names for functions between 'methods' and 'vipPanelMethods'.
		// this only for debugging, but shouldn't be removed.
		for (var methodName in methods) {
			for (var staticMethodName in vipPanelMethods)
				if (methodName == staticMethodName)
					alert("duplicate method names for: methods."+staticMethodName+" and vipPanelMethods."+staticMethodName);
		}

		/**
		 * For pure static methods that don't require an element or the presence of a VIP panel/dashboard.
		 */
		var staticMethods = {
			/**
			 * Used for VIP confirmations via email link FOR RPM3 ONLY
			 */
			initShowConfirmSuccessMessage : function(){
				var message = "<div class='cs-infobox-text-wide'>Thank you for registering. You can now access all restricted website services through the VOW bar on this website.</div>";
				$.clickSoldUtils('infoBoxCreate', {
					html : message,
					scrolling : false,
					cb_his_control : "skip",
					onComplete : function(){
						$.clickSoldUtils('infoBoxResize');
						//NOTE: Putting this in onClosed causes it to fire twice for some reason
						$(document).bind("cbox_closed", function(){
							$(document).unbind("cbox_closed");
							if($('.cs-vip-panel').length > 0) $('.cs-vip-panel').csVOWPanel('completeRegistration');
							else if($('#dashboard').length > 0) $('#dashboard').csVOWPanel('completeRegistration');
						});
					}
				});
			}
		};
		
		/** Private methods
		  *
		  */
		var helpers = {

			/** This function toggles whether the VIP recieves automatic favorite listing updates or not
			  * 
			  * @param notificationValue toggle value
			  */
			favoriteListingsToggleNotification : function(notificationValue){
				var options = helpers.loadOptions.call(this);
				$.csVOWPanel('csVOWAjax', {
					type: "GET",
					dataType: "html",
					url: options.vipAjaxTarget,
					data: "pathway=173&favoriteListingsToggleNotification=true&favoriteListingsNotification="+notificationValue,
					beforeSend: function(){
						$('#csFavoriteListings').block({message: "Saving..."});
					},
					error: function(data, error){
						alert("Error: favoriteListingsToggleNotification(): " + error + " " + data);
					},
					success: function(data){
					},
					complete: function (XMLHttpRequest, textStatus) {
						setTimeout(function(){$('#csFavoriteListings').unblock();}, 500);
					}
				}, function(){}, function(){}, false);

				return false;
			},

			/** This function searches the favorite listings and reloads the appropriate div on the page
			  * 
			  * @param sortBy sorting order
			  * @param onComplete function to be run after the results have been successfully resorted
			  */
			reloadFavoriteListings:function(sortBy, modletId, onComplete) {
				var options = helpers.loadOptions.call(this);
				
				$.csVOWPanel('csVOWAjax', {
					type: "GET",
					dataType: "html",
					url: options.vipAjaxTarget,
					data: "pathway=173&favoriteListingsSearch=true&sortBy="+sortBy+"&modletId=" + modletId,
					beforeSend: function(){
						$('#csFavoriteListingsLoadingOverlay').block({message: "Loading..."});
					},
					error: function(data, error){
						alert("Error: " + error + " " + data);
					},
					success: function(data){
						$('#csFavoriteListingsContent').html(data);
					},
					complete: function (XMLHttpRequest, textStatus) {
						if(onComplete != null && typeof(onComplete) == "function")
							onComplete();
						$('#csFavoriteListingsLoadingOverlay').unblock();
					}
				}, function(){}, function(){}, false);
				
				return false;
			},

			/**
			  * runs the market analyzer
			  */
			plotMarketAnalyzerResults:function(){
				try{
					$('#homeEvalContent').find('#daysOnMarket').clickSoldUtils("renderDOMGraph", daysOnMarket.MLSStatsDOMs)
					$('#homeEvalContent').find('#prices').clickSoldUtils("renderPricesGraph", listingPrices.MLSStatsPrices)
					$('#homeEvalContent').find('#listedVersusSold').clickSoldUtils("renderListedVersusSoldGraph", listedVersusSold.MLSStatsListedVersusSold);
				}catch(ex){}
			},
			/** 
			  * runs the market analyzer
			  *
			  * @param alreadyBlocked boolean indicating whether the view is already blocked from a preceding call.
			  */
			runMarketAnalyzer:function(alreadyBlocked){
				var options = helpers.loadOptions.call(this);
			
				$.csVOWPanel('csVOWAjax', {
					type: "GET",
					dataType: "html",
					url: options.vipAjaxTarget,
					data: "pathway=173&instantHomeEval=true&reload_stats=true&city=" + $("#city").val() + "&neigh=" + $("#neigh").val() + "&prop=" + $("#prop").val(),
					beforeSend: function(){
						if(!alreadyBlocked)
							$('#homeEvalResults').block({message: "Loading..."});
					},
					error: function(data, error){
						alert("Error: saveVIPMarketWatchEmailSetting(): " + error);
					},
					success: function(data){
						$("#homeEvalResults").html(data);
					},
					complete: function(){
						setTimeout(function(){$('#homeEvalResults').unblock();}, 500);
						helpers.plotMarketAnalyzerResults();
					}
				}, function(){}, function(){}, false);
			},
			/** 
			  * re-populates the market-analyzer forms if the city element is toggled.
			  *
			  * @param cValue cValue the string value of the newly selected city
			  */
			marketAnalyzerReloadNeighborhoods:function(cValue){
				var options = helpers.loadOptions.call(this);
				
				$.csVOWPanel('csVOWAjax', {
					type: "GET",
					dataType: "html",
					url: options.vipAjaxTarget,
					data: "pathway=173&instantHomeEval=true&reload_neigh=true&city=" + cValue,
					beforeSend: function(){
						$('#homeEvalResults').block({message: "Loading..."});
					},
					error: function(data, error){
						alert("Error: saveVIPMarketWatchEmailSetting(): " + error);
					},
					success: function(data){
						// load the new drop-down
						$("#neigh_list").html(data);
						
						// re-bind the change event
						$("#neigh", '#csMarketAnalyzer').change(function(){
							helpers.runMarketAnalyzer();
						});
						
						// run the market analyzer
						helpers.runMarketAnalyzer(true);
					}
				}, function(){}, function(){}, false);
			},

			/** If logged in successfully, will fire events to enable/show VOW-only features
			  * in the listing details view
			  *
			  */
			initListingDetails : function(){  // throws exception
				var options = helpers.loadOptions.call(this);
			
				$("#listing_listingNumber").each(function(){
					$.csVOWPanel('csVOWAjax', {
						type: "GET",
						dataType: "text",
						url: options.ajaxTarget,
						data: "pathway=6&checkFavoriteListing=true&listingNumber="+$(this).val(),
						hideVIPRegistration: true,
						error: function(data, error){
							alert("Error: $.checkFavoriteListing(): " + error + " " + data);
						},
						success: function(data){
							if(data.indexOf("SUCCESS") > -1){
								$("#saveFavoriteListingLink_"+listNum).parent().html('Saved. (<a href="#" id="deleteFavoriteListingLink_'+listNum+'" onclick="return $.csVOWPanel(\'csVOWDeleteFavoriteListing\', '+listNum+', null);">remove</a>)');
							}
						},
						complete: function (XMLHttpRequest, textStatus) {
							vIPAjaxRequest = null;
						}
					}, function(){}, function(){}, false);

					return false;
				});
			},

			/** Makes an AJAX call to get the "logout" form (after a user has successfully signed in).
			  * Will install the "logout" form on all VOW panels in the page.
			  *
			  * @param onSuccess function to be called if the logout form is successfully loaded
			  *
			  */
			vOWAdminGetLogout:function(onSuccess){  // throws exception
				// replace VIP login with sign-out content
				var options = helpers.loadOptions.call(this);
				
				$.ajax({
					type: "GET",
					dataType: "text",
					url: options.vipAjaxTarget,
					data: "pathway=168&vipSignupLogin=true",
					error: function(data, error){
						alert("Error: completeVIPRegistration(): " + error);
					},
					success: function(data){
						helpers.vOWAdminFinishLogin(data);
						$('#dashboard_login').html(data);	// support for RPM3 VIP panels.

						// run any success functions
						if(onSuccess != null && typeof(onSuccess) == "function")
							onSuccess();
					},
					complete: function (XMLHttpRequest, textStatus) {
						helpers.bindToSignOut();
					}
				});
			},
			
			/** Fills the admin section of the VOW panel with the login response from the server
			  *
			  * @param data data to place in the vOWAdmin area
			  *
			  */
			vOWAdminFinishLogin:function(data){  // throws exception
				$('.cs-vip-panel-status').html(data);
			},

			/** If logged in successfully, will fire events to enable/show VOW-only features
			  * in the listing details view
			  *
			  */
			vOWAdminInit:function(){
				// assign registration click event if not logged in
				$("#csVOWRegister").click(function(){
					var options = helpers.loadOptions.call(this);
					return helpers.showRegistration(options.vipAjaxTarget, function(){$.clickSoldUtils('infoBoxResize');}, function(){}, "log");
				});

				// assign registration click event
				$("#csVOWSignIn").click(function(){
					var options = helpers.loadOptions.call(this);
					return helpers.showSignIn(options.vipAjaxTarget, function(){$.clickSoldUtils('infoBoxResize');}, function(){}, "log");
				});
			},

			/**
			  * Initializes the legacy RPM3 panel with required.
			  *
			  */
			vIPPanelLoginInit:function(){  // throws exception
				$("#vipDashboardRegister").click(function(){
					var options = helpers.loadOptions.call(this);
					return helpers.showRegistration(options.vipAjaxTarget, function(){}, function(){}, "log");
				});
				
				$("#vipDashboardConfirm").click(function(){
					var options = helpers.loadOptions.call(this);
					return helpers.showVerify(options.ajaxTarget, function(){}, function(){}, "log");
				});

				$("#vipDashboardForgot").click(function(){
					var options = helpers.loadOptions.call(this);
					return helpers.showForgotPassword(options.ajaxTarget, function(){}, function(){}, "log");
				});

				// bind to the form's submit event if present
				$("#loginForm", "#dashboard").submit(function() {
					var options = helpers.loadOptions.call(this);
					$.ajax({
						type: "GET",
						dataType: "text",
						url: options.vipAjaxTarget,
						cache: false,
						data: $('#'+this.id+' input').fieldSerialize() + "&t=" + Date(),
						beforeSend: function (XMLHttpRequest) {},
						error: function(data, error){
							alert("Error: helpers.vIPPanelLoginInit(): " + error);
						},
						success: function(data){
							// legacy support for the RPM3 VIP panel
							// search the string for a relocation command. If not found it's a client logging in
							if(data.indexOf("window.l") >= 0)
								eval(data);
							else
								$('#dashboard_login').html(data);

							// complete the VOW login
							if(!(data.indexOf("loginForm") >= 0)){
								helpers.vOWAdminFinishLogin(data);
								alert(SIGNEDINMESSAGE);
							}
						},
						complete: function (XMLHttpRequest, textStatus) {
							// re-init in case the login failed
							helpers.vIPPanelLoginInit();
							
							// bind to the logout button in case login succeeded
							helpers.bindToSignOut();

							// if user has not logged into the back office, then initialize any listing details
							$('.csVOWLogout', '#dashboard_login').each(function(){
								helpers.initListingDetails();
							});
						}
					});
		
					return false;
				});
		
				$("#username", "#loginForm").one("focus", function(){
					$("#username", "#loginForm").attr("value", "");
				});
				
				$("#password", "#loginForm").one("focusin", function(){
					// check if this field is already in error state - if so, use the same class
					$("#password", "#loginForm").replaceWith('<input type="password" class="'+$("#password", "#loginForm").attr("class")+'" value="" id="password" name="password">');
					setTimeout(function(){
						$("#password", "#loginForm").focus();  //hack to get it to actually focus in IE 7/8
					}, 0);
				});
			},

			/**
			  * Static function that binds a click event to the to all Sign Out links in a page. 
			  * Has legacy support for the RPM3 VIP panel.
			  *
			  */
			bindToSignOut:function(){  // throws exception
				// bind a logout event
				$('.csVOWLogout').click(function(){
					var options = helpers.loadOptions.call(this);
					if(confirm(SIGNOUTCONFIRMMESSAGE)){
						$.ajax({
							type: "GET",
							dataType: "html",
							cache: false,
							url: options.ajaxTarget,
							data: "pathway=187&t=" + Date(),
							error: function(data, error){
								alert("Error: helpers.bindToSignOut(): " + error);
							},
							success: function(data){
								// replace VOW panel login area
								$('.cs-vip-panel-status').html(SIGNEDOUTPANELHTML);
								helpers.vOWAdminInit();

								$('#dashboard_login').html(data);	// support for legacy RPM3 VIP panel
							},
							complete: function (XMLHttpRequest, textStatus){
								// rebind everything
								helpers.vIPPanelLoginInit();
								alert(SIGNEDOUTMESSAGE);
							}
						});
					}
					return false;
				});
			},

			/**
			  * Highlights the tab with the specified ID
			  *
			  * @param id - id of the tab we're looking to highlight
			  */
			selectTab:function(tabId){  // throws exception
				// reset all tabs
				$(".cs-tabs-tab-active", '#csVOWInfoWindow').addClass("cs-tabs-tab").removeClass("cs-tabs-tab-active");
				
				// highlight the correct tab
				$(tabId, '#csVOWInfoWindow').parent().addClass("cs-tabs-tab-active").removeClass("cs-tabs-tab");
			},
				
			/**
			  * Returns the options object saved in the dashboard element
			  *
			  * @param options - options sent from running the plugin (if available)
			  */
			loadOptions:function(opts){  // throws exception
				var options = null;
				
				if($(".cs-vip-panel").length > 0){  //Try to get options from CS dashboard
					options = $(".cs-vip-panel").data("options");
				}else if($("#dashboard").length > 0){  //Try to get options from RPM3 dashboard
					options = $("#dashboard").data("options");
				}else{
					options = $(this).data('options'); // attempt to extract any stored configs from this DOM element
				}
				
				// if config is still null, continue.
				if(options == null || typeof options == "undefined"){
					if(opts != null && typeof opts != "undefined"){
						options = {};
						$.extend(options, opts);
					}else{
						return null;
					}
				}
								
				return options;
			},

			/** Generic "show registration feature" function used throughout the registration process.
			  *
			  * @param onSuccess function to be called once the user has completed VIP registration
			  * @param onFailure function to be called if the user does not complete VIP registration
			  * @param history_control - if set to "skip" infoboxes opened by this call won't be logged in the history.
			  */
			showRegistrationFeature : function(resourceUrl, onSuccess, onFailure, history_control){
				var self = this;
				//Show the registration panel
				$.clickSoldUtils('infoBoxCreate', {
					href: resourceUrl,
					scrolling: false,
					onComplete: function(){
						$.clickSoldUtils('infoBoxResize');
						if(onSuccess != null && typeof(onSuccess) == "function") onSuccess();
						helpers.initTabs.call(self);
					},
					onRPMClosed: function(){
						if(onFailure != null && typeof(onFailure) == "function") onFailure();
					},
					cb_his_control: history_control
				});

				return false;
			},

			/** Shows the registation panel
			  *
			  * @param onSuccess function to be called once the user has completed VIP registration
			  * @param onFailure function to be called if the user does not complete VIP registration
			  * @param history_control - if set to "skip" infoboxes opened by this call won't be logged in the history. Default is to log them in the history.
			  */
			showRegistration : function(vipAjaxTarget, onSuccess, onFailure, history_control){
				return helpers.showRegistrationFeature(vipAjaxTarget + "?pathway=168&loadSignupForm=true", onSuccess, onFailure, history_control);
			},

			/** Shows the sign-in panel
			  *
			  * @param onSuccess function to be called once the user has completed VIP registration
			  * @param onFailure function to be called if the user does not complete VIP registration
			  * @param history_control - if set to "skip" infoboxes opened by this call won't be logged in the history. Default is to log them in the history.
			  */
			showSignIn : function(vipAjaxTarget, onSuccess, onFailure, history_control){
				return helpers.showRegistrationFeature(vipAjaxTarget + "?pathway=168&loadSignInForm=true", onSuccess, onFailure, history_control);
			},
			/** Shows the verify panel
			  *
			  * @param onSuccess function to be called once the user has completed VIP registration
			  * @param onFailure function to be called if the user does not complete VIP registration
			  * @param history_control - if set to "skip" infoboxes opened by this call won't be logged in the history. Default is to log them in the history.
			  */
			showVerify : function(ajaxTarget, onSuccess, onFailure, history_control){
				return helpers.showRegistrationFeature(ajaxTarget + "?pathway=101&loadVIPConfirm=true", onSuccess, onFailure, history_control);
			},
			/** Shows the forgot password panel
			  *
			  * @param onSuccess function to be called once the user has completed VIP registration
			  * @param onFailure function to be called if the user does not complete VIP registration
			  * @param history_control - if set to "skip" infoboxes opened by this call won't be logged in the history. Default is to log them in the history.
			  */
			showForgotPassword : function(ajaxTarget, onSuccess, onFailure, history_control){
				return helpers.showRegistrationFeature(ajaxTarget + "?pathway=101", onSuccess, onFailure, history_control);
			},
			
			showTOS : function(vipAjaxTarget, onSuccess, onFailure, history_control){
				return helpers.showRegistrationFeature(vipAjaxTarget + "?pathway=168&loadTOS=true", onSuccess, onFailure, history_control);
			},

			/**
			  * Initializes the tabs of the VOW popup window
			  *
			  * @param options - the options for this plugin
			  */
			initTabs:function(){
				//alert("Init Tabs!?!");
			
				var options = helpers.loadOptions.call(this);
				
				$.clickSoldUtils("$infoBox", "#csVOWTabRegister").unbind("click").bind("click", function(){
					helpers.saveRegistrationState();
					return helpers.showRegistration(options.vipAjaxTarget, function(){$.clickSoldUtils('infoBoxResize'); helpers.selectTab('#csVOWTabRegister'); helpers.loadRegistrationState();}, function(){}, "skip");
				});
				$.clickSoldUtils("$infoBox", "#csVOWTabVerify").unbind("click").bind("click", function(){
					helpers.saveRegistrationState();
					return helpers.showVerify(options.ajaxTarget, function(){$.clickSoldUtils('infoBoxResize'); helpers.selectTab('#csVOWTabVerify');}, function(){}, "skip");					
				});
				$.clickSoldUtils("$infoBox", "#csVOWTabTermsOfService").unbind("click").bind("click", function(){
					helpers.saveRegistrationState();
					return helpers.showTOS(options.vipAjaxTarget, function(){$.clickSoldUtils('infoBoxResize'); helpers.selectTab('#csVOWTabTermsOfService');}, function(){}, "skip");					
				});
				$.clickSoldUtils("$infoBox", "#csVOWTabSignIn").unbind("click").bind("click", function(){
					helpers.saveRegistrationState();
					return helpers.showSignIn(options.vipAjaxTarget, function(){$.clickSoldUtils('infoBoxResize'); helpers.selectTab('#csVOWTabSignIn');}, function(){}, "skip");
				});
			},
			
			/**
			 *  Saves the state of the registration for for reuse i.e. when navigating to the terms of service via
			 *  link.
			 */
			saveRegistrationState : function(){
				if($("#csVOWTabRegister").parent("li").hasClass("cs-tabs-tab-active")){
					var regFormData = {};
					regFormData.firstName  = $("#firstName").val();
					regFormData.lastName   = $("#lastName").val();
					regFormData.email_addr = $("#email_addr").val();
					regFormData.home_phone = $("#home_phone").val();
					$("#cboxContent").data("regForm", regFormData);
				}
			},
			
			/**
			 *  Loads the state of the registration form when navigating to it from another tab item.
			 */
			loadRegistrationState : function(){
				var regFormData = $("#cboxContent").data("regForm");
				if(typeof regFormData != "undefined" && regFormData != null){
					$("#firstName").val(regFormData.firstName);
					$("#lastName").val(regFormData.lastName);
					$("#email_addr").val(regFormData.email_addr);
					$("#home_phone").val(regFormData.home_phone);
				}
			},
			
			/** This function toggles whether the VIP recieves automatic Market Watch updates or not
			  * 
			  * @param notificationValue toggle value
			  */
			marketWatchToggleNotification : function(notificationValue){
				$.csVOWPanel('csVOWAjax', {
					type: "GET",
					dataType: "html",
					url: "vIPDashboard",
					data: "pathway=173&marketWatch=true&email="+notificationValue+"&sort="+$("#sort").val(),
					beforeSend: function(){
						$('#marketWatchSearch').block({message: "Saving..."});
					},
					error: function(data, error){
						alert("Error: saveVIPMarketWatchEmailSetting(): " + error);
					},
					success: function(data){
						//Show save message here
					},
					complete: function(){
						setTimeout(function(){$('#marketWatchSearch').unblock();}, 500);
					}
				}, function(){}, function(){resetDashboard();}, true);
			},
			
			/** This function searches the Market Watch and reloads the appropriate div on the page
			  * 
			  * @param sortBy sorting order
			  */
			marketWatchSearch : function(sortBy){
				//alert("Sort by: " + sortBy);
				$.csVOWPanel('csVOWAjax', {
					type: "GET",
					dataType: "html",
					url: "vIPDashboard",
					data: "pathway=173&marketWatch=true&reload=1&sort="+sortBy,
					beforeSend: function(){
						$('#marketWatchSearch').block({message: "Searching..."});
					},
					error: function(data, error){
						alert("Error: changeVIPMarketWatchSorting(): " + error);
					},
					success: function(data){
						// load content
						$("#marketWatchResults").html(data);
					},
					complete: function(){
						setTimeout(function(){$('#marketWatchSearch').unblock();}, 500);
					}
				}, function(){}, function(){resetDashboard();}, true);
			}
			
		}
		
		// The meat of the matter - where everything is called
		if(methods[method]){
			if(helpers["loadOptions"].call(this) == null) {
				var methodQueue = new Array();
				if( typeof this.data("methodQueue") != "undefined" ) methodQueue = this.data("methodQueue");
				methodQueue.push([method, Array.prototype.slice.call( arguments, 1 )]);				
				this.data("methodQueue", methodQueue);
				return false;
		
			} else return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		}else if(vipPanelMethods[method]) {
			if(helpers["loadOptions"].call(this) == null){
				var vpMethodQueue = new Array();
				if( typeof this.data("vpMethodQueue") != "undefined" ) vpMethodQueue = this.data("vpMethodQueue");
				vpMethodQueue.push([method, Array.prototype.slice.call( arguments, 1 )]);				
				this.data("vpMethodQueue", vpMethodQueue);
				return false;				
		
			} else return vipPanelMethods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		}else if(staticMethods[method]){
			return staticMethods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		}else if(typeof method === "object"){
			var init = methods.init.apply(this, arguments);
			if( typeof this.data("methodQueue") != "undefined" ) {
				var methodQueue = this.data("methodQueue");
				while(methodQueue.length > 0){
					var m = methodQueue.shift();
					methods[m[0]].apply(this, m[1]);
				}
			}
			if( typeof this.data("vpMethodQueue") != "undefined" ) {
				var vpMethodQueue = this.data("vpMethodQueue");
				while(vpMethodQueue.length > 0){
					var m = vpMethodQueue.shift();
					methods[m[0]].apply(this, m[1]);
				}
			}

			return init;
		}else{
			alert("Error! Method does not exist: " + method);
			$.error("Method " + method + " doesn't exist on jQuery.VIP");
		}
	}
	
	// Legacy Functions
	$.showVIPRegistration = function(){
		$.csVOWPanel("initLegacyShowVIPRegistration");
		return false;
	}
	
	// Utility Functions
	function resetDashboard(){
		// remove highlighting
		$("#vipMenu li a.over").each(function(){
			$(this).removeClass('over');
		});
		self.openDashboardElement = null;
	}
	
})(jQuery);
