// index.js

var map;
var scriptname = 'index';
var markers = new Array();

function sortNumber(a, b)
{
	return a - b;
}


function load_index ()
{
	// show shortcuts
	var xml  = '<wrapper>' + $('shortcuts-src').innerHTML + '</wrapper>';
	var shortcutsXMLTree = xmlTreeCreate (xml.replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&'));
	var shortcuts = shortcutsXMLTree.getElementsByTagName("shortcut");
	$('shortcuts').innerHTML = "";
	for (var s=0; s<shortcuts.length; s++)
	{
		//alert (shortcuts[s].getAttribute("name") + ' - ' + shortcuts[s].getAttribute("latlong") + ' - ' + shortcuts[s].getAttribute("zoom"));
		var latlong = shortcuts[s].getAttribute("latlong").split(',');
		var zoom = shortcuts[s].getAttribute("zoom");
		$('shortcuts').innerHTML += '<a href="#" onclick="map.setCenter(new GLatLng(' + latlong[0] + ',' + latlong[1] + '),' + zoom+ '); return false;">' + shortcuts[s].getAttribute("name") + '</a> ';
	}
	$('shortcuts').innerHTML += '&middot; <span id="permalink"></span>';
	//alert ('done');
	
	// load google map
	if (GBrowserIsCompatible())
	{
		// get variables passed in from html
		/*
		var latitude = parseFloat(document.getElementById('latitude').innerHTML);
		var longitude = parseFloat(document.getElementById('longitude').innerHTML);
		var heading = document.getElementById('heading').innerHTML;
		var ll_accuracy = document.getElementById('ll_accuracy').innerHTML;
		*/
		
		// maybe get latlong from cookie
		var latitude;
		var longitude;
		var zoom;
		
		// london (go to london if no cookie or permalink)
		latitude = 51.5;
		longitude = -0.127;
		zoom = 13;
		
		// get zoom and bbox from GET vars
		var llzArray;
		if (document.getElementById("latlongzoom").innerHTML != "")
		{
			llzArray = document.getElementById("latlongzoom").innerHTML.split(',');
			latitude = llzArray[0];
			longitude = llzArray[1];
			zoom = parseInt(llzArray[2]); // damn that parseInt being necessary!
		}
		else // get zoom and bbox from cookie
		{
			var llzCookie = readCookie('latlongzoom');
			if (llzCookie)
			{
				llzArray = llzCookie.split(',');
				latitude = llzArray[0];
				longitude = llzArray[1];
				zoom = parseInt(llzArray[2]); // damn that parseInt being necessary!
			}
		}

		// set up OSM layer for Google Maps API
		var copyOSM = new GCopyrightCollection("<a href=\"http://www.openstreetmap.org/\">OpenStreetMap</a>");
		copyOSM.addCopyright(new GCopyright(1, new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180)), 0, " "));
		var tilesMapnik = new GTileLayer(copyOSM, 1, 17, {tileUrlTemplate: 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png'});
		var osmMapnik = new GMapType([tilesMapnik], G_NORMAL_MAP.getProjection(), "OSM");

		// create the map, add OSM view
		map = new GMap2(document.getElementById("google_map"), { mapTypes: [osmMapnik] });
		map.setCenter(new GLatLng(latitude, longitude), zoom);
		map.setMapType(G_SATELLITE_MAP);
		map.setUIToDefault();
		
		GEvent.addListener(map,"moveend", getMarkers);
		getMarkers();
	}
	

	// create the time slider
	var dateCanvas = $('dateCanvas');
	dateCanvas.width = $('google_map').offsetWidth;
	dateCanvas.height = 28;
	var startYear = 1800;
	var endYear = 2010;
	var yearRange = endYear-startYear;
	var base = 25;
	var x;
	
	var thisStartYear = $('date_from').value ? Math.floor($('date_from').value) : startYear;
	var thisEndYear = $('date_to').value ? Math.ceil($('date_to').value) : endYear;
	yearSlider = $('year-slider');
	yearSlider.style.width = $('google_map').offsetWidth + 'px';
    var slideControl = new Control.Slider(yearSlider.select('.yearsliderhandle'), yearSlider, {
		range: $R(startYear, endYear),
		sliderValue: [0, thisStartYear, thisEndYear],  /* the first of these references a hidden dummy handle (since index 0 causes other problems) */
		onSlide: function(values) {
			handleHitHandler(values, slideControl);	
			$('date_from').value = values[1];
			$('date_to').value = values[2];
			$('startYear').innerHTML = Math.floor(values[1]);
			$('endYear').innerHTML = Math.ceil(values[2]);
		},
		onChange: function(values) {
			handleHitHandler(values, slideControl);	
			$('date_from').value = Math.floor(values[1]);
			$('date_to').value = Math.ceil(values[2]);
			$('startYear').innerHTML = Math.floor(values[1]);
			$('endYear').innerHTML = Math.ceil(values[2]);
			getMarkers();
		}
    }
	);
	
}


function getCurrentBbox ()
{
	var bounds = map.getBounds();
	var sw = bounds.getSouthWest();
	var ne = bounds.getNorthEast();
	return sw.lng() + ',' + sw.lat() + ',' + ne.lng() + ',' + ne.lat();
}


function getCurrentDateOptions()
{
	var dateOpt = "";
	if (document.getElementById('date_from').value)
	{
		dateOpt = "&date=" + document.getElementById('date_from').value;
		if (document.getElementById('date_to').value)
			dateOpt += '-' + document.getElementById('date_to').value;
	}
	return dateOpt;
}


function handleHitHandler(values, slideControl)
{
	var h, handle = slideControl.activeHandleIdx;
	for (h=handle-1; h>0; h--)
		if (values[h]>values[handle])
			slideControl.setValue(values[handle],h);

	for (h=handle+1; h<values.length; h++)
		if (values[h]<values[handle])
			slideControl.setValue(values[handle],h);
}

function getMarkers (pagenumber)
{
	// build bbox
	/*
	var centerLatLng = map.getCenter();
	var ratio = Math.cos (centerLatLng.lat()/180*Math.PI);
	var bottomLeft = new GLatLng (centerLatLng.lat() - radius/metersPerDegree, centerLatLng.lng() - radius/metersPerDegree/ratio);
	var topRight = new GLatLng (centerLatLng.lat() + radius/metersPerDegree, centerLatLng.lng() + radius/metersPerDegree/ratio);
	var bbox = bottomLeft.lng() + ',' + bottomLeft.lat() + ',' + topRight.lng() + ',' + topRight.lat();
	*/
	var showingbooks = document.getElementById('showbooks').checked;
	var bbox = getCurrentBbox();
	if (typeof(pagenumber) == 'undefined')
		pagenumber = 0;

	// check zoom is ok for geograph
	if (map.getZoom() < 16 && document.getElementById('geograph').checked)
	{
		document.getElementById('geograph').checked = false;
		alert ('Geograph is disabled for zoom levels < 16 (this is level ' + map.getZoom() + '). Zoom in to see Geograph markers.');
	}

	// check zoom is ok for autocomp
	if (map.getZoom() < 16 && document.getElementById('autocomp').checked)
	{
		document.getElementById('autocomp').checked = false;
		alert ('Autocomposed images [cctv and street view-style] are disabled for zoom levels < 16 (this is level ' + map.getZoom() + '). Zoom in to see autocompsed markers.');
	}
	
	//alert ("http://www.snapmap.org/api/0.1/snapmap?bbox="+bbox);
	// load xml - should do this every 10 seconds of gentle movement, or immediately after a repositioning
	var xmlDoc = new window.XMLHttpRequest();
	//var reqURL = "http://www.snapmap.org/api/0.1/snapmap?bbox="+bbox+"&geograph";
	
	// geograph?
	var geograph = document.getElementById('geograph').checked ? '&geograph' : '';
	var autocomp = document.getElementById('autocomp').checked ? '&autocomp' : '';
	var pagesize = showingbooks ? 10000 : 100;
	pagesize = 10000;
	var pageReq = '&pagesize=' + pagesize + (pagenumber ? '&page=' + pagenumber : '');
	var minAltitude = document.getElementById('min_altitude').value;
	var altFilter =  minAltitude === "" ? "" : '&minAltitude=' + parseInt(minAltitude);
		
	//var pageReq = pagenumber ? '&page=' + pagenumber : '';
	
	var reqURL = "/api/0.1/snapmap?bbox="+bbox+getCurrentDateOptions()+geograph+autocomp+altFilter+pageReq;
	document.getElementById('sql').innerHTML = reqURL; // debug
	//alert (reqURL);
	
	// notice the use of a proxy to circumvent the Same Origin Policy.

	new Ajax.Request(reqURL, {
		method: 'GET',
		onSuccess: function(transport) {
			/*
			var notice = $('notice');
			if (transport.responseText.match(/href="http:\/\/prototypejs.org/))
				notice.update('Yeah! You are in the Top 10!').setStyle({ background: '#dfd' });
			else
				notice.update('Damn! You are beyond #10...').setStyle({ background: '#fdd' });
			*/
			var xmlResponse = transport.responseXML;

			var id;
			var latitude;
			var longitude;
			var heading = undefined;
			var thumbnail = "";
			var title = "";
			var html;
			var ll_accuracy;
			var numPhotos = xmlResponse.getElementsByTagName("photos")[0].getAttribute("count");
			var photos = xmlResponse.getElementsByTagName("photo");
			var resultCount = xmlResponse.getElementsByTagName("SnapML")[0].getAttribute("resultcount");
			var pageCount = xmlResponse.getElementsByTagName("SnapML")[0].getAttribute("pagecount");
			var photo;
			var numNewPhotos = 0;
			var deleteOldMarkers = new Array();
			var books = new Array();
			var limitToInaccuratePhotos = 60;
			var inaccuratePhotosHTML = "";

			// remove existing markers
			// (note that this optimization means that some markers which need changing, if there have been edits, remain the same)
			for (id in markers)
				deleteOldMarkers[id] = true;
				
			
			for (var p=0; p<numPhotos; p++)
			{
				thumbnail = "";
				title = "";
				heading = undefined;
				photo = photos[p];
				id = photo.getAttribute("id");
				latitude = photo.getAttribute("latitude")
				longitude = photo.getAttribute("longitude");
				if (photo.hasAttribute("ll_accuracy"))
					ll_accuracy = photo.getAttribute("ll_accuracy");
				if (photo.hasAttribute("heading"))
					heading = photo.getAttribute("heading");
				if (photo.hasAttribute("thumbnail"))
					thumbnail = photo.getAttribute("thumbnail");
				if (photo.hasAttribute("title"))
					title = photo.getAttribute("title");

				if (0)
				{
					// send thumbnail to localhost?
					if (thumbnail.indexOf('www.lorp.org/books/images/') != -1)
						thumbnail = thumbnail.replace('www.lorp.org/books/images/', 'localhost/~lorp/lorp-books-scans/');
				}

				if (id<100000)
					html = "<h3>" + id + ': ' + title + '</h3><div style="width:100%;height:128px;text-align=center;"><a href="/images/' +id + '"><div><img src="' + thumbnail + '" style="max-width:120px;max-height:120px;"/></div>SnapMap photo ' + id + '</a></div>';
				else // geograph hack
					html = "<h3>Geograph #" + (id-100000) + ': ' + title + '</h3><div style="width:100%;height:128px;text-align=center;"><a href="http://www.geograph.org.uk/photo/' + (id-100000) + '" target="_new"><img src="' + thumbnail + '" /><br/>Geograph photo ' + (id-100000) + '</a><br>(opens in new window)</div>';

				// add new marker if it hasn't already been added
				if (!markers[id])
				{
					var prefix = id<100000 ? 'pointer' : 'blue_pointer'; // geograph hack
					var marker = createMarkerWithAngle (latitude, longitude, ll_accuracy, heading, html, prefix);
					map.addOverlay(marker);
					markers[id] = marker;
					numNewPhotos++;
				}
				deleteOldMarkers[id] = false;

				// add books to the bookshelf
				var regex = /^http:\/\/www\.lorp\.org\/books\/images\/([0-9]+)\/_pics\/.*$/;
				if (showingbooks && thumbnail != "")
				{
					var matches = regex.exec(thumbnail);
					if (matches != null)
					{
						var spineurl = 'http://www.lorp.org/books/images/' + matches[1] + '/_pages/128/_spine.jpg';
						if (books[spineurl] == undefined)
							books[spineurl] = {count: 1, bookml:'http://www.lorp.org/books/' + matches[1] + '.bookml'};
						else
							books[spineurl].count ++;
					}
				}

				// add pic to the inaccurate photo list
				if (document.getElementById('inaccurate').checked)
				{
					if (ll_accuracy > 30 && limitToInaccuratePhotos--)
						inaccuratePhotosHTML += '<div class="imagelist-outer"><div class="imagelist-inner"><a href="/images/' + id + '"><img class="imagelist-img" src="' + thumbnail + '"/></a></div></div>';
				}
			}

			var bookshelf = "";
			if (showingbooks)
			{
				// sort books by number of pics in each
				var booksSorted = [];
				for (var sKey in books)
					booksSorted.push({key:sKey, bookml:books[sKey].bookml, count:books[sKey].count});
				booksSorted.sort(function(a,b) {return b.count - a.count});
				for (var nid in booksSorted)
					bookshelf += '<a href="' + booksSorted[nid].bookml + '"><img src="' + booksSorted[nid].key + '" alt="(' + booksSorted[nid].count + ')" title="(' + booksSorted[nid].count + ')"/></a>';
				document.getElementById('bookshelf').innerHTML = bookshelf;
			}
			else
				document.getElementById('bookshelf').innerHTML = "";

			for (id in deleteOldMarkers)
			{
				if (deleteOldMarkers[id])
				{
					map.removeOverlay(markers[id]);
					delete markers[id];
				}
			}

			// create pager UI
			var pagerString = 'Results: ' + resultCount + ' (showing ' + pagesize + ' results per page)<br><b>Pages: </b>';
			for (var page=0; page < pageCount; page++)
			{
				if (page==pagenumber)
					pagerString += '<b>' + (page+1) + '</b> ';
				else
					pagerString += '<a onclick="getMarkers(' + page + ')" style="cursor:pointer">' + (page+1) + '</a> ';
			}
			document.getElementById('pager').innerHTML = pagerString;
			document.getElementById('stats').innerHTML = '[' + numNewPhotos + '/' + numPhotos + ']';
			document.getElementById('sql').innerHTML += ' ' + xmlResponse.getElementsByTagName("duration")[0].firstChild.nodeValue + 's';

			// show inaccurate pics
			if (document.getElementById('inaccurate').checked)
			{
				document.getElementById('inaccurate-images').innerHTML = "<h2>Inaccurately positioned images</h2>";
				document.getElementById('inaccurate-images').innerHTML += inaccuratePhotosHTML + '<br clear="all">';
				document.getElementById('inaccurate-images').style.display = 'block';
			}
			else
			{
				document.getElementById('inaccurate-images').style.display = 'none';
			}
			
			// create date ui background canvas
			if (typeof $('year-debug') != 'undefined')
			{
				var dateCanvas = $('dateCanvas');
				dateCanvas.width = $('google_map').offsetWidth;
				dateCanvas.height = 28;
				var startYear = 1800;
				var endYear = 2010;
				var yearRange = endYear-startYear;
				var base = 25;
				var x;
				
				if (dateCanvas.getContext)
				{  
					var ctx = dateCanvas.getContext('2d');
					ctx.fillStyle = "rgba(255,255,255)";
					ctx.clearRect(0, 0, dateCanvas.width, dateCanvas.height);
					var graphWidth = dateCanvas.width - $('year-start').offsetWidth;
					var graphOffset = $('year-start').offsetWidth/2;
					
					// draw decade tabs
					
					ctx.lineStyle = "black";
					ctx.lineWidth = 1.0;
					ctx.beginPath();
					year += 10 - year % 10; // make year a decade
					for (var year=startYear; year<=endYear; year += 10)
					{
						x = Math.round((year - startYear) * (graphWidth/yearRange) + graphOffset);
						if (year % 50 == 0)
						{
							ctx.moveTo(x-0.5,base+2.5);
							ctx.lineTo(x+1.5,base+2.5);
							ctx.lineTo(x+1.5,base-1.5);
							ctx.lineTo(x-0.5,base-1.5);
							ctx.lineTo(x-0.5,base+2.5);
						}
						else
						{
							ctx.moveTo(x+0.5,base+1);
							ctx.lineTo(x+0.5,base-1);
						}
					}
					ctx.stroke();

					ctx.fillStyle = "rgba(0,0,0,0.3)"; // black
					ctx.fillStyle = "rgba(151,186,0,0.2)"; // snapmap light green
					ctx.fillStyle = "rgba(40,92,0,0.3)"; // snapmap dark green
					for (var p=0; p<numPhotos; p++)
					{
						photo = photos[p];
						id = photo.getAttribute("id");
						if (photo.hasAttribute("date"))
						{
							//$('year-debug').innerHTML += photo.getAttribute("date") + ' - ';
							x = (photo.getAttribute("date").substring(0,4) - startYear) * (graphWidth/yearRange) + graphOffset;
							//x += Math.random()*1.5 - 0.75;
							
							ctx.beginPath();
							
							ctx.moveTo(x,0);
							ctx.lineTo(x+3,base); 
							ctx.lineTo(x-3,base);
							
							/*
							ctx.arc(x, 13, 6, 0, Math.PI*2, true);
							*/
							ctx.closePath();
							ctx.fill();
						}
					}
				}
		/// slider came from here XXXXXXXXXXXXX
				
				
			}
			else
				alert ('element year-debug not defined');
		}
	});

	/*
	xmlDoc.open("GET", reqURL, false); // we should set 'async' to true to handle things smoothly
	xmlDoc.send("");
	var xmlResponse = xmlDoc.responseXML;
	
	if (xmlResponse === null)
		alert ("Ajax call failed: trying to retrieve 'http://www.snapmap.org/api/0.1/snapmap?bbox="+bbox+"'");
	else
	{
	}
	*/
	
	// store where we are in permalink span and cookie
	var center = map.getCenter();
	document.getElementById('permalink').innerHTML = '<a href="/?latlongzoom=' + center.lat()+','+center.lng()+','+map.getZoom() + '">permalink</a>';
	createCookie('latlongzoom', center.lat()+','+center.lng()+','+map.getZoom(), 365);
}


function createMarkerWithAngle (latitude, longitude, ll_accuracy, heading, text, prefix)
// adapted slightly from http://econym.org.uk/gmap/basic1.htm
// this really needs to go into main.js
{
	var icon = new GIcon();
	if (ll_accuracy == undefined || ll_accuracy > 30)
	{
		icon.image = "/icons/markers/marker.png";
	}
	else if (heading === undefined)
	{
    	icon.image = "/icons/markers/" + prefix + ".png";
	}
	else
	{
		var angle = (5 * parseInt (heading/5 +0.5)) % 360; // round angle to nearest 5 deg, and 360 => 0
    	icon.image = "/icons/markers/" + prefix + angle + ".png";
	}

    icon.shadow = "/icons/markers/_shadow.png";
    icon.iconSize = new GSize(17.0, 17.0);
    icon.shadowSize = new GSize(26.0, 17.0);
    icon.iconAnchor = new GPoint(8.0, 8.0);
    icon.infoWindowAnchor = new GPoint(8.0, 8.0);

	var marker = new GMarker(new GLatLng(latitude, longitude), icon);
	if (text!='')
		GEvent.addListener (marker, "click", function() {
				marker.openInfoWindowHtml (text);
				});
	return marker;
}


function datesChanged ()
{
	alert ('manual date change');
	var yearFrom = parseInt(document.getElementById('date_from').value);
	var yearTo = parseInt(document.getElementById('date_to').value);
	if (yearFrom >= 1000 && yearFrom <= 3000 && yearTo >= 1000 && yearTo <= 3000 && yearFrom < yearTo)
		getMarkers();
}


function altitudeChanged ()
{
	var minAltitude = parseInt(document.getElementById('min_altitude').value);
	getMarkers();
}


function toggleInaccurate()
{
	if (document.getElementById('inaccurate').checked)
		getMarkers(); // lazy
	else
		{} // document.getElementById('inaccurate-images').style.display = 'none';
}


/*
function handle_response(xmlResponse)
{
	var numPhotos = xmlResponse.getElementsByTagName("photos")[0].getAttribute("count");
	alert ('num = ' + numPhotos);
}
*/