/****************************************************************************/
/* turns the results list and tagcloud on/off, repositioning as appropriate */
	
var tagcloud_on = 1;
var results_on = 1;

function menu_toggle(id)
{
    if (document.getElementById)
    {
	var el = document.getElementById(id);
	
	var tagcloud_el = document.getElementById('tagcloud');
	var results_el = document.getElementById('results');
	
	if (Element.visible(el)) {
	    Effect.SwitchOff(el, {duration: 0.1, queue: 'front'});
	}
	else {
	    Effect.BlindDown(el, {duration: 0.1, queue: 'front'});
	}	
      
	if (results_on && (id =='tagcloud')) {
	    tagcloud_el.style["right"] = "235px";
	}      
	else {
	    tagcloud_el.style["right"] = "2px";
	}
	
	if (tagcloud_on && (id == 'results')) {
	    results_el.style["right"] = "235px";
	}
	else {
	    results_el.style["right"] = "2px";
	}
    }
    if (id == 'tagcloud')  {tagcloud_on = (tagcloud_on == 1) ? 0 : 1};
    if (id == 'results') { results_on = (results_on == 1) ? 0 : 1; }
}

/****************************************************************************/
/* toggles state between showing all books, or books in the user's library */

function mybooks_toggle (logged_in) {
    if(logged_in) {
	GDownloadUrl("toggle_mybooks.php" , function(data) {
	    var button = document.getElementById('mybookstoggle');
	    label = button.innerHTML;
	    if(label == "My Books"){
		button.innerHTML = "All Books";
		button.title = "Select this link to show All Books";
	    }
	    else {
		button.innerHTML = "My Books";
		button.title = "Select this link to show only My Books";
	    }
	    
	    setcook('p', 0);
	    breadcrumb();
	    resultlist_html();
	    showmarkers();
	});
    }
    else {
	alert("This feature restricts your display to books that you've added to your \npersonal library. You have to be registered, log in, and build a library first!\nSee the help page for more details");
    }
}

/****************************************************************************/
/* Cookie functions */

function setcook(cname, ccontent) {
    //    alert("Location.Hostname: " + location.hostname);
    document.cookie = cname+"="+ccontent;
}

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
	var c = ca[i];
	while (c.charAt(0)==' ') c = c.substring(1,c.length);
	if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

function getcook(cname) {
    return readCookie(cname);
}

function eraseCookie(name) {
    setcook(name,"",-1);
}

/****************************************************************************/
/* Create a marker whose info window displays book info - title, author, cover art, etc. */

function createMarker(point, html, title) {
    // Create our "tiny" marker icon
    var icon = new GIcon();
    icon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
    icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
    icon.iconSize = new GSize(12, 20);
    icon.shadowSize = new GSize(22, 20);
    icon.iconAnchor = new GPoint(6, 20);
    icon.infoWindowAnchor = new GPoint(5, 1);
    
    var marker = new GMarker(point, {icon:icon, title:title});     
    var html = "<div class=\"mymapmarker\">" + html + "</div>";
    GEvent.addListener(marker, 'click', function() {marker.openInfoWindowHtml(html);});
    
    return marker;
}

/****************************************************************************/
/* generate and update the markers for a nsew combo - since we can't */
/* necessarily display all markers, the query samples and displays a */
/* semi-arbitrary subset of the geotag locations within the */
/* lat-long. Redisplay gets you updated markers for your (presumably */
/* new) lat-long window */

function drawmarkers (query, refit)
{
    map.clearOverlays();
    GDownloadUrl(query , function(data) {
	var xml = GXml.parse(data);
        var markers = xml.documentElement.getElementsByTagName("marker");
	var bounds = new GLatLngBounds();

	for (var i = 0; i < markers.length; i++) {
	    var name = parsetoHTML(markers[i].getAttribute("name"));
            var html = parsetoHTML(markers[i].getAttribute("html"));
	    var title = name + ": " + parsetoHTML(markers[i].getAttribute("title"));
            var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
               	                    parseFloat(markers[i].getAttribute("lng")));
	    var marker = createMarker(point, html, title);
	    bounds.extend(point);
            map.addOverlay(marker);
        }

	if(refit) {
	    fit(map, bounds);
	}
    });
}

/****************************************************************************/

function showmarkersat (south, north, west, east) {

    var query = "gen_markers.php?" + "south=" + south + "&north=" + north + "&west=" + west + "&east=" + east;
    drawmarkers(query, false);
}

/****************************************************************************/
/* shows the markers associated with the current result set */
/* same as showmarkersat, but respects all query parameters */

function showmarkers () {

    var query = "gen_markers.php?"+get_query_args();
    drawmarkers(query, false);
}

function showmarkers_bookid (bookid, refit){

    var query = "gen_markers.php?bookid="+bookid;
    drawmarkers(query, refit);
}

/****************************************************************************/

function fit(map, bounds)
{
    var center = bounds.getCenter();
    map.closeInfoWindow();

    var sw = bounds.getSouthWest();
    var ne = bounds.getNorthEast();
    var north = ne.lat();
    var south = sw.lat();
    var east = ne.lng();
    var west = sw.lng();
//    alert(south+":"+north+":"+east+":"+west+":");
    if ((north==south) && (east==west)) {
	map.setZoom(3);
    }
    else {
	map.setZoom(map.getBoundsZoomLevel(bounds));
    }
    map.setCenter(center);
    //map.panDirection(0,0.2);
}

/****************************************************************************/
/* get the lat long scale for geotag and recenter the map accordingly */

function moveto_geotag (lat, lng, scale) {

    //alert("moveto:"+ "lat: "+lat+ "lng: "+lng+ "scale: "+scale);
    //totally arbitrary scale choice: but seems to work ok.
    //scale = scale + 4; 
    //scale = 8;

    map.setCenter(new GLatLng(lat, lng), scale);
}

/****************************************************************************/
/* extracts arg values from the cookies and constructs url string */

function get_query_args ()
{
    var args = "";
    var sort = getcook("sort") ? getcook("sort") : 'title';
    var gtag = getcook("gtag") ? getcook("gtag") : '';
    var p    = getcook("p") ? getcook("p") : '';
    var np   = getcook("np") ? getcook("np") : '';
    var s    = getcook("s") ? getcook("s") : '';
    var north = getcook("north") ? getcook("north") : '';
    var south = getcook("south") ? getcook("south") : '';
    var east = getcook("east") ? getcook("east") : '';
    var west = getcook("west") ? getcook("west") : '';
    
    args += "sort=" + sort;
    args += "&gtag=" + gtag;
    args += "&p=" + p;
    args += "&np=" + np;
    args += "&s=" + s;
    args += "&south=" + south;
    args += "&north=" + north;
    args += "&west=" + west;
    args += "&east=" + east;
    
    //alert(args);
    return args;
}

/****************************************************************************/
/* sets a cookie for a given parameter, and regens the screen */

function set_parameter (parameter, value)
{
//    alert(parameter+": "+value);

    setcook(parameter, value);
//    alert(getcook(parameter));

    if(!(parameter=='p'))  //if the parameter is not a page change request, set the page to 0
    {
	setcook('p', 0);
    }

    breadcrumb();
    resultlist_html();
    if( !((parameter == 'p') || (parameter == 'np')) ) // no need to redisplay markers for paging
    {
	showmarkers();
    }
}

/****************************************************************************/
/* sets a geotag parameter, and regens the screen. resets screen boundaries,*/
/* as its un-intuitive to keep that once you have selected an explicit location */

function set_gtag (parameter, value, lat, lng, scale, name)
{
    setcook(parameter, value);
    setcook('gtag_name', name);
    eraseCookie('north');
    eraseCookie('south');
    eraseCookie('east');
    eraseCookie('west');
    setcook('p', 0);

    breadcrumb();
    resultlist_html();
    showmarkers();
    moveto_geotag(lat, lng, scale);
}

function unset_gtag ()
{
    eraseCookie('gtag');
    eraseCookie('gtag_name');
    setcook('p', 0);

    breadcrumb();
    resultlist_html();
    showmarkers();
}

/****************************************************************************/

function unset_search_string ()
{
    eraseCookie('s');
    setcook('p', 0);

    breadcrumb();
    resultlist_html();
    showmarkers();
}

/* designed to be called via scriptaculous autocompleter */ 

function updateSearch (text, li) {

    set_parameter('s', text.value);

    var search_string = encodeURIComponent(text.value);
    var query = "geocode.php?exact=1&" + "name=" + search_string;
    GDownloadUrl(query , function(data) {
	var xml = GXml.parse(data);
        var markers = xml.documentElement.getElementsByTagName("geoname");

	if(markers.length>0) {
	    var name = parsetoHTML(markers[0].getAttribute("name"));
            var lat = parsetoHTML(markers[0].getAttribute("lat"));
            var lng = parsetoHTML(markers[0].getAttribute("lng"));
            var displayscale = parsetoHTML(markers[0].getAttribute("displayscale"));
//	    displayscale = displayscale - 4.0;
	    moveto_geotag(lat, lng, displayscale);
        }
    });
}

/****************************************************************************/

function delete_element_if_exists (parent, name)
{
    var foo = document.getElementById(name);
    if (foo){$(parent).removeChild(foo);}
}

/****************************************************************************/
/* generates breadcrumb      */

function breadcrumb ()
{
    var gtag = getcook('gtag_name');   
    var north = getcook('north');
    var search_string = getcook('s');

    delete_element_if_exists('breadcrumb_span', 'gtag_bc_span');
    delete_element_if_exists('breadcrumb_span', 'map_bc_span');
    delete_element_if_exists('breadcrumb_span', 'search_bc_span');
    delete_element_if_exists('breadcrumb_span', 'separator1');
    delete_element_if_exists('breadcrumb_span', 'separator2');

    if(gtag) {
	$('breadcrumb_span').appendChild(
	    Builder.node('span', {id:'gtag_bc_span'},
			 [Builder.node('a', {className:'control'}, 'GeoTag: '),
			  Builder.node('a', {className:'breadcrumb'}, gtag),
			  Builder.node('a',
				       {href:'#', onclick:'unset_gtag()',title:'delete geotag filter from query'}, 
				       [Builder.node(
					   'sup', 
					   [Builder.node('img', 
							 {border:0, src:'../images/delete10.gif', hspace:0})] )])]));
    }
    
    if(gtag && north)
	$('breadcrumb_span').appendChild(Builder.node('span', {id:'separator1'},
						      [Builder.node('a', {className:'separator'}, ' | ')]));	

    if (north) {
	$('breadcrumb_span').appendChild(
	    Builder.node('span', {id:'map_bc_span'},
			 [Builder.node('a', {className:'control'}, 'MapFilter: '),
			  Builder.node('a', {className:'breadcrumb'}, 'On'),
			  Builder.node('a',
				       {href:'#', onclick:'unset_map_filter()',title:'delete map filter from query'}, 
				       [Builder.node(
					   'sup', 
					   [Builder.node('img', 
							 {border:0, src:'../images/delete10.gif', hspace:0})] )])]));
    }
    
    if(search_string && (north || gtag))
	$('breadcrumb_span').appendChild(Builder.node('span', {id:'separator2'},
						      [Builder.node('a', {className:'separator'}, ' | ')]));	

    if (search_string) {
	$('breadcrumb_span').appendChild(
	    Builder.node('span', {id:'search_bc_span'},
			 [Builder.node('a', {className:'control'}, 'Keywords: '),
			  Builder.node('a', {className:'breadcrumb'}, search_string),
			  Builder.node(
			      'a',
			      {href:'#', onclick:'unset_search_string()',title:'delete keyword search from query'}, 
			      [Builder.node('sup', 
					    [Builder.node('img',
							  {border:0, src:'../images/delete10.gif', hspace:0})] )])]));
    }
}

/****************************************************************************/
/* sets the query parameters to filter to current map display boundaries    */

function filter_by_map ()
{
    var glatln = map.getBounds();
    var sw = glatln.getSouthWest(glatln);
    var ne = glatln.getNorthEast(glatln);
    var north = ne.lat();
    var south = sw.lat();
    var east = ne.lng();
    var west = sw.lng();
    
    //alert(south+":"+north+":"+west+":"+east+":");
    // this happens if the screen region covers the 180/-180 split. This is a hack.
    
    if ( (north < south) |  (east < west) ) {
	north = 180; south = -180; east = 180; west = -180;
    }
    setcook("east", east);
    setcook("west", west);
    setcook("north", north);
    setcook("south", south);

    setcook('p', 0);
    breadcrumb();
    resultlist_html();
    showmarkers();
}  

function unset_map_filter ()
{
    eraseCookie('east');
    eraseCookie('west');
    eraseCookie('north');
    eraseCookie('south');

    setcook('p', 0);

    breadcrumb();
    resultlist_html();
    showmarkers();
}
    

/****************************************************************************/
/* generates all the html for results list and tagcloud, updates screen     */
/* desperately wants to be refactored into something readable by normal humans */

function resultlist_html ()
{
    var tr_class = "even";
    var args = get_query_args();
    var query = "gen_results.php?"+args;
    var p    = getcook("p") ? getcook("p") : '';
    var np   = getcook("np") ? getcook("np") : '';
    var tagcloud_span;
    var paging_span;

//    alert(query);
    delete_element_if_exists('results', 'results_table');
    delete_element_if_exists('tagcloud', 'tagcloud_span');
    delete_element_if_exists('results', 'paging_span');

    GDownloadUrl(query , function(data) {
	var xml = GXml.parse(data);
	var books = xml.documentElement.getElementsByTagName("book");
	var results_table = Builder.node('table', {id:'results_table'});
	var tr;
	var td;

	var books_top = xml.documentElement.getElementsByTagName("counts");
	var n_books = parsetoHTML(books_top[0].getAttribute("total"));	
	var number_of_pages = Math.ceil(n_books / np);
	var page = Math.max(0, p-1);
	paging_span = Builder.node('span', {id:'paging_span'});
	
	var buzz_style = 
	    (getcook("sort") == '(averagerating * numberofratings) desc') ? 'control_paging' : 'control_paging_italic';
	var recent_style = (getcook("sort") == 'bookid desc') ? 'control_paging' : 'control_paging_italic';
	var title_style = (getcook("sort") == 'title') ? 'control_paging' : 'control_paging_italic';
	var author_style = (getcook("sort") == 'author') ? 'control_paging' : 'control_paging_italic';

	tbody = Builder.node(
	    'tbody', 
	    [Builder.node(
		'tr',
		[Builder.node(
		    'td', {align:'left'}, 
		    [Builder.node('a', {className:'control'}, 'Sort: '),
		     Builder.node(
			 'a', 
			 {className:buzz_style, href:'#', 
			  onclick:"set_parameter('sort', '(averagerating * numberofratings) desc')"},
			 'Buzz'),
		     Builder.node('a', 
				  {className:recent_style, href:'#', onclick:"set_parameter('sort', 'bookid desc')"},
				  'Recent'),
		     Builder.node('a', 
				  {className:title_style, href:'#', onclick:"set_parameter('sort', 'title')"}, 
				  'Title'),
		     Builder.node('a', 
				  {className:author_style, href:'#', onclick:"set_parameter('sort', 'author')"}, 
				  'Author')
		    ])]), 
	     Builder.node('tr', [Builder.node('td', {align:'left'},
					      [Builder.node('a', 
							    {className:'control'}, 
							    "Results: "+n_books+
							    ((n_books == 1) ? " book" : " books")
							   )])])
	    ]);
	
	paging_span.appendChild( 
	    Builder.node('table', {className:'paging_sort'}, [tbody]));
	
 	paging_span.appendChild(Builder.node('a', {className:'control'}, 'Page: '));
	if (number_of_pages > 3) {
//  	    paging_span.appendChild(
//        		Builder.node(
// 		    'a', 
// 		    {href:'#', 
// 		     className:'control_paging', onclick:"set_parameter('p', 0)", title:'Go to first page'}, '<<'));
	}
	paging_span.appendChild(Builder.node('a', 
					     {href:'#', 
					      className:'control_paging', 
					      onclick:"set_parameter('p',"+page+")", title:'Go to previous page'},
					     '<'));
	
	for(var ii=1; ii <= Math.min(number_of_pages, 3); ii++) {
	    page = ii-1;
	    paging_span.appendChild(Builder.node('a', {href:'#', className:'control_paging', 
						       onclick:"set_parameter('p',"+page+")", 
						       title:'Go to page '+ii}, ii));
	}
	
	if(number_of_pages > 3) {
	    paging_span.appendChild(Builder.node('a', {className:'control_paging'}, '...'));
	}

	page = Math.min(number_of_pages - 1, (p*1)+1); //p*1 gets p to a float not a string
	paging_span.appendChild(
	    Builder.node('a',
			 {href:'#', className:'control_paging', onclick:"set_parameter('p',"+page+")",
			  title:'Go to next page'}, '>'));
	
	if(number_of_pages > 3){
	    page = number_of_pages - 1;
	    paging_span.appendChild(Builder.node('a', 
						 {href:'#', className:'control_paging', 
						  onclick:"set_parameter('p',"+page+")", 
						  title:'Go to last page'},
						 '>>'));
	}
	$('results').appendChild(paging_span);

	for (var i = 0; i < books.length; i++) {
	    var title = parsetoHTML(books[i].getAttribute("title"));
	    var author = parsetoHTML(books[i].getAttribute("author"));
	    var coverarturl = parsetoHTML(books[i].getAttribute("coverarturl"));
	    var amazonurl = parsetoHTML(books[i].getAttribute("amazonurl"));
	    var isbn = parsetoHTML(books[i].getAttribute("isbn"));
	    var bookid = parsetoHTML(books[i].getAttribute("bookid"));
	    var smalltable;

	    var auth_array = author.split(",");
	    if (auth_array.length == 1){
		var new_author = auth_array[0];
	    }
	    else if (auth_array.length == 2){
		var new_author = auth_array[1]+' '+auth_array[0];		 		
	    }
	    else {
		var new_author = "Unknown";	
	    }
	    
	    //alert(title+" "+author);
	    //setup alternating row counters for styling
	    if(tr_class == "odd") {tr_class = "even";}   
	    else  {tr_class = "odd";}
	    
	    tr = Builder.node('tr',{className:tr_class});

	    if (coverarturl) {
		var imb = Builder.node('b', [Builder.node('img', {src:coverarturl, title:'image title'})]);
//		td1 = Builder.node('a', {className:'title', href:amazonurl}, [title, imb]);
		td1 = Builder.node('a', {className:'title', href:'book.php?bookid='+bookid}, [title, imb]);
	    }
	    else {
		td1 = Builder.node('a', {className:'title', href:'book.php?bookid='+bookid}, [title]);
	    }
	    
	    td2 = Builder.node('td',{className:'author'}, "by: "+new_author);

	    smalltable = Builder.node('td', {className:'title'}, 
 				      [Builder.node('ul', 
 						    [Builder.node('li', {className:tr_class}, [td1]),
 						     Builder.node('li', {className:tr_class}, [td2])])]);

// IE seems to have problems with scriptaculous nested tables, so replaced this with the list above.
// 	    smalltable = Builder.node('td', {className:'title'}, 
// 				      [Builder.node('table', 
// 						    [Builder.node('tbody',
// 								  [Builder.node('tr', [td1]),
// 								   Builder.node('tr', [td2])])])]);

 	    tr.appendChild(smalltable);

	    var tbody2 = Builder.node('tbody', [tr]);
	    results_table.appendChild(tbody2);
	}
	
	$('results').appendChild(results_table);
	
	var tags = xml.documentElement.getElementsByTagName("gtag");
	tagcloud_span = Builder.node('span', {id:'tagcloud_span'});

	for (var iii = 0; iii < tags.length; iii++) {
	    if(tags[iii]) {
		var my_class = parsetoHTML(tags[iii].getAttribute("class"));
		var my_name = parsetoHTML(tags[iii].getAttribute("name"));
		var id = parsetoHTML(tags[iii].getAttribute("id"));
		var lat = parsetoHTML(tags[iii].getAttribute("lat"));
		var lng = parsetoHTML(tags[iii].getAttribute("lng"));
		var scale = parsetoHTML(tags[iii].getAttribute("scale"));

		if (!scale) scale = 1;
		var clickstring = 
		    "set_gtag('gtag'," +id +',' +lat +',' +lng +',' +scale +",'" +my_name +"')";

		var elt = Builder.node('a', {href:'#', className:my_class, onclick: clickstring}, my_name);
		tagcloud_span.appendChild(elt);
		var elt2 = Builder.node('a',
		    {href:'#', className:my_class, onclick:'moveto_geotag('+lat+','+lng+','+scale+')',
		    title:'move map to '+my_name}, 
 		    [Builder.node('sup', [Builder.node('img', {border:0, 
 		    src:'../images/system-software-update.gif', hspace:0})])]);
		tagcloud_span.appendChild(elt2);
	    }
	}
	$('tagcloud').appendChild(tagcloud_span);
    });

    //recentlist_html();
}

/****************************************************************************/
/* creates a panel of recently modified/created books */

function recentlist_html ()
{
    var query = "gen_results.php?recent=1";
    var recent_span;

    delete_element_if_exists('TV', 'recent_span');
    recent_span = Builder.node('div', {id:'recent_span'});

    GDownloadUrl(query , function(data) {
	var xml = GXml.parse(data);
	var books = xml.documentElement.getElementsByTagName("book");
	
	for (var i = 0; i < books.length; i++) {
	    var title = parsetoHTML(books[i].getAttribute("title"));
	    var author = parsetoHTML(books[i].getAttribute("author"));
	    var smallcoverarturl = parsetoHTML(books[i].getAttribute("smallcoverarturl"));
	    var amazonurl = parsetoHTML(books[i].getAttribute("amazonurl"));
	    var isbn = parsetoHTML(books[i].getAttribute("isbn"));
	    var bookid = parsetoHTML(books[i].getAttribute("bookid"));
	    var lastusername = parsetoHTML(books[i].getAttribute("lastusername"));
	    var smalltable;
	    if (lastusername == "") lastusername = "System";

	    if (smallcoverarturl) {
		var img = Builder.node('img', {className:'TVimg', src:smallcoverarturl, title:'image title'});
		booklink = Builder.node('a', {className:'title', href:'book.php?bookid='+bookid}, [img]);
		var link = Builder.node('a', {className:'TVtext'}, 'Last touched by ');
		var link2 = Builder.node('a', {className:'TVtext'}, lastusername);
		var br = Builder.node('br');
		var div1 = Builder.node('div', {className:'TVdiv'}, [booklink]);
		var div2 = Builder.node('div', {className:'TVdiv'}, [link, br, link2]);
 		recent_span.appendChild(div1);
 		recent_span.appendChild(div2);
	    }
	}
	$('TV').appendChild(recent_span);
    });
}

/****************************************************************************/
/* returns width & height. implementation approach via http://www.howtocreate.co.uk/ */

function WindowSize(size) {
    
    var myWidth = 0, myHeight = 0;
    if( typeof( window.innerWidth ) == 'number' ) {
	//Non-IE
	myWidth = window.innerWidth;
	myHeight = window.innerHeight;
    } 
    else if ( document.documentElement && 
	      ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
	//IE 6+ in 'standards compliant mode'
	myWidth = document.documentElement.clientWidth;
	myHeight = document.documentElement.clientHeight;
    }
    else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
	//IE 4 compatible
	myWidth = document.body.clientWidth;
	myHeight = document.body.clientHeight;
    }
    size[0] = myWidth;
    size[1] = myHeight;
}

/****************************************************************************/

function parsetoHTML (str) {
    str = str.replace(/&lt;/g, "<");
    str = str.replace(/&gt;/g, ">");
    str = str.replace(/&quot;/g, '"');
    str = str.replace(/&#39;/g, "'");
    str = str.replace(/&amp;/g, "&");
    return str;
}
