var starOnHtml = '<img class="favorite_on" src="graphics/star-on.gif" alt="favorite business" title="This business is marked as one of your favorites&mdash;click to unmark it">';
var starOffHtml = '<img class="favorite_off" src="graphics/star-off.gif" alt="not a favorite business" title="Click the star to mark this business as one of your favorites">';

// RSH setup
window.dhtmlHistory.create({
	toJSON: function(o) {
		return JSON.stringify(o);
	}, 
	fromJSON: function(s) {
		return JSON.parse(s);
	}
});
var lastQueryObjListened = null;
var changeListener = function(queryString, historyData) {
	var queryObj = queryStringToObject(queryString);
	if (queryObj != lastQueryObjListened) { // if queryString has changed
		setFormValues(queryObj);
		updatePage(queryObj);
		lastQueryObjListened = queryObj;
	}
}
window.onload = function() {
	dhtmlHistory.initialize();
	dhtmlHistory.addListener(changeListener);
};

$(document).ready(function() {

	// begin init code -------------------------------

	// set up category selection portion of form
	printCategorySelectors();

	// load url's #query into form fields
	initializePage();

	// begin event handling -------------------------------

	// updatePage when a form field value changes
	$("#inputform :input").change(function() {
		var queryObj = formToQueryObj();
		queryObjToPageHistory(queryObj);
		updatePage(queryObj);
		return false;
	});
	
	// trigger state change when radio or checkbox is clicked for ie
	$("#inputform :input@type=checkbox").click(function() {
		$(this).change();
	});

	// trigger state change when enter is pressed in form field
	$("#inputform :input").keypress(function(e) {
		if(e.keyCode == 13) {
			$(this).change();
			return false;
		}
	});

	// form submits are SO 90s!
	$("#inputform").submit(function() {
		return false;
	});
	
	// handle category clicks
	$(".category_selector").live('click', function(e) {
		var matches = /category-(\d+)/.exec(this.id);
		var categoryId = matches[1];

		if ($(this).hasClass("selected_category") || $(this).hasClass("partially_selected_category")) { // deselection
			deselectCategory(categoryId);
		} else { // selection
			selectCategory(categoryId, e);
		}
		var queryObj = formToQueryObj();
		queryObjToPageHistory(queryObj);
		updatePage(queryObj);
	});

	// handle button clicks
	$(".favorite_control img").live('click', function(){
		var businessId;
		$(this).parents('.business_row').each(function() { 
			var matches = /business-(\d+)/.exec(this.id);
			if (matches) {
				 businessId = matches[1];
			}
		});
		var was_favorite = $(this).hasClass('favorite_on');
		request = $.get('set_favorite_business.php', {'business_id':businessId, 'flip_on':was_favorite?0:1}, function(jsonString) {
			if (jsonString) {
				var resultsObj = JSON.parse(jsonString);
				// result represents error message
				if (resultsObj.ERROR) {
					printResultsHeader('<span class="error">Error</span> '+resultsObj['ERROR']);

				// result represents confirmation of setting
				} else {
					$("#business-"+businessId+" .favorite_control").html(
						resultsObj.is_favorite==1 ? starOnHtml : starOffHtml
					);
				}
			}
		});
	});

	var businessinfo;
	$(".show_businessinfo").live('click', function(){
		$(this).parents('.business_row').each(function() { 
			// mark parent category as partially selected 
			var matches = /business-(\d+)/.exec(this.id);
			if (matches) {
				var businessId = matches[1];
				var businessName = $('#business-'+businessId+' h3').text();
				$('#viewing_business_id').val(businessId);
				var queryObj = formToQueryObj();
				queryObjToPageHistory(queryObj);
				showBusinessInfo(businessId,businessName);
			}
		});
		return false;
});

	$('#clear_all').click(function() {
		var queryObj = queryStringToObject('f=0&k=&p=25&l=&o=name&v=&');
		setFormValues(queryObj);
		queryObjToPageHistory(queryObj);
		updatePage(queryObj);
	});


	// end event handling -------------------------------
});

function initializePage() {
	if (window.location.hash) {
		var queryObj = queryStringToObject(
			window.location.hash.replace(/^#/, '')
		);
	} else if ($.cookie("search_criteria")) {
		var queryObj = JSON.parse(
			$.cookie("search_criteria")
		); 
		queryObjToPageHistory(queryObj);
	} else {
		var queryObj = queryStringToObject(
			'f=0&k=&p=25&l=&o=name&v=&'
		);
		queryObjToPageHistory(queryObj);
	}
	setFormValues(queryObj);
	updatePage(queryObj);
}
// mark category as selected and (maybe) print subcategory widget
function selectCategory(categoryId, e) {
	if(e && !e.ctrlKey) { // if not holding down ctrl, deselect siblings
		$('#category-'+categoryId).siblings().each(function() {
			var matches = /category-(\d+)/.exec(this.id);
			var categoryId = matches[1];
			deselectCategory(categoryId);
		});
	}
	$('#category-'+categoryId) 
		.addClass('selected_category') // mark selected
		.parents('.selectorsection').each(function() { 
			// mark parent category as partially selected 
			var matches = /category_selector_section-(\d+)/.exec(this.id);
			if (matches) {
				var parentCategoryId = matches[1];
				$('#category-'+parentCategoryId)
					.removeClass('selected_category')
					.addClass('partially_selected_category');
			}
		});
	printCategorySelectors(categoryId); // (maybe) print subcategory widget
}
// mark category as deselected and (maybe) delete subcategory widget
function deselectCategory(categoryId) {
	$('#category-'+categoryId)
		.removeClass('selected_category')
		.removeClass('partially_selected_category');
	$('#category_selector_section-'+categoryId).remove();
}

// convert form into string
function formToQueryObj() {
	var queryObj = new Object;
	queryObj.f = $('#only_favorites').is(':checked')?1:0;
	queryObj.k = $('#keyword').val();
	queryObj.p = $('#proximity').val();
	queryObj.l = $('#location').val();
	queryObj.o = $('#orderby').val();
	queryObj.v = $('#viewing_business_id').val();

	// load partially selected categories into queryString
	var partiallySelectedCategoryIds = [];
	$(".partially_selected_category").each(function() {
		var matches = /category-(\d+)/.exec(this.id);
		partiallySelectedCategoryIds.push(matches[1]);
	});
	if (partiallySelectedCategoryIds.length) {
		queryObj.pc = partiallySelectedCategoryIds.join(',');
	}

	// load selected categories into queryString
	var selectedCategoryIds = [];
	$(".selected_category").each(function() {
		var matches = /category-(\d+)/.exec(this.id);
		selectedCategoryIds.push(matches[1]);
	});
	if (selectedCategoryIds.length) {
		queryObj.c = selectedCategoryIds.join(',');
	}
	return queryObj;
}
function queryObjToPageHistory(queryObj) {
	var string = '';
	for (var label in queryObj) {
		var value = queryObj[label];
		string += label+'='+encodeURIComponent(value)+'&';
	}
	dhtmlHistory.add(string);
}
function clearCategorySelectors() {
	$('.selected_category').removeClass('selected_category');
	$('.partially_selected_category').removeClass('partially_selected_category');
	$('.selectorsection:not(#category_selector_section-top)').remove();
}
// set form according to contents of queryObj
function setFormValues(queryObj) {
	// set normal form fields
	if (queryObj.f==1)
		$('#only_favorites').attr('checked', true);
	else
		$('#only_favorites').attr('checked', false);
	$('#keyword').val(queryObj.k?queryObj.k:'');
	$('#proximity').val(queryObj.p?queryObj.p:'25');
	$('#location').val(queryObj.l?queryObj.l:'');
	$('#orderby').val(queryObj.o?queryObj.o:'');
	$('#viewing_business_id').val(queryObj.v?queryObj.v:'');

	clearCategorySelectors();
	// set partially selected categories and (maybe) print subcategory widgets
	if (queryObj.pc) {
		var partiallySelectedCategoryIds = queryObj.pc.split(','); 
		for (var i=0, len=partiallySelectedCategoryIds.length; i<len; i++) { 
			$('#category-'+partiallySelectedCategoryIds[i]).addClass('partially_selected_category');
			printCategorySelectors(partiallySelectedCategoryIds[i]);
		}
	}
	// set selected categories
	if (queryObj.c) {
		var selectedCategoryIds = queryObj.c.split(','); 
		for (var i=0, len=selectedCategoryIds.length; i<len; i++) { 
			if (!in_array(selectedCategoryIds[i], partiallySelectedCategoryIds)) {
				selectCategory(selectedCategoryIds[i]);
			}
		}
	}
}
// this function prints top or sub level category selector widget
function printCategorySelectors(parentCategoryId) {
	if (parentCategoryId && (!categoryIdTreeObj[parentCategoryId] || !categoryIdTreeObj[parentCategoryId].children)) {	// no children
		return false;

	} else if (parentCategoryId) {	// children
		var sectionTitle = categoriesObj[parentCategoryId]+' subcategories';
		var categoriesIdBranchObj = categoryIdTreeObj[parentCategoryId].children;
		var identifier = 'category_selector_section-'+parentCategoryId;

	} else { // top-level categories
		var sectionTitle = 'Search by category';
		var categoriesIdBranchObj = categoryIdTreeObj;
		var identifier = 'category_selector_section-top';
	}
	var count = 0;
	for (k in categoriesIdBranchObj) if (categoriesIdBranchObj.hasOwnProperty(k)) count++;
	if (count>1) {
		// create widget structure
		$("#category_selectors").append(
			'<div id="'+identifier+'" class="inputsection selectorsection">'+
				'<h2 class="inputsectionheader">'+sectionTitle+'</h2>'+
				'<div class="inputsectionbody">'+
					(count>1?'<div class="instruction">to choose several, hold Ctrl</div>':'')+
					'<div class="selectors"></div>'+
				'</div>'+
			'</div>'+
		'');
		// fill widget with individual category selectors
		for (var categoryId in categoriesIdBranchObj) {
			$('#'+identifier+' .selectors').append(
				'<span id="category-'+categoryId+'" class="category_selector">'+
					output(categoriesObj[categoryId])+
				'</span>'
			);
		}
	}
}

var request; // global XMLHttpRequest object so we can cancel earlier requests when making new ones
var lastQueryObjQueried = null;
// take queryObj and make request to results.json.php, then run printResults()
function updatePage(queryObj) {
	// compare relevant query bits with last query
	if (lastQueryObjQueried &&
		queryObj.f==lastQueryObjQueried.f && 
		queryObj.k==lastQueryObjQueried.k && 
		queryObj.p==lastQueryObjQueried.p && 
		queryObj.l==lastQueryObjQueried.l && 
		queryObj.c==lastQueryObjQueried.c &&
		queryObj.o==lastQueryObjQueried.o) {

		updateModalDialog(queryObj.v); // handle modal dialog separately
		return false;                  // don't update results list
	} else {
		lastQueryObjQueried = queryObj;
	}
	
	// save cookie
	$.cookie(
		"search_criteria", 
		JSON.stringify(queryObj), 
		{ expires: 7 }
	);

	// clear previously loaded result rows
	$("#results tbody").empty();

	// check for minimum required criteria
	if (queryObj && (queryObj.f==1 || queryObj.k.length>0 || (queryObj.p && queryObj.l.length>0) || queryObj.c)) {

		$("#introduction").hide();
		$(".inputsectionhelp").hide();
		$("#resultsheader").show();

		// abort earlier request if there is one
		if (request)
			request.abort();

		// make ajax request 
		statusBusy();
		request = $.get('results.json.php', queryObj, function(jsonString){
			statusReady();
			// json result received
			if (jsonString) {
				resultsObj = JSON.parse(jsonString);

				// result represents error message
				if (resultsObj.ERROR) {
					printResultsHeader('<span class="error">Error</span> '+resultsObj['ERROR']);

				// result represents 1 or more businesses
				} else {
					printResultsHeader(resultsObj.length+(queryObj.f==1? ' favorite' : '')+' business'+(resultsObj.length!=1?'es':'')+(queryObj.k? ' matching phrase "'+queryObj.k+'"' : '')+(queryObj.l? ' within '+queryObj.p+' miles of '+queryObj.l : '')+(queryObj.c? ' in '+queryObj.c.split(',').length+' '+(queryObj.c.split(',').length==1?'category':'categories') : ''));

					printResults(resultsObj);
					updateModalDialog(queryObj.v);
					//$("#log").append('<p>Retrieved '+resultsObj.length+' results for '+dump(queryObj)+'</p>')
					
				}
			// empty result received
			} else {
				printResultsHeader('Sorry, no businesses matched your criteria.');
			}
		});
	} else {
		$("#resultsheader").hide();
		$("#additional_message").html('');
		$('#introduction').show();
		$('.inputsectionhelp').show();
	}
	
	// enable proximity sort if location has been specified
	if (queryObj && queryObj.l) {
		if ($('#orderby option[value="proximity"]').length == 0) {
			$('#orderby').append('<option value="proximity">proximity</option>');
		}
	} else {
		if ($('#orderby').val()=='proximity') 
			$('#orderby').val('name')
		$('#orderby option[value="proximity"]').remove();
	}
}
function updateModalDialog(business_id) {
	if (!business_id) {
		hideBusinessInfo();
	} else {
		$('#business-'+business_id+' .show_businessinfo').click();
	}
}

function printResultsHeader(message) {
	$("#status").html('<h2>'+message+'</h2>');
}
// convert resultsObj into table rows
function printResults(resultsObj) {

	// iterate through results object
	for (var label in resultsObj) {
		var business = resultsObj[label];

		// append business details to results table
		$("#results tbody").append(
			'<tr class="business_row" id="business-'+business.business_id+'">'+
				(USER_LOGGED_IN?'<td class="favorite_control">'+
					(business.is_favorite_business=='1' ? starOnHtml : starOffHtml)+
				'</td>':'')+
				'<td>'+
					'<h3>'+output(business.name)+'</h3>'+
					'<p class="category">'+output(business.category_paths?business.category_paths.replace(/,/g,", ").replace(/\//g," &rsaquo; "):'')+'</p>'+
					'<p class="discount">'+output(business.discount_short_description)+'</p>'+
				'</td>'+
				'<td>'+
					(business.phone?'<p>'+business.phone+'</p>':'')+
					'<p class="small">'+business.address_1+(business.address_2?', '+business.address_2:'')+', '+business.city+', '+business.state+(business.distance?' <span class="proximity">('+output(business.distance)+' '+(business.distance=='1'?'mi':'mi')+')</span>':'')+'</p>'+
					(business.website?'<p class="small"><a href="'+business.website+'">'+shortURL(business.website)+'</a></p>':'')+
				'</td>'+
				'<td class="last_td"><input type="button" class="show_businessinfo" value="more info"></td>'+
			'</tr>'
		);
	}
	// apply class to every other row
	$("#results tr:odd").addClass("odd_tr");
	$("#additional_message").html('Note: changing or removing some of your search criteria may produce more results.');
}
var statusmessage;
function statusBusy() {
	statusmessage = $("#status").html();
	$("#status").html('<div id="loading_indicator"><image src="graphics/loading.gif"></div>');
}
function statusReady() {
	$("#loading_indicator").remove();
	$("#status").html(statusmessage);
}

