var map;
var scriptname = 'showimage';
var markers = new Array();
var markerAttributes = ["left", "right","position"];
var markerLabels = ["L", "R",""];
var maxMarkers = 3;
var polylineFOV;
var polylineHeading;

function viewSelectorChange()
{
	var helpboxes = document.getElementsByName('add-view-help');
	var viewtype = document.getElementById('view-selector').value;
	var viewxmlbox = document.getElementById('viewxml');
	for (var h=0; h<helpboxes.length; h++)
	{
		if (helpboxes[h].id == 'add-view-help-' + viewtype)
			helpboxes[h].style.display = 'block';
		else
			helpboxes[h].style.display = 'none';
	}
	viewxmlbox.value = "";
	viewxmlbox.setAttribute('readonly',true);
	document.getElementById("slingshot-trim-checkbox-ui").style.display = "none";
	if (viewtype == 'photooverlay')
	{
		document.getElementById("addview_submit_button").disabled = false;
		viewxmlbox.removeAttribute('readonly');
	}
	else if (viewtype == 'slingshot')
		document.getElementById("slingshot-trim-checkbox-ui").style.display = "inline";
}


function slingshotTrimToggle()
{
	if (document.getElementById("slingshot-trim-checkbox").checked)
	{
		document.getElementById("slingshot-slider").style.display = "block";
		var trimslider = $('new-trim-slider');
		var imageWidth = $("main-image").width;
		trimslider.style.width = (100) + 'px';
	}
	else
		document.getElementById("slingshot-slider").style.display = "none";
	updateViewXML();
}


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 mainImageOnLoad ()
{
	// slider (using prototype)
	$("debug").style.display = 'block';
	
	var imageWidth = $("main-image").width; // the image has loaded, so now we can get its width & height
	var imageHeight = $("main-image").height;
	var trimslider = $('new-trim-slider');
	trimslider.style.width = (imageWidth) + 'px';
	$('leftTrim').value = '-1';
	$('rightTrim').value = '1';
	
	$$('.tuner-needle').each(function(Element) {Element.style.height=imageHeight+'px';});

    var slideControl = new Control.Slider(trimslider.select('.newtrimhandle'), trimslider, {
		range: $R(-1, 1),
		sliderValue: [0, $('leftTrim').value, $('rightTrim').value],  /* the first of these references a hidden dummy handle (since index 0 causes other problems) */
		onSlide: function(values) {
			handleHitHandler(values, slideControl);	
			$('leftTrim').value = values[1];
			$('rightTrim').value = values[2];
			updateViewXML();
			calcRealLeftAndRight (values, imageWidth);
		},
		onChange: function(values) {
			handleHitHandler(values, slideControl);	
			$('leftTrim').value = values[1];
			$('rightTrim').value = values[2];
			updateViewXML();
			calcRealLeftAndRight (values, imageWidth);
		}
    }
	);

	
	/*
	// slider (using jquery)
	var imageWidth = $("#main-image").width(); // the image has loaded, so now we can get its width & height
	var imageHeight = $("#main-image").height();
	$("#slingshot-trim-slider").width(imageWidth); // only now do we know width & height of slider div
	$(".tuner-needle").height(imageHeight+3);
	var leftDefault = 0;
	var rightDefault = imageWidth;
	
	$(function() {
		$("#slingshot-trim-slider").slider({
			range: true,
			min: 0,
			max: imageWidth,
			values: [0, imageWidth],
			slide: function(event, ui) {
				$("#leftTrim").val((ui.values[0]/imageWidth*2-1).toFixed(4));
				$("#rightTrim").val((ui.values[1]/imageWidth*2-1).toFixed(4));
				$("#left-tuner").css('left', (ui.values[0] - 10) + 'px');
				$("#right-tuner").css('left', (ui.values[1] - 10) + 'px');
				
				// calculate true L and R from trimmed Lt and Rt
				
				// first, calculate circumscribed circle of P, Lt, Rt
				// - the coordinate system is transformed such that:
				//   * we are looking down at a line segment representing the photo's width
				//   * the line segment runs from L at -1 to R at +1
				//   * the trimmed values Lt and Rt are known
				//   * P, or (Px,Py), is defined to be centrally aligned with the image, therefore Px=0
				// - so, we need to find Py
				// - but first we must find C, the centre of the circle
				

				// distances
				var Px=0, Py;
				var Lt=ui.values[0]/imageWidth*2-1;
				var Rt=ui.values[1]/imageWidth*2-1
				var LtRtDistHalf = (Rt-Lt)/2;
				var Cx = (Lt+Rt)/2;

				var alpha = getMarkerAngle (markers);
				var Cy = -Math.tan(deg2rad(alpha))/(Rt-Cx);
				var r = Math.sqrt(LtRtDistHalf*LtRtDistHalf+Cy*Cy);
				var Py = Cy - Math.sqrt(r*r-Cx*Cx);
				
				// angles
				var OPR = rad2deg(Math.atan2(-Py,1));
				var OPL = -OPR;
				var OPRt = rad2deg(Math.atan2(-Py,Rt));
				var OPLt = alpha-OPRt;
				
				document.getElementById('debug').innerHTML = 
					'alpha=' + alpha + '<br>' +
					'OPR=' + OPR + '<br>' +
					'Lt=' + Lt + ',Rt=' + Rt + '<br>' +
					'P(' + Px.toFixed(3) + ',' + Py.toFixed(3) + ')<br>'+
					'C(' + Cx.toFixed(3) + ',' + Cy.toFixed(3) + ')';

				updateViewXML();
			}
		});

		// set defaults
		$("#left-tuner").css('left', (leftDefault - 10) + 'px');
		$("#right-tuner").css('left', (rightDefault - 10) + 'px');
		$("#left-tuner").css('top', '0px');
		$("#right-tuner").css('top', '0px');

		// report values
		$("#leftTrim").val(($("#slingshot-trim-slider").slider("values", 0)/imageWidth*2-1).toFixed(4));
		$("#rightTrim").val(($("#slingshot-trim-slider").slider("values", 1)/imageWidth*2-1).toFixed(4));
	});
	*/
	
}

function load_showimage ()
{
	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;
		
		// 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
		map = new GMap2(document.getElementById("google_map"), { mapTypes: [osmMapnik] }); // for some reason, this also includes the 4 standard map types
		var photoLatLng = new GLatLng(latitude, longitude);
		if (ll_accuracy < 1000000)
			map.setCenter(photoLatLng, 16);
		else
			map.setCenter(photoLatLng, 2);
		
		map.setMapType(G_SATELLITE_MAP);
		map.setUIToDefault();
		
		// this allows markers to be added
		GEvent.addListener(map,"click", addMoveableMapMarker);
		
		// add the default marker
		if (latitude || longitude)
		{
			var icon = new GIcon(G_DEFAULT_ICON);
		    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);

			if (heading.length == 0)
			{
				if (ll_accuracy > 0 && ll_accuracy < 30)
					icon.image = "http://www.snapmap.org/icons/markers/pointer.png";
				else
					icon.image = "http://www.snapmap.org/icons/markers/marker.png";
			}
			else
			{
				heading = Math.round(heading);
				icon.image = "http://www.snapmap.org/icons/markers/pointer" + heading + ".png";
			}
			
			var latlng = new GLatLng(latitude, longitude);
			var marker = new GMarker(latlng, {icon:icon});
			map.addOverlay(marker);
		}
		
		// slingshot view displayer
		var slingshots = document.getElementById('slingshots').innerHTML.replace(/&lt;/,'<').replace(/&gt;/,'>').replace(/&amp;/,'&');
		var xmlTree = xmlTreeCreate (slingshots);
		var slingshotviews = xmlTree.getElementsByTagName("view");
		if (slingshotviews.length)
		{
			if (slingshotviews[0].attributes.getNamedItem("type").nodeValue == 'slingshot')
			{
				var left = slingshotviews[0].getAttribute("left").split(',');
				var right = slingshotviews[0].getAttribute("right").split(',');
				var position = slingshotviews[0].getAttribute("position").split(',');
		
				// add static markers to the google map
				var latlngL = new GLatLng(left[0], left[1]);
				var latlngR = new GLatLng(right[0], right[1]);
				var latlngP = new GLatLng(position[0], position[1]);
				var ratio = Math.cos (deg2rad (position[0]));
				var metreVectorL = [left[0] - position[0], (left[1] - position[1]) * ratio];
				var vecLenL = Math.sqrt ((metreVectorL[0] * metreVectorL[0]) + (metreVectorL[1] * metreVectorL[1]))
				metreVectorL[0] /= vecLenL;
				metreVectorL[1] /= vecLenL;
				var metreVectorR = [right[0] - position[0], (right[1] - position[1]) * ratio];
				var vecLenR = Math.sqrt ((metreVectorR[0] * metreVectorR[0]) + (metreVectorR[1] * metreVectorR[1]))
				metreVectorR[0] /= vecLenR;
				metreVectorR[1] /= vecLenR;
				var length = 500; // how long should the diagonals be?
			
				var latlngLx = new GLatLng(1 * position[0] + length/metres_per_degree*metreVectorL[0] , 1 * position[1] + length/metres_per_degree*metreVectorL[1]/ratio);
				var latlngRx = new GLatLng(1 * position[0] + length/metres_per_degree*metreVectorR[0] , 1 * position[1] + length/metres_per_degree*metreVectorR[1]/ratio);

				//var latlngLx = new GLatLng(1 * position[0] + 1000 *(left[0]-position[0]) , 1 * position[1] + 1000 *(left[1]-position[1]));
				//var latlngRx = new GLatLng(1 * position[0] + 1000 *(right[0]-position[0]) , 1 * position[1] + 1000 *(right[1]-position[1]));
				addStaticMapMarker (latlngL, 'L');
				addStaticMapMarker (latlngR, 'R');
				addStaticMapMarker (latlngP, '');
			
				// add the field of view polygon
				var polygonFOV = new GPolygon([
					latlngLx,
					latlngP,
					latlngRx
				], "#000000", 4, 1.0, "#ffffff", 0.3);
				map.addOverlay(polygonFOV);
	//			alert ("got" + (1.0 * position[0] + 1.0 *(left[0]-position[0])));
			}
		}

		// photooverlay displayer
		var photooverlay_hfov = document.getElementById('photooverlay_hfov').innerHTML;
		if (photooverlay_hfov)
		{
			var length = 5000; // a longer coverage for aerial shots
			var posPixel = map.fromLatLngToContainerPixel(photoLatLng);
			var neighbourPixel = new GPoint(posPixel.x + 1, posPixel.y);
			var neighbourPixelLatLng = map.fromContainerPixelToLatLng(neighbourPixel);
	        var metresPerPixel = neighbourPixelLatLng.distanceFrom(photoLatLng);
			var pointLx = new GPoint(posPixel.x + Math.round (Math.sin(deg2rad(heading - photooverlay_hfov/2)) * length / metresPerPixel),
									posPixel.y - Math.round (Math.cos(deg2rad(heading - photooverlay_hfov/2)) * length / metresPerPixel));
			var pointRx = new GPoint(posPixel.x + Math.round (Math.sin(deg2rad(heading + photooverlay_hfov/2)) * length / metresPerPixel),
									posPixel.y - Math.round (Math.cos(deg2rad(heading + photooverlay_hfov/2)) * length / metresPerPixel));
			var latlngLx = map.fromContainerPixelToLatLng(pointLx);
			var latlngRx = map.fromContainerPixelToLatLng(pointRx);
			var polygonPhotoOverlayFOV = new GPolygon([
				latlngLx,
				photoLatLng,
				latlngRx
			], "#000000", 4, 1.0, "#ffffff", 0.3);
			map.addOverlay(polygonPhotoOverlayFOV);
		}
	}
	
	// rating
	if (document.getElementById('myRating').innerHTML == '6')
		document.getElementById('fave-star').style.color = 'red';
		
		
	/*
	rating = xmlResponse.getElementsByTagName("photo")[0].getAttribute("rating");
	document.getElementById("myRating").innerHTML = rating;
	*/
	
	/*
	"http://" + SERVER + "/api/0.1/rating.php?id=" + id + "&rating=" + rating;


	$("#another-star").click(function(){  
	        $("#result").html(ajax_load);  
	        $.get(  
	            loadUrl,  
	            {language: "php", version: 5},  
	            function(responseText){  
	          //      $("#result").html(responseText);  
					alert (responseText);
	            },  
	            "html"  
	        );  
	    });
	*/

	
}


function simplifyNumberString(n, decimals)
{
	var num = parseFloat(n).toFixed(decimals).toString();
	var pos = num.length-1;
	while (pos>=0)
	{
		if (num[pos] != '0')
		{
			if (num[pos]=='.')
				pos--;
			break;
		}
		pos--;
	}
	return num.substring(0, pos+1);
}

function updateViewXML()
{
	// get latlng of each marker
	var viewType = document.getElementById("slingshot-trim-checkbox").checked ? 'slingshot-trim' : 'slingshot';
	var str = "<view type=\"" + viewType + "\" ";
	var latlng;
	for (var m=0; m<markers.length; m++)
	{
		latlng = markers[m].getLatLng();
		str += markerAttributes[m] + '=';
		str += "\"" + latlng.lat() + ',' + latlng.lng() + "\" ";
	}
	if (viewType == 'slingshot-trim')
	{
		str += 'leftTrim="' + simplifyNumberString(document.getElementById("leftTrim").value, 4) + '" ';
		str += 'rightTrim="' + simplifyNumberString(document.getElementById("rightTrim").value, 4) + '" ';
	}
	str += "/>";
	document.getElementById('viewxml').value = str;
	
	delete str;
}


function calcRealLeftAndRight (values, imageWidth)
{
	// calculate true L and R from trimmed Lt and Rt
	
	// first, calculate circumscribed circle of P, Lt, Rt
	// - the coordinate system is transformed such that:
	//   * we are looking down at a line segment representing the photo's width
	//   * the line segment runs from L at -1 to R at +1
	//   * the trimmed values Lt and Rt are known
	//   * P, or (Px,Py), is defined to be centrally aligned with the image, therefore Px=0
	// - so, we need to find Py
	// - but first we must find C, the centre of the circle
	

	// distances
	var Px=0, Py;
	var Lt=values[1];
	var Rt=values[2];
	var LtRtDistHalf = (Rt-Lt)/2;
	var Cx = (Lt+Rt)/2;
	//document.getElementById('debug').innerHTML += '5('+values[1]+')	';
	var alpha = getMarkerAngle (markers);
	//document.getElementById('debug').innerHTML += '('+alpha+')';
	var Cy = -Math.tan(deg2rad(alpha))/(Rt-Cx);
	var r = Math.sqrt(LtRtDistHalf*LtRtDistHalf+Cy*Cy);
	var Py = Cy - Math.sqrt(r*r-Cx*Cx);

	// angles
	var OPR = rad2deg(Math.atan2(-Py,1));
	var OPL = -OPR;
	var OPRt = rad2deg(Math.atan2(-Py,Rt));
	var OPLt = alpha-OPRt;
	$('debug').innerHTML = 
		'alpha=' + alpha + '<br>' +
		'OPR=' + OPR + '<br>' +
		'Lt=' + Lt + ',Rt=' + Rt + '<br>' +
		'P(' + Px.toFixed(3) + ',' + Py.toFixed(3) + ')<br>'+
		'C(' + Cx.toFixed(3) + ',' + Cy.toFixed(3) + ')';
}


function addMoveableMapMarker(overlay, latlng)
{
	if (!(document.getElementById('view-selector').value == 'slingshot'))
		return;
		
	if (markers.length < maxMarkers)
	{
		var m = markers.length;
		var icon = new GIcon(G_DEFAULT_ICON);
		if (markerLabels[m] != '') // maybe choose an icon with a letter
			icon.image = "http://www.google.com/mapfiles/marker" + markerLabels[m] + ".png";
		markers[m] = new GMarker(latlng, {draggable:true, icon:icon});

		GEvent.addListener(markers[m], "dragstart", function(latlng) {
			map.closeInfoWindow();
			});
		GEvent.addListener(markers[m], "drag", movedMarker);
		GEvent.addListener(markers[m], "dragend", movedMarker);
		map.addOverlay(markers[m]);

		if (markers.length == maxMarkers)
		{
			document.getElementById("addview_submit_button").disabled = false;
			document.getElementById("slingshot-trim-checkbox").disabled = false;
		}
	}

	if (markers.length==3)
		movedMarker();

	// "The GPoint value is: " + map.fromLatLngToDivPixel(latlng) + "
}


function addStaticMapMarker(latlng, label)
{
	var icon = new GIcon(G_DEFAULT_ICON);
	if (label) // label should be a single cap letter
		icon.image = "http://www.google.com/mapfiles/marker_black" + label + ".png";
	else
		icon.image = "http://www.google.com/mapfiles/marker_black.png";
	var marker = new GMarker(latlng, {icon:icon}); // don't need to keep track of it
	map.addOverlay(marker);
}


function movedMarker ()
{
	updateViewXML();
	updatePolylines();
}


function getMarkerAngle (markers)
{
	var latlngs = new Array();
	for (var m=0; m<markers.length; m++)
		latlngs[m] = markers[m].getLatLng();
	var ratio = Math.cos (deg2rad (latlngs[2].lat())); // get the ratio in terms of where P is
	var L = { x:latlngs[0].lng() * ratio, y:latlngs[0].lat() };
	var R = { x:latlngs[1].lng() * ratio, y:latlngs[1].lat() };
	var P = { x:latlngs[2].lng() * ratio, y:latlngs[2].lat() };

	var PL = rad2deg(Math.atan2 (L.y-P.y,L.x-P.x));
	var PR = rad2deg(Math.atan2 (R.y-P.y,R.x-P.x));
	
	// make sure PR and PL can be subtracted properly
	if (PR-PL < 0)
		PR+=360.0;
	else if (PR-PL > 360)
		PR-=360.0;	

	var angle = PL-PR;
	if (angle < 0)
		angle += 360;
		
	return angle;
}


function updatePolylines ()
{
	var latlngs = new Array();
	for (var m=0; m<markers.length; m++)
		latlngs[m] = markers[m].getLatLng();
	
	var ang = 0;
	if (!latlngs[0].equals(latlngs[2]) && !latlngs[1].equals(latlngs[2]))
	{
		var lngFactor = Math.cos(deg2rad(latlngs[2].lat()));
		var ang1 = Math.atan2(deg2rad(latlngs[0].lat()) - deg2rad(latlngs[2].lat()), (deg2rad(latlngs[0].lng()) - deg2rad(latlngs[2].lng())) * lngFactor);
		var ang2 = Math.atan2(deg2rad(latlngs[1].lat()) - deg2rad(latlngs[2].lat()), (deg2rad(latlngs[1].lng()) - deg2rad(latlngs[2].lng())) * lngFactor);
		
		if (ang2 < ang1)
			ang = (ang2 + ang1)/2;
		else
			ang = (ang2 + 2 * Math.PI + ang1)/2;
	}
	
	var cameraPositionPx = map.fromLatLngToContainerPixel(latlngs[2]);
	var cameraTargetPx = new GPoint (cameraPositionPx.x + 1000 * Math.sin(ang+Math.PI/2), cameraPositionPx.y + 1000 * Math.cos(ang+Math.PI/2));
	//alert (pixelOrigin.x +','+ pixelOrigin.y);
	
	// remove old lines
	if (polylineFOV) map.removeOverlay(polylineFOV);
	if (polylineHeading) map.removeOverlay(polylineHeading);
		
	// the two red lines that mark the left & right extents of the horizontal field of view
	polylineFOV = new GPolyline([
		latlngs[0],
		latlngs[2],
		latlngs[1]
	], "#ff0000", 4);
	map.addOverlay(polylineFOV);

	// the grey line that points in the direction the photo is heading
	polylineHeading = new GPolyline([
		latlngs[2],
		map.fromContainerPixelToLatLng(cameraTargetPx)
	], "#ffffff", 4);
	map.addOverlay(polylineHeading);
	
	// let's get angle of PL
	// let's get angle of PR
	var P = map.fromLatLngToContainerPixel(latlngs[2]);
	var L = map.fromLatLngToContainerPixel(latlngs[0]);
	var R = map.fromLatLngToContainerPixel(latlngs[1]);
	var PL = rad2deg(Math.atan2 (L.y-P.y,L.x-P.x));
	var PR = rad2deg(Math.atan2 (R.y-P.y,R.x-P.x));
	
	// make sure PR and PL can be subtracted properly
	if (PR-PL < 0)
		PR+=360.0;
	else if (PR-PL > 360)
		PR-=360.0;
		
	// are they correct in terms of left and right?
	if (PR-PL > 180.0)
	{
		var llLeft = markers[0].getLatLng();
		var llRight = markers[1].getLatLng();
		markers[0].setLatLng(llRight);
		markers[1].setLatLng(llLeft);
	}
	
	// delete objects
	delete polylineFOV;
	delete polylineHeading;
	delete cameraPositionPx;
	delete cameraTargetPx;
	delete latlngs;
}


function toggleFave(id)
{
	var id = parseInt(document.getElementById("id").innerHTML);
	var rating = parseInt(document.getElementById("myRating").innerHTML);
	if (rating == 6)
		rating = 0;
	else
		rating = 6;
	var xmlDoc = new window.XMLHttpRequest();
	var reqURL = "/api/0.1/rating.php?id=" + id + "&rating=" + rating;
	
	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 set rating ...");
	else
	{
		rating = xmlResponse.getElementsByTagName("photo")[0].getAttribute("rating");
		document.getElementById("myRating").innerHTML = rating;
		if (rating == 6)
			document.getElementById("fave-star").style.color = 'red';
		else
			document.getElementById("fave-star").style.color = 'lightgrey';
		//alert (rating == 6 ? 'faved' : 'defaved');
	}
}

