Number.prototype.toRad = function() {  // convert degrees to radians
  return this * Math.PI / 180;
}
Number.prototype.toDeg = function() {  // convert radians to degrees (signed)
  return this * 180 / Math.PI;
}

var keywordInput;
var locationInput;
var klsi;

var postLoadingDiv;
var resultsLoadingDiv;

function preLoadPost(){
	$('#wordcloud').hide();
	$('#ofa_fullpost').empty();
	$('#ofa_fullpost').append($(postLoadingDiv).show());
}
function preSearch(){
	$('#ofa_res_search_results_container').append($(resultsLoadingDiv).show());
}
function postSearch(){
	$(resultsLoadingDiv).hide();
}
function noPostLoaded(){
	$('#wordcloud').show();
	$('#ofa_fullpost').empty();
}

function postShowPost(){
	
}
function errorShowPost(){

}
function getAdvancedQueryParamaters(){
	var q = '&lfkw='+ulToBinary($('#advanced_col_keywords ul'));
	q += '&match='+$('#advanced_match_number').text();
	q += '&jtype='+ulToBinary($('#advanced_col_type ul'));
	q += '&edu='+ulToBinary($('#advanced_col_edu ul'));
	return q;
}
function ulToBinary(list){
	var b = '';
	$(list).children().each(function(){
		if ($(this).hasClass('selected')) b = b+'1';
		else b = b+'0';
	});
	return b;
}

function initializeSmartScroll(){
	var winheight = $(window).height();
	//set center container to the height of the window
	$('#ofa_center_container').css( {
			'height' : winheight
//			, 'background-color' : 'red'
	} );
	
	var top = $('#ofa_center_container').offset().top;
	var fullheight = $('#ofa_center_container').height();
	var docscroll = $(window).scrollTop();
	var eltop = $('#ofa_right_col').offset().top;
	var search_results_header_height = $('#ofa_res_search_results_container').offset().top - $('#ofa_mid_search_header').offset().top;
	
	if (docscroll < top) { //if there is scrolling
		//set the height of the search results container and the columns; consider the search results header
		$('#ofa_res_search_results_container').css({
			'height' : (winheight - eltop + docscroll - search_results_header_height)+'px'
		});
		$('#ofa_right_col').css({ height : (winheight - eltop + docscroll )+'px' });
		//move columns - the header and the right column - to the top
		$('#ofa_mid_search_header, #ofa_right_col').css({ 'margin-top': (0)+'px' });
	} else {
		//mid_search_results_container_and_right_col.css({ 'height' : (top + fullheight - eltop)+'px' });
		
		$('#ofa_res_search_results_container').css({
			'height' : (top + fullheight - eltop - search_results_header_height)+'px'
		});
		$('#ofa_right_col').css({
			'height' : (top + fullheight - eltop )+'px'
		});
		
		//move columns down, so they are visible on the page
		$('#ofa_mid_search_header, #ofa_right_col').css({ 'margin-top': (docscroll - top)+'px' });
	}
}

function initializeSearchHelp(){
	
	$('.ofa_help_square').click(function(){
		$(this).siblings().filter('.ofa_help_info').fadeIn();				 
	});
	$('.ofa_help_info').click(function(){
		$(this).fadeOut();							   
	});
}

$(document).ready( function(){
	postLoadingDiv = document.getElementById('ofa_fullpost_loading');
	$(postLoadingDiv).hide();
	resultsLoadingDiv = document.getElementById('ofa_results_loading');
	$(resultsLoadingDiv).hide();

	initializeSearchHelp();
							
	klsi = new KLS.Interface( $("#ofa_search_keywords"), $("#ofa_search_locations"), $("#ofa_results_count"), $('#ofa_res_search_results_container'), $('#ofa_fullpost'));
	klsi.setControllerUrl('http://organizersforamerica.org/jb_resume_kls_controller.php?');
	klsi.hooks.preLoadPost = preLoadPost;
	klsi.hooks.preSearch = preSearch;
	klsi.hooks.postSearch = postSearch;
	klsi.hooks.noPost = noPostLoaded;
	klsi.hooks.getAdvancedQueryParams = getAdvancedQueryParamaters;
	
	/*
	//Add sortby fields
	klsi.sortby_add_fields( [
			{label : "Posted Date", field : "posted", orderdirection : "DESC"},
			{label : "Organization", field: "organization_name", orderdirection : "ASC"},
			{label : "Job Title", field: "title", orderdirection : "ASC"}
		]
	)
	*/

	//advanced search stuff	
	$('#ofa_searchbox_advanced').hide();
	$('#ofa_searchbox_advanced li').addClass('selected');
	$('#ofa_searchbox_advanced li').click(function(){
		if ($(this).hasClass('selected')){
			$(this).removeClass('selected');
			 klsi.refreshQueryTotals(); klsi.refreshResults();
		} else {
			$(this).addClass('selected');
			klsi.refreshQueryTotals(); klsi.refreshResults();
		}
	});
	$('#ofa_advanced_show_link').click(function(){
		if ($('#ofa_searchbox_advanced').css('display') == 'none') $('#ofa_searchbox_advanced').slideDown();
		else $('#ofa_searchbox_advanced').slideUp();
	});
	$('#ofa_advanced_hide_link').click(function(){
		$('#ofa_searchbox_advanced').slideUp();
	});	
	$('#ofa_advanced_match_less').click(function(){
		var n = parseInt($('#advanced_match_number').text());
		if (n != '1'){
			$('#advanced_match_number').text((n - 1));
		}
	});
	$('#ofa_advanced_match_more').click(function(){
		var n = parseInt($('#advanced_match_number').text());
		$('#advanced_match_number').text((n + 1));
	});

	keywordInput = $("#ofa_search_keywords").fcbkcomplete({
		json_url: "http://organizersforamerica.org/keywordSuggestions.php?table=jobs_resumes_keywords&style=fcbkcomplete",
		json_cache: false,
		filter_case: false,
		filter_hide: true,
		filter_selected: true,
		newel: true,
		shownewel: true,
		firstselected: true,
		complete_text: 'Type a keyword, press enter to add...',
		onselect: klsi.addKeyword,
		onremove: klsi.removeKeyword
		}).get(0);
	
	locationInput = $("#ofa_search_locations").fcbkcomplete({
		filter_case: false,
		filter_hide: true,
		filter_selected: true,
		newel: true,
		shownewel: false,
		complete_text: 'Type a location, press enter to add...',
		onselect: klsi.addLocation,
		onremove: klsi.removeLocation
	});

	klsi.refreshResults();	//do the first search


	//smart scroll css and js - notice the footer adjustments
	initializeSmartScroll();
		$('#ofa_footer').css( { 'margin-top':'0px' } );
		$(window).scroll(initializeSmartScroll);
		$(window).resize(initializeSmartScroll);
		//to fix fast scrolling and allow time for results to be populated
		setInterval( 'initializeSmartScroll()',500);
})

// KLS = KeywordLocationSearch
var KLS = new Object();
KLS.Interface = function(keywordInput, locationInput, resultsCountNode, resultsNode, postNode){
	var thisObj = this;
	var locations = Array();
	var keywords = Array();
	var posts = Array();
	var controllerUrl;

	var selectedPostId;				//the id of the post that is currently being viewed
	var resultsPage;
	var numResultsPages;
	var prevDbox;				//links for next and previous page of results
	var nextDbox;				//
	
	this.sortby_fields = Array(); 	//name value pairs
	this.hooks = Object();			//holds references to function hooks
	
	

	
	//functions to add regions and handle geocoding of region descriptions
	var checkLocationForVirtual = function(description){
		description = description.toUpperCase();
		if (description == 'VIRTUAL') return true;
		if (description == 'TBD') return true;
		if (description == 'TELECOMMUTING') return true;
		if (description == 'INTERNET') return true;
		if (description == 'ONLINE') return true;
		if (description == 'ON-LINE') return true;
		if (description == 'ON LINE') return true;
		if (description == 'WEB') return true;
		if (description == 'WEB BASED') return true;
		return false;
	}
	this.addKeyword = function(){
		//add the keyword and refresh the results
		var newKeyword = this.text().toLowerCase();	//this refers to the keywords control
		var i = 0;
		for (i = 0; i < keywords.length; i++){
			if (keywords[i] == newKeyword) {
				//TODO: remove the keyword
				alert('Sorry, that keyword is already part of your search criteria. Try something else.');
				return false;
			}
		}
		keywords.push(newKeyword);
		thisObj.refreshResults();
	}
	this.removeKeyword = function(){
		var rem = this.text();
		var i = 0;
		for (i = 0; i < keywords.length; i++){
			if (keywords[i] == rem) break;	
		}
		keywords.splice(i, 1);
		thisObj.refreshResults();
	}
	this.addLocation = function(){
		//geocodes the location and if its valid, add it to the search and refresh results
		var fbnode = this; //since this function is called from the fbsearch control
		var loc = $(fbnode).text();
		loc = loc.replace(/^\s+|\s+$/g,'').replace(/\s+/g,' ');  		//trim extra spaces
		$(fbnode).text(loc);
		loc = loc.toLowerCase();
		
		//if its virtual, add it and exit
		if (checkLocationForVirtual(loc)){
			//TODO: do something about searching for telecommuters?
			alert("Sorry, searching specifically for telecommuters is still under development.");
			return true;
		}
		
		//Geocode into a single Lat-Lon point and state information
		thisObj.geocoder.getLocations(loc, function(result) {
		  if (result.Status.code != 200) {
			alert('Sorry, the location you added could not be understood. Try something else');
			//TODO: remove the location
		  } else {
			  if (result.Placemark.length == 1){
				  //there is only 1 response, we can handle it directly
					var lat = result.Placemark[0].Point.coordinates[1];
					var lng = result.Placemark[0].Point.coordinates[0];
					var stateAbbr = result.Placemark[0].AddressDetails.Country.AdministrativeArea.AdministrativeAreaName;
					//thisObj.addLocation(new KLS.Location(loc, center, fbnode));
					var i = 0;
					for (i=0; i<locations.length; i++){
						if (locations[i].label == loc || (	locations[i].lat == lat && locations[i].lng == lng ) ){
							alert('Sorry, that location is already part of your search. Try something else.');
							return true;
						}
					}
					locations.push({label: loc, state: stateAbbr, lat: lat, lng: lng});
					thisObj.refreshResults();
					return true;
			  } else {
				alert("The location you entered had "+result.Placemark.length+" matches! Try something more specific...");
				//TODO: clear the added location
			  }			
		  }
		});
	}
	this.removeLocation = function(){
		var rem = this.text().toLowerCase();
		var i = 0;
		for (i = 0; i < locations.length; i++){
			if (locations[i].label == rem) break;	
		}
		locations.splice(i, 1);
		thisObj.refreshResults();
	}
	
	this.clearPosts = function(){
		posts = new Array();
		$(resultsNode).empty();
	}
	
	var getLocationsQueryString = function(){
		var q = '';
		var i = 0;
		for (i = 0; i < locations.length; i++){
			q += locations[i].state+locations[i].lat+' '+locations[i].lng+'/';
		}
		return q;
	}
	
	

/*
	//create "sortby control"
	this.sortby_add_fields = function( fields_to_add ) {
		//add fields
		var x;
		for (x in fields_to_add) {
			sortby_field = fields_to_add[x];
			this.sortby_fields.push( sortby_field );
			if ( this.sortby_fields.length == 1 ) {
				//if it is the first field added, create the button and select the first sort field
				$('#ofa_search_field').click( function () {
					if ( $('#ofa_sortby_menu').is(':hidden') ) {
						$('#ofa_sortby_menu').css({ 'margin-top': $(this).height() }).show();
					} else {
						$('#ofa_sortby_menu').hide();
					}
				});
				this.sortby_select( sortby_field.field );
			}
		}
		this.sortby_update_menu();
	}
	this.sortby_select = function( selected_field ){
		//marks one of the objects in this.sortby_fields as selected
		//label, field, table, selected
		var x;
		for (x in this.sortby_fields) {
			if ( this.sortby_fields[x].field == selected_field ) {
				this.sortby_fields[x].selected = 1;
				$('#ofa_sortby_menu').hide();
				$('#ofa_search_field').html(this.sortby_fields[x].label+' &#9660;');
				this.sortby_update_menu();
			} else {
				this.sortby_fields[x].selected = 0;
			}
		}
	}
	this.sortby_update_menu = function() {
		$('#ofa_sortby_menu ul#ofa_sortby_list').html('');
		var x;
		for (x in this.sortby_fields) {
			var li = document.createElement('li');
			if (this.sortby_get_selected().field == this.sortby_fields[x].field) $(li).addClass('selected_sort_field');
			$(li).text(this.sortby_fields[x].label);
			$(li).click(function(i){
				return function(){
					thisObj.sortby_select(thisObj.sortby_fields[i].field);
					thisObj.refreshResults();
				}
			}(x));
			$('#ofa_sortby_menu ul#ofa_sortby_list').append(li);
			//$('#ofa_sortby_menu ul#ofa_sortby_list').append('<li ' + ( (this.sortby_get_selected().field == this.sortby_fields[x].field) ? 'class="selected_sort_field"' : '' ) + ' onclick="klsi.sortby_select(\''++'\')">'++'</li>');
		}
	}
	this.sortby_get_selected = function() {
		var x;
		for (x in this.sortby_fields) {
			if ( this.sortby_fields[x].selected == 1 ) {
				return this.sortby_fields[x];
			}
		}
	}
*/
	
	
	this.setControllerUrl = function(newUrl){
		//check for "?" and handle smartly if its missing or not
		controllerUrl = newUrl;
	}

	this.highlightSearchKeywords = function(){
		$(postNode).removeHighlight();
		$(keywords).each(function(){
			$(postNode).highlight($(this).text());
		});	
	}

	this.loadPost = function(id){
		//highlight the post in the results list, load it into the 
		for (var i=0; i<posts.length; i++){
			if (posts[i].getId() == id) posts[i].getDbox().className = 'result_selected';
			else posts[i].getDbox().className = '';
		}
		
		if (selectedPostId == id) {
			//just to remove highlighting of any removed keywords
			thisObj.highlightSearchKeywords();
		} else {
			selectedPostId = id;
			if (typeof this.hooks.preLoadPost == 'function') this.hooks.preLoadPost();
			$(postNode).load(controllerUrl+'action=getpost&id='+id, null, function(){
				thisObj.highlightSearchKeywords();											   
			});
		}
	}
	
	var parseResultsXml = function(xml){
		thisObj.clearPosts();
		if (typeof thisObj.hooks.preSearch == 'function') thisObj.hooks.postSearch();

		$("searchresults>post", xml).each(function(){
			posts.push(new KLS.Post(this));						  
		});
		resultsCountNode.text(posts.length+' RESULTS OF '+$("searchresults", xml).attr('total')+' TOTAL');

		var postIsSelected = false;

		for (var i=0; i<posts.length; i++){
			var p = posts[i];
			resultsNode.append(p.getDbox());
			if (p.getId() == selectedPostId) postIsSelected = true;		//check if the selected post is within the current result set
			p.getDbox().onclick = function(post){ 
				return function(e){
					//TODO: make sure the post is within the viewable area
					//post.getDbox().scrollIntoView();
					thisObj.loadPost(post.getId());
				}
			}(p);
		}
		
		if (postIsSelected == true){
			thisObj.loadPost(selectedPostId);
		} else {
			selectedPostId = null;
			if (typeof thisObj.hooks.noPost == 'function') thisObj.hooks.noPost();
		}
	}

	this.refreshResults = function(){
		var sortby_string = '';		
		var offset_string = '';

/*
		if(typeof this.sortby_get_selected == 'function') {
			//if ( this.sortby_get_selected() ) {
			sortby_string = '&orderby='+this.sortby_get_selected().field+'&orderdirection='+this.sortby_get_selected().orderdirection;
		} else {
			//alert('See 489 -- sortby_string can be created.')
		}
		//alert(selectedRegion+' , '+selectedRegion.getNumPosts());
		numResultsPages = Math.ceil(selectedRegion.getNumPosts()/99);
		if (numResultsPages > 1){
			//theres more than 1 page of results
			offset_string = '&poffset='+resultsPage;
		}
*/	
		if (typeof thisObj.hooks.preSearch == 'function') thisObj.hooks.preSearch();
		$.ajax({
			type: "GET",
			url: 	controllerUrl+'action=search' + '&keywords='+keywords.join('/') + '&where='+getLocationsQueryString() + this.hooks.getAdvancedQueryParams() + sortby_string + offset_string,
			dataType: "xml",
			error: function (xhr, desc, exceptionobj) {
					alert('ERROR: '+desc);
			},
			success: function(data){
				var xml;
				if (typeof data == "string") {
					xml = new ActiveXObject("Microsoft.XMLDOM");
					xml.async = false;
					xml.loadXML(data);
				} else {
				   xml = data;
				}
				parseResultsXml(xml);
			}
		});		
	}

	this.loadNextPage = function(){
		if (resultsPage < numResultsPages){
			resultsPage++;
			thisObj.refreshResults();
		}
	}
	this.loadPrevPage = function(){
		if (resultsPage > 1) {
			resultsPage--;
			thisObj.refreshResults();
		}
	}
	
	//create next/prev page links
	prevDbox = document.createElement('A');
	prevDbox.className = 'switchPage';
	prevDbox.innerHTML = 'Load Previous Page';
	prevDbox.onclick = thisObj.loadPrevPage;
	nextDbox = document.createElement('A');
	nextDbox.className = 'switchPage';
	nextDbox.innerHTML = 'Load Next Page';
	nextDbox.onclick = thisObj.loadNextPage;
	
	//initialize geocoder
	if (GBrowserIsCompatible()) {
		this.geocoder = new GClientGeocoder();
	}
}

KLS.Post = function(xml){
	var jxml = $(xml);
	var thisObj = this;
	var id;
	var index;			//true index in the results list
	var description;
	var dbox;

	this.getId = function(){ return id; }
	this.getIndex = function(){ return index; }
	this.getDbox = function(){ return dbox; }

	dbox = document.createElement('A');
	dbox.appendChild(function(){
							  var t = document.createElement('DIV'); t.className='headshot'; 
							  if (jxml.attr('image')) {
								  var s = document.createElement('IMG');
								  s.src = '/image_cache.php?f='+jxml.attr('image')+'&w=70&xa=0.5&ya=0.5&x=70&h=70&y=70&t=jpg&q=90&ap=true';
								  t.appendChild(s);
							  }
							  return t;}());
	dbox.appendChild(function(){var t = document.createElement('SPAN'); t.className='title'; t.innerHTML=jxml.attr('title'); return t;}());
	dbox.appendChild(function(){var t = document.createElement('SPAN'); t.innerHTML=jxml.attr('edu'); return t;}());
	dbox.appendChild(function(){var t = document.createElement('SPAN'); t.innerHTML='Posted on '+jxml.attr('posted'); return t;}());
	id = jxml.attr('id');
}
