//  Display "How To" window if this is the user's first visit.
function showHowToWindow() {
	var ALREADY_VISITED_COOKIE_NAME = "howToPopupWasViewed";
	var alreadyVisitedCookie = readCookie(ALREADY_VISITED_COOKIE_NAME);
	if ( alreadyVisitedCookie == null || alreadyVisitedCookie == undefined) {
		createCookie(ALREADY_VISITED_COOKIE_NAME,"true",365);
		toggleLayerBlock('modalWindow', true);
		toggleLayerBlock('howToUseModalParent', true);
	}
}

//  Close the "How to use the tours by neighborhood page
function closeHowToPopup() {
	toggleLayerBlock('modalWindow', false);
	toggleLayerBlock("howToUseModalParent", false);
}

//  Search engine spiders don't call javascript so the first page of Journeys for this City is loaded on the server side
//  so the spiders have something to index. The isFirstLoad var prevents re-loading this initial set of journeys.
var isJourneysPreloaded;  
var journeyType = "All Journeys";
var isDisplayAjaxLoader = true; //  Allows ajax responders to be disabled if necessary

// Our function that initializes when the page is finished loading.
function initFilteringSystem(initialJourneyType,cityId) {

	//  First display "How To" window if necessary
	showHowToWindow();

	journeyType = initialJourneyType;
	
   	// initialize the DHTML History framework
   	dhtmlHistory.initialize();

   	// add ourselves as a DHTML History listener
   	dhtmlHistory.addListener(handleHistoryChange);

	//  Load the neighborhoods into the Google Map
	loadMapNeighborhoods(cityId); 

   	// Determine what our initial location is by retrieving it from the browser's
   	// location (after the # in the URL)...may have been passed via a stored bookmark
   	var currentLocation = dhtmlHistory.getCurrentLocation();
	if ( currentLocation != "") {
		//  The journeys are being filtered so the pre-loaded content from the server is probably not valid.
		//  This can happen with saved browser favorites or when a user clicks a neighborhood or category in the Journey descriptions.
		isJourneysPreloaded = false;
	} else {
		//  The pre-loaded journeys are valid so don't load again.
		isJourneysPreloaded = true;
	}

	//  Now update the filtered journeys pager
	convertToStoredLocation(currentLocation);
}

// 	Handles history (back/forward) events from dhtmlHistory for Ajax 
function handleHistoryChange(newLocation, historyData) 
{
	//  Addresses bug in Safari (1/2/3/?) that causes a HistoryChange event to be called when the 
	//  page first loads and results in a continuous looping of page updates.
	if (BrowserDetect.browser == "Safari") {
		if (!dhtmlHistory.isFirstLoad()) {
			convertToStoredLocation(newLocation) ;
		}
	} else {
		convertToStoredLocation(newLocation) ;
	}
}

// 	Moves the filtered Journeys pager to the new page offset.
//  Offset will be used by <pg:pager> when displaying correct page.  
//	Assumed to be zero offset if not present
var pgOffset = 0;
function showPagerOffset(offset, isScrollToTop) 
{
	pgOffset = offset;  //  track the page offset for possible updating of neighborhoods and categories
	processNewFilterSelection();

	// And lastly, scroll the webpage to the top if requested.
	// Typically requested in case the user clicked the bottom pager navigation buttons
	if ( isScrollToTop == "true") {
		window.scroll(0,0); // horizontal and vertical scroll targets
	}
}

//  This function is called when the user clicks to update the currently 
//	displayed Journeys either by clicking a Category, selecting a 
//	neighborhoods, or clicking the back/next Pager buttons.
//
//  This method will first store the new settings into dhtmlHistory and then
//	call the AJAx methods to update the page.
function processNewFilterSelection() 
{
   	var modifiedLocation = getLocationStr();

   	var historyData = new Object(); // currently store nothing in history
	dhtmlHistory.add(modifiedLocation, historyData);
   	updatePager();
}

// 	Loads updated journey selection from the server
function updatePager() 
{
	var params = getParams();
	
	// 	Updates the left-side Neighborhood and Category filters
	new Ajax.Request(
		"ajaxGetFilteredNeighborhoodsAndCategories.do", 
		{
	 		onSuccess  : loadOtherFiltersSuccessful,
	 		onFailure  : loadOtherFiltersFailed,
			parameters : params
		}
	);
	
	if ( isJourneysPreloaded ) {
		//  The journey count by neighborhood and category should updated (above) but 
		//	no need to update the first set of Journeys.  They were pre-loaded on the server
		//  side so the search spiders had something to crawl.
		isJourneysPreloaded = false;

		//  Now prepare the Ajax responders to display the loading image
		Ajax.Responders.register(
			{ 
				onCreate : function() {
						if(isDisplayAjaxLoader) {
							displayRelativeAjaxWarning("ajaxLoadingPanel", "Results will appear below", "Updating Selected Tours")
						}}, 
				onComplete : function() {
						if(isDisplayAjaxLoader) {
							hideAjaxWarning("ajaxLoadingPanel")
						}}
			}
		);
	} else {
		//  Replace current Journeys with ajax loader.  This loader will then be cleared when the journeys are loaded and replace the <div>'s contents.
		displayRelativeAjaxWarning("filteredJourneysPager", "Loading Tours");

		// 	Updates the list of filtered journeys per user request.
		new Ajax.Request(
			"ajaxGetFilteredJourneysPage.do", 
			{
		 		onSuccess  : loadFilteredJourneysSuccessful,
		 		onFailure  : loadFilteredJourneysFailed,
				parameters : params
			}
		);
	}
} 

//  Creates the param String for Ajax calls
function getParams() 
{
	//  First validate that we are dealing with a real number
	if (pgOffset != parseInt(pgOffset))
		pgOffset = 0;

	var params = Form.serialize($("filteredJourneysForm"));

	// Now add non-Form params
	params  = params + "&selectedDate=" + $("singleDateSpan").innerHTML // Selected date if any
				+ "&pagerOffset=" + pgOffset        // The <pg:pager> offset
				+ "&journeyType=" + journeyType;  // All, Guided, ....
	return params;
} 

var journeyTypeForPager = ""; // type of tour for results String in <Pager>
function loadFilteredJourneysSuccessful(xhrObject)
{
	//  First update the pager's page
	$("filteredJourneysPager").innerHTML = xhrObject.responseText;

	//  Next update the results text with the selected date & neighborhood 
	var dateRB = document.filteredJourneysForm.dateRange;	
	var selectedDate = getSelectedDate();
	if ( selectedDate == null)
		selectedDate = "all dates";

	var neighborhoodRBs   = document.filteredJourneysForm.neighborhoods;	
	var neighborhood = getSelectedRadioButton(neighborhoodRBs).id;

	var categoryRBs = document.filteredJourneysForm.categories;	
	var category 	= getSelectedRadioButton(categoryRBs).id;
	if ( category == "All Categories")
		category = ""; 
	
	// Finally create the new results String
	var index = $("resultsPageResultsStr").innerHTML.indexOf("tour");
	$("resultsPageResultsStr").innerHTML = $("resultsPageResultsStr").innerHTML.substring(0,index) 
										   + journeyTypeForPager
										   + category + " "
										   + $("resultsPageResultsStr").innerHTML.substring(index,$("resultsPageResultsStr").innerHTML.length) 
										   + " in " + neighborhood + " for " + selectedDate;
}
	
function loadFilteredJourneysFailed(xhrObject)
{
	$("filteredJourneysPager").innerHTML = "Unable to load tour due to server error.";
	alert("An has error occurred while processing your request.\n\nPlease refresh your page and try again.");
}

function loadOtherFiltersSuccessful(xhrObject)
{
	if ( xhrObject.responseText.indexOf("filteredJourneyCounts") >= 0) {
	 	var response = eval('('+xhrObject.responseText+')');
		appendJourneyCountToCheckboxes(response.filteredJourneyCounts.neighborhoods, document.filteredJourneysForm.neighborhoods)
		appendJourneyCountToCheckboxes(response.filteredJourneyCounts.categories, document.filteredJourneysForm.categories)
	} else
		loadOtherFiltersFailed(xhrObject);
}
	
function loadOtherFiltersFailed(xhrObject)
{
	$("otherJourneyFilters").innerHTML = "Unable to load tour filters to server error.";
	alert("An has error occurred while processing your request.\n\nPlease refresh your page and try again.");
}

//  Hide the neighborhood Checkbox links
function hideNeighborhoodLinks() {
	toggleLayerBlock('activeNeighborhoodsSelector', false);
	toggleLayerBlock('hideNeighborhoodsLink', false);
	toggleLayerBlock('showNeighborhoodsLink', true);
}

//  Show the neighborhood Checkbox links
function showNeighborhoodLinks() {
	toggleLayerBlock('showNeighborhoodsLink', false);
	toggleLayerBlock('activeNeighborhoodsSelector', true);
	toggleLayerBlock('hideNeighborhoodsLink', true);
}

// 	Creates a String of the format:  "offset:0;date:5-5-08;n:0;c:1-2-3-4"
//	If the date is absent, then a value of "All Dates" should be assumed
//	Return a String containing info about the currently selected date, neighborhoods, & categories
function getLocationStr() 
{
	// First set the offset
	var location = "offset:" + pgOffset;
	
	//  Set the date
	var selectedDate = getSelectedDate();
	if ( selectedDate != null)
		location += ";date:" + selectedDate;
	
	//  Set neighborhood selections
	var neighborhoodRB   = document.filteredJourneysForm.neighborhoods;	
	var selNeighborhoods = getSelectedRadioButton(neighborhoodRB);
	if ( selNeighborhoods.length == 1 && selNeighborhoods[0] == "0") //  All neighborhoods selected
		location += ";n:0";
	else {
		location += ";n:" + selNeighborhoods[0];
		for ( var i = 1; i < selNeighborhoods.length; i++) {
			location += "-" + selNeighborhoods[i];
		}
	}

	//  Set journey category selections
	var categoryCB    = document.filteredJourneysForm.categories;	
	var selCategories = getSelectedCheckboxes(categoryCB);
	location += ";c:" + selCategories[0].value;
	for ( var i = 1; i < selCategories.length; i++) {
		location += "-" + selCategories[i].value;
	}

	//  Set selected journey type
	location += ";jType:" + journeyType;

	return location;
}

// 	Uses the provided location String to set the selected date, neighborhoods, & categories.
// 	Location String must be of the format:  "offset:0;date:5-5-08;n:0;c:1-2-3-4"
//	If the date is absent, then a value of "All Dates" will be assumed
function convertToStoredLocation(locationStr) 
{
		//  Get pager offset
		pgOffset = 0; // start with default in case this is the original start page
		var startIndex = locationStr.indexOf("offset");
		var endIndex   = locationStr.indexOf(";", startIndex);
		if ( startIndex >= 0) {
			if ( endIndex < 0)
				endIndex   = locationStr.length;
			pgOffset = locationStr.substring(startIndex+7,endIndex);
		}

		//  Get date
		startIndex = locationStr.indexOf("date");
		if ( startIndex >= 0) {
			endIndex   = locationStr.indexOf(";", startIndex);
			if ( endIndex < 0)
				endIndex   = locationStr.length;

			var date = locationStr.substring(startIndex+5,endIndex);
			date = replaceAll(date,"-","/");
			$("singleDateSpan").innerHTML = date;
			var dateRadioButtons = document.filteredJourneysForm.dateRange;
			toggleInput(dateRadioButtons, "Single Date", true); 
		} else {
			var dateRadioButtons = document.filteredJourneysForm.dateRange;
			toggleInput(dateRadioButtons, "All Dates", true); 
		}
		
		//  Get neighborhoods
		var neighborhood;
		startIndex = locationStr.indexOf("n:");
		if ( startIndex >= 0) {
			endIndex   = locationStr.indexOf(";", startIndex);
			if ( endIndex < 0)
				endIndex   = locationStr.length;
			var neighborhoodsStr = locationStr.substring(startIndex+2,endIndex);
			neighborhood = parseEncodedString(neighborhoodsStr); // returns array even though we should always have a single sel neighborhood
		}
		if ( neighborhood == null || neighborhood.length == 0 || typeof(neighborhood[0]) == "undefined") {
			neighborhood = new Array();
			neighborhood[0] = "0";
		}
		var neighborhoodRBs   = document.filteredJourneysForm.neighborhoods;	
		selectRadioButton(neighborhoodRBs, neighborhood[0]);

		//  Get categories
		var categoryArr = null;
		startIndex = locationStr.indexOf("c:");
		if ( startIndex >= 0) {
			endIndex   = locationStr.indexOf(";", startIndex);
			if ( endIndex < 0)
				endIndex   = locationStr.length;
			var categoriesStr = locationStr.substring(startIndex+2,endIndex);
			categoryArr    = parseEncodedString(categoriesStr);
		}
		if ( categoryArr == null || categoryArr.length == 0 || typeof(categoryArr[0]) == "undefined") {
			categoryArr = new Array();
			categoryArr[0] = "All Categories";
		}
		var categoryCB    = document.filteredJourneysForm.categories;	
		selectCheckboxes(categoryCB, categoryArr);
		
		// Set selected Journey type
		journeyType = "All Journeys"; // provide a default
		startIndex = locationStr.indexOf("jType:");
		if ( startIndex >= 0) {
			endIndex   = locationStr.indexOf(";", startIndex);	
			if ( endIndex < 0)
				endIndex   = locationStr.length;
			journeyType = locationStr.substring(startIndex+6,endIndex);
		}

		//  Validate journey type was provided
		if ( journeyType != "All Journeys" && journeyType != "Guided" && journeyType != "Multimedia" && journeyType != "Self-Guided") {
			 //  journeyType must be equal to one of JourneyTypes.TYPES
			journeyType = "All Journeys";
		}

		//  Finally determine which tab to display
		var tab = "allJourneysTab";  //  A little redundant but this is the default
		if ( journeyType == "All Journeys") //  Journey types based on JourneyTypes.TYPES
			tab = "allJourneysTab";
		else if ( journeyType == "Guided")
			tab = "guidedJourneysTab";
		else if ( journeyType == "Multimedia")
			tab = "mediaJourneysTab";
		else if ( journeyType == "Self-Guided")
			tab = "selfGuidedJourneysTab";

		updateSelectedTab(tab)
		updatePager();
}

//  Takes a String of form x-y-z and returns an array of {x,y,z}
function parseEncodedString(encodedStr)  
{
	var arr   = new Array();
	var index = 0;
	while (encodedStr.length > 0) {
		var endIndex = encodedStr.indexOf("-");
		if ( endIndex < 0) {
			arr[index] = encodedStr.substring(0,encodedStr.length);
			encodedStr = "";
		} else {
			arr[index] = encodedStr.substring(0,endIndex);
			encodedStr = encodedStr.substring(endIndex+1,encodedStr.length);
		}	
		index++;
	}
	return arr;
}

//  Appends the # of journeys for each neighborhood and category to the end of the checkbox name
function appendJourneyCountToCheckboxes(filteredValues, checkboxes) {
    for (var i = 0; i < checkboxes.length; i++)
	{
		var isFound = false;
	    for (var j = 0; j < filteredValues.length; j++)
	    {
	    	var name = filteredValues[j];
	    	j++; // names & counts alternate
	    	var count = filteredValues[j];
	    	if ( checkboxes[i].id == name) {
			 	$("cbLabel_"+name).innerHTML = name + " <span class=\"ajLogoText\">(" + count + ")<\span>";
			 	isFound = true;
			 	break;
			 }
		}
		if (!isFound)
			$("cbLabel_"+checkboxes[i].id ).innerHTML = checkboxes[i].id  + " <span class=\"ajLightGrayText\">(0)<\span>";
	}
}

// User selected the "Single Date" radio button
function processSingleDateSelection()
{
	//  Don't allow the 'Single Date' checkbox to be selected except through the 
	//  popup Calendar.  Otherwise there are too many ways for a user to cancel
	//	the calendar popup by clicking outside the calendar popup so we 
	//	would then have the "Single Date" checkbox selected but no date entered.
	var dateRadioButtons = document.filteredJourneysForm.dateRange;
	toggleInput(dateRadioButtons, "All Dates", true); 
	showCalendarWithSpan('dateCalendarPopupDiv','singleDateSpan','singleDateLink', singleDateSpanUpdated,-50,10)
}

// User selected the "All Dates" radio button
function processAllDateSelection()
{
	//  Nothing more to do for now
	processDateSelection();
}

// The date <span> has been updated and the Calendar has called back to this method
function singleDateSpanUpdated()
{
	//  First ensure the single date radio button is selected
	var dateRadioButtons = document.filteredJourneysForm.dateRange;
	toggleInput(dateRadioButtons, "Single Date", true);
	processDateSelection();
}

// User selected a date radio button so process the selection
function processDateSelection()
{
	// 	First reset offset to zero.  Must do this as (1) this is the natural UI experience and (2) the newly selected
	//	dataset may not be as long as the prior dataset.
	pgOffset = 0;

	//  Test to ensure single date is actually a date....and not the "Select a Date" text...
	var selectedDate = getSelectedDate();
	if ( selectedDate == null) {
		var dateRadioButtons = document.filteredJourneysForm.dateRange;
		
		// No date selected so reselect "All Dates" radiobutton
		toggleInput(dateRadioButtons, "All Dates", true); 
	}
	processNewFilterSelection();
}

// Return the selected date if one exists else return null.
function getSelectedDate()
{
	var dateRadioButtons = document.filteredJourneysForm.dateRange;

	if ( getSelectedRadioButton(dateRadioButtons).value == "Single Date") {
		//  Test to ensure single date is actually a date....and not the "Select a Date" text...
		if ( $("singleDateSpan").innerHTML.indexOf('/') > 0)
			return $("singleDateSpan").innerHTML;
		else
			return null; // No date selected
	}
}

// Called to select a Neighborhood checkbox
function selectNeighborhood(neighborhood)
{
	// 	First reset offset to zero.  Must do this as (1) this is the natural UI experience and (2) the newly selected
	//	dataset may not be as long as the prior dataset.
	pgOffset = 0;

	var checkboxes = document.filteredJourneysForm.neighborhoods;
	deselectAllCBBut(checkboxes, neighborhood);
	isAllNeighborhoodsSelected = false;

	processNewFilterSelection(); // Update the displayed journeys
}

// Maintains state of "All Neighborhoods" between user updates so functions
// like updateAllCBSelection() work properly
var isAllNeighborhoodsSelected = true; 

// Called when a Neighborhood checkbox is clicked
function processNeighborhoodCBSelection(neighborhoodId)
{
	// 	First reset offset to zero.  Must do this as (1) this is the natural UI experience and (2) the newly selected
	//	dataset may not be as long as the prior dataset.
	pgOffset = 0;

	var checkboxes = document.filteredJourneysForm.neighborhoods;
	
	//  Value for "All Neighborhoods" is zero
	isAllNeighborhoodsSelected = updateAllCBSelection(checkboxes, "0", isAllNeighborhoodsSelected)
	
	// Display Google Map popup for the newly selected Neighborhood
	if ( neighborhoodId != "0" ) //  "All Neighborhoods" is zero
		showNeighborhoodPopup(neighborhoodId);

	processNewFilterSelection();
}

// Called when a Category checkbox is clicked
var isAllCategoriesSelected = true; // maintains state of "All Categories" between user updates
function processCategoriesCBSelection()
{
	// 	First reset offset to zero.  Must do this as (1) this is the natural UI experience and (2) the newly selected
	//	dataset may not be as long as the prior dataset.
	pgOffset = 0;

	var checkboxes = document.filteredJourneysForm.categories;
	isAllCategoriesSelected = updateAllCBSelection(checkboxes, "All Categories", isAllCategoriesSelected)
	processNewFilterSelection();
}

//  A tab was clicked in the UI, so update the selected tab and then update the pager
function processTabSelection(newSelTab)
{
	// 	First reset offset to zero.  Must do this as (1) this is the natural UI experience and (2) the new tab's 
	//	dataset may not be as long as the old tab's data.
	pgOffset = 0;

	updateSelectedTab(newSelTab)
	processNewFilterSelection(); // happens asynchronously so let kick this off now
}

//  Select the given tab by moving it to the front, updating its images, and deselecting the prior selection
//  Also change the background on the icon for those tabs with images on them (e.g. Guided, Media, ...)
//  The All Journeys tab doesn't have an icon so skip it...
function updateSelectedTab(newSelTab)
{
	var allTab    = $("allJourneysTab");
	var guidedTab = $("guidedJourneysTab");
	var mediaTab  = $("mediaJourneysTab");
	var selfTab   = $("selfGuidedJourneysTab");

	if ( newSelTab == "allJourneysTab") {
		allTab.className="selectedTab";guidedTab.className="";mediaTab.className="";selfTab.className="";
		journeyType = "All Journeys";
		journeyTypeForPager = "";
	} else if ( newSelTab == "guidedJourneysTab") {
		allTab.className="";guidedTab.className="selectedTab";mediaTab.className="";selfTab.className="";	
		journeyType = "Guided";		
		journeyTypeForPager = " guided ";
	} else if ( newSelTab == "mediaJourneysTab") {
		allTab.className="";guidedTab.className="";mediaTab.className="selectedTab";selfTab.className="";
		journeyType = "Multimedia";
		journeyTypeForPager = " multimedia ";
	} else if ( newSelTab == "selfGuidedJourneysTab") {
		allTab.className="";guidedTab.className="";mediaTab.className="";selfTab.className="selectedTab";
		journeyType = "Self-Guided";
		journeyTypeForPager = " self-guided ";
	}
}

/** Takes an address of the form "420 Mangels Ave, San Francisco, CA" and passes
    it to Google to retrieve the Lat/Long for it.  */
function plotAddress() 
{
	var address = $("cityAddress").value;
	new GClientGeocoder().getLatLng(address,displayAddress);
}

// Display the address provided by the user in the Google Map 
function displayAddress(point) {
	if (!point) {
		$("addressError").innerHTML = "Address not found.  Please check the formatting of your address.";
		$("addressError").className = "ajFormError";
	} else {
		$("addressError").className = "ajSmallText";
		googleMap.setCenter(point, 13);
		var marker = new GMarker(point);
		googleMap.addOverlay(marker);
		var address = $("cityAddress").value;
		var popupHtml = '<iframe src="userAddressPopup.do?address=' + address + '" scrolling="no" frameborder="0" height="50" width="300"></iframe>';
		marker.openInfoWindowHtml(popupHtml);
	}
}


