function presentXmlResult(
    compass_degrees,
    transmitter_lat,
    transmitter_long,
    transmitter_name,
    transmitter_region,
    signal_quality,
    transmitter2_lat,
    transmitter2_long,
    compass2_degrees,
    transmitter2_name,
    transmitter2_region,
    signal2_quality,
    transmitter3_lat,
    transmitter3_long,
    compass3_degrees,
    transmitter3_name,
    transmitter3_region,
    signal3_quality,
    receiver_lat,
    receiver_long,
    receiver_utm_zone,
    receiver_utm_x,
    receiver_utm_y,
    receiver_region)
{
    if (infowin) {
	map.removeOverlay(infowin);
	infowin = null;
    }
    if (infowin2) {
	map.removeOverlay(infowin2);
	infowin2 = null;
    }
    
    //if (infowin3) {
    //	map.removeOverlay(infowin3);
    //	infowin3 = null;
    //}
    
    if (signal_quality > 0) {      
	// Create our "tiny" marker icon
	icon = rasterconfTransmitterIcon;

	if (recommendedTransmitter) map.removeOverlay(
	    recommendedTransmitter);
	if (transmitterLine)
	    map.removeOverlay(transmitterLine);

	var point = new GLatLng(transmitter_lat, transmitter_long);
	recommendedTransmitter = new GMarker(point, icon, true);
	map.addOverlay(recommendedTransmitter);

	var recPt = new GLatLng(receiver_lat, receiver_long);
	var zoomLevel = currZoom;
	var mapbounds = map.getBounds();
        var sw = mapbounds.getSouthWest();
        var ne = mapbounds.getNorthEast();
	
	// Check if recommended transmitter is outside map at current zoom
	while (point.lat() < sw.lat() || point.lat() > ne.lat() ||
	       point.lng() < sw.lng() || point.lng() > ne.lng())
	{
	    zoomLevel--;
	    if (zoomLevel < MIN_ZOOM_LEVEL) {
		break;
	    }
	    map.setCenter(recPt, zoomLevel);
	    mapbounds = map.getBounds();
            sw = mapbounds.getSouthWest();
	    ne = mapbounds.getNorthEast();
	}

	if (printTransmitterLines == true)
	{
	    transmitterLine = new GPolyline(
	        [previousMarker.getPoint(), point],
	        "#ffffff", 2);
	        map.addOverlay(transmitterLine);
	}
	else {
	    transmitterLine = null;
	}
	
	compass_degrees = Math.round(compass_degrees);

	var div = document.getElementById('container');
	div.innerHTML = '';
	div.style.display = 'block';
	
	if (printReceiverRegion == true && receiver_region != null) {
	    div.innerHTML += '<b>' + lsReceiverRegion + ': </b> ' +
		receiver_region + ' ';
	    //div.innerHTML += '(lat. ' + receiver_lat + '; lng. ' +
	    // receiver_long
	    //    + ')';
	    div.innerHTML += '<br>';
	}

	if (printWhichIsBest == true) {
	    div.innerHTML += '<b>' + lsBestTransmitter + ': </b>';
	}
	if (indoor || printCompassOutdoor == false) {
	    div.innerHTML += transmitter_name;
	    if (printTransmitterRegion == true) {
		div.innerHTML +=
		    ' (' + transmitter_region + ')';
	    }
	}
	else {
	    div.innerHTML += transmitter_name;

	    if (printTransmitterRegion == true) {
		div.innerHTML += ' (' + transmitter_region + ')';
	    }
	    div.innerHTML += ', ' + lsCompassDirection + ' ' +
		compass_degrees + ' ' + lsDegrees;
	}
	
	var dist = point.distanceFrom(previousMarker.getPoint());
	dist = dist/100;
	dist = Math.round(dist);
	dist = dist/10;
	div.innerHTML += ' (' + lsDistance + '  ' + dist + ' km)<br>';

	var infohtml;
        infohtml = transmitter_name;
	if (printWhichIsBest == true) {
	    infohtml += ' (' + lsBest + ')';
	}
	infohtml += '<br>';
	
	if (printTransmitterRegion == true) {
	    infohtml += lsRegion + ': ' + transmitter_region + '<br>';
	} else {
	    infohtml += '<br>';
	}
	if (indoor == false && printCompassOutdoor == true) {
	    infohtml += lsCompassDirection2 + ': ' + compass_degrees;
	}
	
	infowin = new HInfowin(point, infohtml);

	//
	// Now, the 2nd best server
	//

	if (recommendedTransmitter2) {
	    map.removeOverlay(recommendedTransmitter2);
	}
	if (transmitterLine2) {
		map.removeOverlay(transmitterLine2);
	}

	if (getXmlThirdBestServer == true && printReceiverRegion == true) {   
	    if (transmitter_region != receiver_region &&
		transmitter2_region != receiver_region &&
		transmitter3_region != null &&
		transmitter3_region == receiver_region)
		{
		    transmitter2_lat = transmitter3_lat;
		    transmitter2_long = transmitter3_long;
		    compass2_degrees = compass3_degrees; 
		    transmitter2_name = transmitter3_name;
		    transmitter2_region = transmitter3_region;
		    signal2_quality = signal3_quality;
		}
	}
	
	if (signal2_quality > 0) {
	    
	    var point2 = new GLatLng(transmitter2_lat, transmitter2_long);
	    recommendedTransmitter2 = new GMarker(point2, icon, true);
	    map.addOverlay(recommendedTransmitter2);

	    if (printTransmitterLines == true)
	    {
	        transmitterLine2 = new GPolyline(
		    [previousMarker.getPoint(), point2],
		   "#ffffff", 2);
	        map.addOverlay(transmitterLine2);
	    } else {
		transmitterLine2 = null;
	    }

	    compass2_degrees = Math.round(compass2_degrees);

	    if (printWhichIsBest == true) {
		div.innerHTML += '<b>' + lsAlternativeTransmitter + ': </b>';
	    }
	    if (indoor || printCompassOutdoor == false) {
		div.innerHTML += transmitter2_name;
		if (printTransmitterRegion == true) {
		    div.innerHTML += ' (' + transmitter2_region + ')';
		}
	    }
	    else {
		div.innerHTML += transmitter2_name;
		if (printTransmitterRegion == true) {
		    div.innerHTML += ' (' + transmitter2_region + ')';
		}
		div.innerHTML += ', ' + lsCompassDirection + ' ' +
		    compass2_degrees + ' ' + lsDegrees;
	    }
	    var dist2 = point2.distanceFrom(previousMarker.getPoint());
	    dist2 = dist2/100;
	    dist2 = Math.round(dist2);
	    dist2 = dist2/10;
	    div.innerHTML += ' (' + lsDistance + '  ' + dist2 + ' km)<br>';

	    var infohtml2;
	    infohtml2 = transmitter2_name;
	    if (printWhichIsBest == true) {
		infohtml2 += ' (' + lsAlternative + ')';
	    }
	    infohtml2 += '<br>';
	    
	    if (printTransmitterRegion == true) {
		infohtml2 += lsRegion + ': ' + transmitter2_region + '<br>';
	    } else {
		infohtml2 += '<br>';
	    }
	    if (indoor == false && printCompassOutdoor == true) {
		infohtml2 += lsCompassDirection2 + ': ' + compass2_degrees;
	    }
	    
	    infowin2 = new HInfowin(point2, infohtml2);
	}

	//
	// Now, the 3rd best server
	//
	// if (recommendedTransmitter3) {
// 	    map.removeOverlay(recommendedTransmitter3);
// 	}
// 	if (transmitterLine3) {
// 		map.removeOverlay(transmitterLine3);
// 	}
// 	if (signal3_quality > 0) {
	    
// 	    var point3 = new GLatLng(transmitter3_lat, transmitter3_long);
// 	    recommendedTransmitter3 = new GMarker(point3, icon, true);
// 	    map.addOverlay(recommendedTransmitter3);

// 	    transmitterLine3 = new GPolyline(
// 		[previousMarker.getPoint(), point3],
// 		"#ffffff", 2);

// 	    map.addOverlay(transmitterLine3);

// 	    compass3_degrees = Math.round(compass3_degrees);

// 	    div.innerHTML += '<b>' + lsAlternativeTransmitter + ': </b>';
// 	    if (indoor) {
// 		div.innerHTML += transmitter3_name;
// 	    }
// 	    else {
// 		div.innerHTML += transmitter3_name +
// 		', ' + lsCompassDirection + ' ' + compass3_degrees + 
// 		    ' ' + lsDegrees;
// 	    }
// 	    var dist3 = point3.distanceFrom(previousMarker.getPoint());
// 	    dist3 = dist3/100;
// 	    dist3 = Math.round(dist3);
// 	    dist3 = dist3/10;
// 	    div.innerHTML += ' (' + lsDistance + '  ' + dist3 + ' km)<br>';

// 	    var infohtml3;
// 	    infohtml3 = transmitter3_name + ' (' + lsAlternative + ')<br>';
// 	    infohtml3 += lsRegion + ': ' + transmitter3_region + '<br>';
// 	    if (!indoor) {
// 		infohtml3 += lsCompassDirection2 + ': ' + compass3_degrees;
// 	    }
	    
// 	    infowin3 = new HInfowin(point3, infohtml3);
// 	}

// 	if (infowin3) {
// 	    map.addOverlay(infowin3);
// 	}
	
	if (infowin2) {
	    map.addOverlay(infowin2);
	}

	if (infowin) {
	    map.addOverlay(infowin);
	}
    } else {
	showWeakOrZero();
    }
    showDisclaimer();
}

var handleSuccess = function(o) {
    // Beware, test error handling in Chrome and IE8 since browsers
    // behave differently!
 
    if  (o.responseXML && o.responseText != null && o.responseText != "") {
	var root = null;
	var dbq_status = null;
	var dbq_status_as_string = null;
	root = o.responseXML.documentElement;
	if (root != null && o.responseText != "") {
	    dbq_status = root.getElementsByTagName(
		'dbq_status')[0].firstChild.nodeValue;	    
	    dbq_status_as_string = root.getElementsByTagName(
		'dbq_status_as_string')[0].firstChild.nodeValue;
	    // GLog.write(dbq_status_as_string);
	}
	if (dbq_status != null && dbq_status == 1) {
	    // i.e. DBQ_OK
	    var compass_degrees = root.getElementsByTagName(
		'compass_degrees')[0].firstChild.nodeValue;
	    var transmitter_lat = root.getElementsByTagName(
		'transmitter_lat')[0].firstChild.nodeValue;
	    var transmitter_long = root.getElementsByTagName(
		'transmitter_long')[0].firstChild.nodeValue;

	    var transmitter_name = root.getElementsByTagName(
		'transmitter_name')[0].firstChild.nodeValue;
	    var elemTmp = root.getElementsByTagName(
		'transmitter_region')[0].firstChild;
	    var transmitter_region;
	    if (elemTmp != null) {
	        transmitter_region = elemTmp.nodeValue;
	    } else {
		transmitter_region = '';
	    }
	    var signal_quality = root.getElementsByTagName(
		'signal_quality')[0].firstChild.nodeValue;

	    // Now, get the 2nd best server
	    var transmitter2_lat = root.getElementsByTagName(
		'transmitter2_lat')[0].firstChild.nodeValue;
	    var transmitter2_long = root.getElementsByTagName(
		'transmitter2_long')[0].firstChild.nodeValue;
	    var compass2_degrees = root.getElementsByTagName(
		'compass2_degrees')[0].firstChild.nodeValue;
	    var transmitter2_name = root.getElementsByTagName(
		'transmitter2_name')[0].firstChild.nodeValue;
	    var elemTmp = root.getElementsByTagName(
		'transmitter2_region')[0].firstChild;
	    var transmitter2_region;
	    if (elemTmp != null) {
	        transmitter2_region = elemTmp.nodeValue;
	    } else {
		transmitter2_region = '';
	    }
	    var signal2_quality = root.getElementsByTagName(
		'signal2_quality')[0].firstChild.nodeValue;
	    
	    // Now, get the 3rd best server
	    var transmitter3_lat = null;
	    var transmitter3_long = null;
	    var compass3_degrees = null;
	    var transmitter3_name = null;
	    var elemTmp = null;
	    var transmitter3_region = null;
	    var signal3_quality = null;
	    
	    if (getXmlThirdBestServer == true) {
		var transmitter3_lat = root.getElementsByTagName(
		    'transmitter3_lat')[0].firstChild.nodeValue;
		var transmitter3_long = root.getElementsByTagName(
		    'transmitter3_long')[0].firstChild.nodeValue;
		var compass3_degrees = root.getElementsByTagName(
		    'compass3_degrees')[0].firstChild.nodeValue;
		var transmitter3_name = root.getElementsByTagName(
		    'transmitter3_name')[0].firstChild.nodeValue;
		var elemTmp = root.getElementsByTagName(
		    'transmitter3_region')[0].firstChild;
		if (elemTmp != null) {
		    transmitter3_region = elemTmp.nodeValue;
		} else {
		    transmitter3_region = '';
		}
		var signal3_quality = root.getElementsByTagName(
		    'signal3_quality')[0].firstChild.nodeValue;
	    }
	    
	    // Now, receiver data
	    var receiver_lat = root.getElementsByTagName(
		'receiver_lat')[0].firstChild.nodeValue;
	    var receiver_long = root.getElementsByTagName(
		'receiver_long')[0].firstChild.nodeValue;
	    var receiver_utm_zone = root.getElementsByTagName(
		'receiver_utm_zone')[0].firstChild.nodeValue;
	    var receiver_utm_x = root.getElementsByTagName(
		'receiver_utm_x')[0].firstChild.nodeValue;
	    var receiver_utm_y = root.getElementsByTagName(
		'receiver_utm_y')[0].firstChild.nodeValue;
	    var receiver_region = null;
	    if (printReceiverRegion == true) {
	        receiver_region =
		    root.getElementsByTagName(
			'receiver_region')[0].firstChild.nodeValue;
	    }
	}
	else {
	    removeSmallOverlays();
	    if (dbq_status != null && dbq_status == 2) {
		if (dbq_status_as_string != "DBQ_FAILED_OUTSIDE_MAP") {
		    alert("Mismatch between error code and error code " + 
                          "as string, maybe error codes changed on " + 
                          "server side?");
		}
		showWeakOrZero();
	    } else {
		// Other error, just clear the info window.
		    div.innerHTML = '';
		    div.style.display = 'none';
	    }
	    var errmsg = null;
	    var info = null;
	    info = root.getElementsByTagName(
		'info')[0].firstChild.nodeValue;
	    if (dbq_status_as_string != null && info != null) {
		// GLog.write("error info: " + info);
	    }
	    // GLog.write(o.responseText);
	    //if (o.statusText) {
	    //	errmsg = invalidResponse + "\nHTTP status: " + o.statusText +
            //		    "\n" + "HTTP headers:\n" + o.getAllResponseHeaders;
	    //}
	    //else {
            //		errmsg = invalidResponse;
	    //}
	    //GLog.write(errmsg);
	    return;
	}
    }
    else {
	// Should happen rarely, server code was re-written to 
        // convert e.g. exceptions to an error code in the XML.
	var errmsg = null;
	if (o.statusText) {
		errmsg = invalidResponse + "\nHTTP status: " + o.statusText +
		    "\n" + "HTTP headers:\n" + o.getAllResponseHeaders;
	} else {
	    errmsg = invalidResponse;
	}
	return;
    }

    presentXmlResult(
	compass_degrees,
	transmitter_lat,
	transmitter_long,
	transmitter_name,
	transmitter_region,
	signal_quality,
	transmitter2_lat,
	transmitter2_long,
	compass2_degrees,
	transmitter2_name,
	transmitter2_region,
	signal2_quality,
	transmitter3_lat,
	transmitter3_long,
	compass3_degrees,
	transmitter3_name,
	transmitter3_region,
	signal3_quality,
	receiver_lat,
	receiver_long,
	receiver_utm_zone,
	receiver_utm_x,
	receiver_utm_y,
	receiver_region);
    
} // end function handleSuccess


function updateCoverageOverlay() {
    map.removeOverlay(currTileLayer);
    map.addOverlay(currTileLayer);
}

function removeDisclaimer()
{
    var discldiv = document.getElementById('disclaimer');
    discldiv.innerHTML = '';
    discldiv.style.display = 'none';
}
    
var handleFailure = function(o) {
    alert(noResponse + "; " + o.statusText);
}

function showWeakOrZero() {
    var div = document.getElementById('container');
    if (recommendedTransmitter) {
	map.removeOverlay(recommendedTransmitter);
    }
    if (transmitterLine) {
	map.removeOverlay(transmitterLine);
    }
    if (recommendedTransmitter2) {
	map.removeOverlay(recommendedTransmitter2);
    }
    if (transmitterLine2) {
	map.removeOverlay(transmitterLine2);
    }

    //    if (recommendedTransmitter3) {
    //	map.removeOverlay(recommendedTransmitter2);
    //    }
    //if (transmitterLine3) {
    //	map.removeOverlay(transmitterLine2);
    //    }
    
    div.innerHTML = '';
    div.style.display = 'block';

    //div.innerHTML += '<b>No reception</b><br />';
    //div.innerHTML += 'Weak or zero signal.<br />';

    div.innerHTML += '<b>Ingen dækning</b><br />';
    div.innerHTML += 'Ingen signal.<br />';
}

function showDisclaimer()
{
    var discldiv = document.getElementById('disclaimer');
    discldiv.style.display = 'block';
    discldiv.innerHTML = '';
    
    var htmltext = '';
    htmltext += lsDisclaimerAndLink;
    discldiv.innerHTML += htmltext;
}


var callback =
{
  success: handleSuccess,
  failure: handleFailure,
  argument: { foo:"foo", bar:"bar" }
};

function showAddressDelayed(address)
{
    var mindelay = 2000; // min delay between geocode reqs in millisecs
    var delay = null;
    var msdiff = null;
    var geocodeDate = new Date();
    var nowMillisec = geocodeDate.getTime();
    
    if (prevGeocodeMillisec != null) {
	msdiff = nowMillisec - prevGeocodeMillisec;
    }
    if (msdiff != null && msdiff < mindelay) {
	delay = mindelay - msdiff;
	
	if (geocodeTimeout != null) {
	    // E.g. if search button pressed many times quickly
	    clearTimeout(geocodeTimeout);
        }
        geocodeTimeout = window.setTimeout(function() {
		showAddress(address); }, delay);
	dbgDelay = delay;
    }
    else {
	// Call showAddress right away
	dbgDelay = null;
	showAddress(address);
    }
}

// ====== Geocoding ======
function showAddress(address)
{
    geocodeTimeout = null;
    var geocodeDate = new Date();
    var nowMillisec = geocodeDate.getTime();
    prevGeocodeMillisec = nowMillisec;
    var geocodeDate = new Date();
    // ====== Perform the Geocoding ======
    geocoder.getLocations(address, function (result)
    {
	map.clearOverlays(); 
	if (result.Status.code == G_GEO_SUCCESS) {
	    // ===== If there was more than one result, "ask did you mean" on them all =====
	    if (result.Placemark.length > 1) {
		var htmltext = '';

		htmltext += "<div class='bulk'><b>" + lsDidYouMean +
		    ':</b><br>';
		// Loop through the results
		for (var i = 0; i < result.Placemark.length; i++) {
		    var p = result.Placemark[i].Point.coordinates;
		    accuracy = result.Placemark[i].AddressDetails.Accuracy;
		    if (accuracy >= 6) {
			zoomLevel = 12;
		    } else {
			zoomLevel = 10;
		    }
		    htmltext += "<br>"+(i+1)+
			": <a href='javascript:requestInfoLatLng("
			+ p[1] + "," + p[0] + "," + zoomLevel +
			")' class='searchlinks'>" +
			result.Placemark[i].address +
			"<\/a>";
		}
		htmltext += '</div>';
		var mapbounds = map.getBounds();
		var sw = mapbounds.getSouthWest();
		var ne = mapbounds.getNorthEast();
		var ypos = sw.lat() + (ne.lat()-sw.lat())*0.45;
		var xpos = sw.lng() + (ne.lng()-sw.lng())*0.45;
		imarker = new GMarker(
		    new GLatLng(ypos,
				xpos)
		    );
               
	        imarker.openExtInfoWindow(
		    map, 
		    "custom_info_window_nobeak",
		    htmltext,
		    {beakOffset: 0}
		    );
	  
		updateCoverageOverlay();
	    }
	    // ===== If there was a single marker =====
	    else {
		point = new GLatLng(
		    result.Placemark[0].Point.coordinates[1],
                    result.Placemark[0].Point.coordinates[0]);
		accuracy =
		    result.Placemark[0].AddressDetails.Accuracy;
		if (accuracy >= 6) {
		    zoomLevel = 12;
		} else {
		    zoomLevel = 10;
		}
		requestInfo(point, zoomLevel);
	    }
	}
	// ====== Decode the error status ======
	else {
	    var reason="Code "+result.Status.code;
	    if (reasons[result.Status.code]) {
		reason = reasons[result.Status.code]
		    } 
	    alert(lsCouldNotFind +  '"' + address +
		  '". ' +  lsErrorCode + '; ' + reason);
	    updateCoverageOverlay();
	}
    });
}

function requestInfoLatLng(lat, lng, zoomLevel) {
    map.getExtInfoWindow().remove();
    var pt = new GLatLng(lat, lng);
    requestInfo(pt, zoomLevel);
}

function requestInfo(point, zoomLevel)
{
    if (!point) {
	return;
    } else {
	removeSmallOverlays();
	var marker = new GMarker(point, options);
	map.addOverlay(marker);
	previousMarker = marker;
	map.panTo(point);
	updateCoverageOverlay();
	//window.setTimeout(function() {
	//	map.setCenter(point, zoomLevel); }, 1000);
	map.setCenter(point, zoomLevel);
	map.addOverlay(previousMarker);
	var request = YAHOO.util.Connect.asyncRequest(
	    'GET', getURL(point), callback); 
    }
}


