//<![CDATA[
	var map, polygon, line, midpoint;
	var zoomLen = new Array(
		2, 2, 2, 2, //  0 -  3
		4, 4, 4, 4, //  4 -  7
		6, 6, 6, 6, //  8 - 11
		8, 8, 8, 8, // 12 - 15
		10, 10, // 16 - 17
		10, 10, // (18 - 19) ***
		10, 10, // (20 - 21)
		10, 10  // ...
	);
	var bearing, rev_bearing;
	var midlat, midlon;
	var no_zoom;

	function loadMap() {

		if (GBrowserIsCompatible()) {
			map = new GMap2(
				document.getElementById('divMap'),
				{draggableCursor: 'crosshair', draggingCursor: 'pointer'}
			);
			map.addMapType(G_PHYSICAL_MAP);
			var mapControl = new GMapTypeControl();
			map.addControl(mapControl);
			map.addControl(new GLargeMapControl());
			map.setCenter(new GLatLng(30, 10), 2);
			map.enableScrollWheelZoom();
			GEvent.addListener(map, "click",
				function (overlay, latlng) {
					if (latlng) {
						if (polygon) {
							map.removeOverlay(polygon);
							polygon = null;
						}
						if (midpoint) {
						  map.removeOverlay(midpoint);
						  midpoint = null;
						}
						if (line) {
							map.removeOverlay(line);
							line = null;
						}
						qth = returnQth(latlng.lat(), latlng.lng());
						z = map.getZoom();
						polygon = new GPolyline(
							[
								fromQth(
									qth.substring(0, zoomLen[z] - 2) +
									qth.substring(zoomLen[z] - 2, zoomLen[z] - 1) +
									qth.substring(zoomLen[z] - 1, zoomLen[z]) +
									"00AA00AA".substring(zoomLen[z] - 2)
								),
								fromQth(
									qth.substring(0, zoomLen[z] - 2) +
									chr(1 + qth.charCodeAt(zoomLen[z] - 2)) +
									qth.substring(zoomLen[z] - 1, zoomLen[z]) +
									"00AA00AA".substring(zoomLen[z] - 2)
								),
								fromQth(
									qth.substring(0, zoomLen[z] - 2) +
									chr(1 + qth.charCodeAt(zoomLen[z] - 2)) +
									chr(1 + qth.charCodeAt(zoomLen[z] - 1)) +
									"00AA00AA".substring(zoomLen[z] - 2)
								),
								fromQth(
									qth.substring(0, zoomLen[z] - 2) +
									qth.substring(zoomLen[z] - 2, zoomLen[z] - 1) +
									chr(1 + qth.charCodeAt(zoomLen[z] - 1)) +
									"00AA00AA".substring(zoomLen[z] - 2)
								),
								fromQth(
									qth.substring(0, zoomLen[z] - 2) +
									qth.substring(zoomLen[z] - 2, zoomLen[z] - 1) +
									qth.substring(zoomLen[z] - 1, zoomLen[z]) +
									"00AA00AA".substring(zoomLen[z] - 2)
								),
							],
							"#ff0000",
							1,
							0.5
						);
						map.addOverlay(polygon);
						/* *** */
						var qthDstval = document.getElementById('qthDst').value;
						var addFrom = '';
						if (qthDstval) {
							addFrom = "&from=" + qthDstval;
						}
						var infoText =
							'<div class="info">Latitude: ' +
								(Math.round(latlng.lat()*1000000)/1000000) +
							"&nbsp; Longitude: " +
								(Math.round(latlng.lng()*1000000)/1000000) +
							"<br />Locator: <b>"
							+ "<a href='?"
							+ "qth="	+ qth.substring(0, zoomLen[z])
							+ addFrom
							+ "' target='_top'>"
							+ qth.substring(0, zoomLen[z]) + "</a></b>"
							+ "&nbsp; (<a href='?qth="
							+ qth.substring(0, zoomLen[z])
							+ addFrom
							+ "&t=n"
							+ "' target='_top'>map</a>"
							+ ", <a href='?qth="
							+ qth.substring(0, zoomLen[z])
							+ addFrom
							+ "&t=s"
							+ "' target='_top'>sat</a>"
							+ ", <a href='?qth="
							+ qth.substring(0, zoomLen[z])
							+ addFrom
							+ "&t=t"
							+ "' target='_top'>terrain</a>"
							+ ")</div>"
						;
						qthDst = document.getElementById('qthDst').value.toUpperCase();
						if (qthDst && qthDst != qth.substring(0, zoomLen[z])) {
							var dst = distanceFrom(qth.substring(0, zoomLen[z]), qthDst)/1000;
							infoText +=
								'<div class="info">Distance from <b>' + qthDst + '</b> - '
								+ "<b>" + Math.round(1000*dst)/1000 + " km</b>"
								+ " (" + Math.round(100*dst/1.609344)/100 + " mi)<br />"
								+ "Bearing ~ <b>" + bearing + "&deg;</b> (reverse bearing ~ "
								+ rev_bearing + "&deg;)<br/>"
								+ "Midpoint - lat: " +
									(Math.round(midlat*1000000)/1000000)
								+ " lon: " +
									(Math.round(midlon*1000000)/1000000)
								+ "</div>"
							;
					    var newIcon = MapIconMaker.createFlatIcon(
								{width: 10, height: 10, primaryColor: "#ff0000"}
							);
							var point = new GLatLng(midlat, midlon);
					    midpoint = new GMarker(point, {icon: newIcon});
					    map.addOverlay(midpoint);
						}

						map.openInfoWindow(
							fromQth(
								qth.substring(0, zoomLen[z] - 2) +
								chr(1 + qth.charCodeAt(zoomLen[z] - 2)) +
								chr(1 + qth.charCodeAt(zoomLen[z] - 1)) +
								"00AA00AA".substring(zoomLen[z] - 2)
							),
							infoText
						);
						document.getElementById('qthTxt').value =
							qth.substring(0, zoomLen[z]);
						/* *** */
					}
				}
			);

			if (type = getParam('t')) {
				switch (type) {
					case 'p': // deprecated
					case 'n':
						map.setMapType(G_NORMAL_MAP);
						break;
					case 's':
						map.setMapType(G_SATELLITE_MAP);
						break;
					case 't':
						map.setMapType(G_PHYSICAL_MAP);
						break;
					default:
					case 'h':
						map.setMapType(G_HYBRID_MAP);
				}
			}
			else {
				map.setMapType(G_HYBRID_MAP);
			}
			if (from = getParam('from')) {
				document.getElementById('qthDst').value = from;
			}
			if (qth = getParam('qth')) {
            document.cookie = "QTH=" + escape(qth);
				findQth(qth);
			}

		} // compatible

		no_zoom = true;

	} // loadMap()

	function getParam(name) {
		name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
		var regexS = "[\\?&]" + name + "=([^&#]*)";
		var regex = new RegExp(regexS);
		var results = regex.exec(window.location.href);
		if(results == null)
			return '';
		else
			return results[1];
	}

	function chr(x) { return String.fromCharCode(x); }
	function floor(x) { return Math.floor(x); }

	function returnQth(lat, lng) {
		var qth = '';
		lat += 90; lng += 180;
		lat = lat / 10 + 0.0000001;
		lng = lng / 20 + 0.0000001;
		qth += chr(65 + lng) + chr(65 + lat);
		lat = 10 * (lat - floor(lat));
		lng = 10 * (lng - floor(lng));
		qth += chr(48 + lng) + chr(48 + lat);
		lat = 24 * (lat - floor(lat));
		lng = 24 * (lng - floor(lng));
		qth += chr(65 + lng) + chr(65 + lat);
		lat = 10 * (lat - floor(lat));
		lng = 10 * (lng - floor(lng));
		qth += chr(48 + lng) + chr(48 + lat);
		lat = 24 * (lat - floor(lat));
		lng = 24 * (lng - floor(lng));
		qth += chr(65 + lng) + chr(65 + lat);
		return qth;
	} // returnQth()

	function fromQth(qth) {
			var i = 0;
			var l = new Array();
			qth = qth.toUpperCase();
			while (i < 10) l[i] = qth.charCodeAt(i++) - 65;
			l[2] += 17; l[3] += 17;
			l[6] += 17; l[7] += 17;
			var lng = (l[0]*20 + l[2]*2 + l[4]/12 + l[6]/120 + l[8]/2880 - 180);
			var lat = (l[1]*10 + l[3] + l[5]/24 + l[7]/240 + l[9]/5760 - 90);
			return new GLatLng(lat, lng);
	} // fromQth()

	function findQth(qth) {
		if (GBrowserIsCompatible()) {
			if (qth) {
				qth = qth.toUpperCase();
			}
			else {
				qth = document.getElementById('qthTxt').value.toUpperCase();
			}
			qthLen = qth.length;
			if (qthLen < 4)  qth += '55LL55LL';
			if (qthLen < 6)  qth += 'LL55LL';
			if (qthLen < 8)  qth += '55LL';
			if (qthLen < 10) qth += 'LL';
			var qthFormat = /[A-R]{2}[0-9]{2}[A-X]{2}[0-9]{2}[A-X]{2}/;
			if (qthFormat.test(qth)) {
				z = qthLen * 2 - 1;
				if (z > 17)	map.setZoom(17);
				else map.setZoom(z);
				map.setCenter(fromQth(qth));
				GEvent.trigger(map, "click", null, fromQth(qth));
			} else {
				window.alert('Enter either 2, 4, 6, 8 or 10 valid characters.');
			}
		} // browser compatible
		return false;
	} // findQth()
	
	function swap() {
		qth = document.getElementById('qthTxt').value;
		document.getElementById('qthTxt').value =
			document.getElementById('qthDst').value;
		document.getElementById('qthDst').value = qth;
	}
	function distanceFrom(qth, dst) {
		dstLen = dst.length;
		qthLen = qth.length;
		if (dstLen < 4)  dst += '00AA00AA';
		if (dstLen < 6)  dst += 'AA00AA';
		if (dstLen < 8)  dst += '00AA';
		if (dstLen < 10) dst += 'AA';
		var qthFormat = /[A-R]{2}[0-9]{2}[A-X]{2}[0-9]{2}[A-X]{2}/;
		if (qthFormat.test(dst)) {
			var dstQth1 = fromQth(dst);
			var dstQth2 = fromQth(
				dst.substring(0, dstLen - 2) +
				chr(1 + dst.charCodeAt(dstLen - 2)) +
				chr(1 + dst.charCodeAt(dstLen - 1)) +
				"00AA00AA".substring(dstLen - 2)
			);
			var dstQth = new GLatLng(
				(dstQth1.lat() + dstQth2.lat()) / 2,
				(dstQth1.lng() + dstQth2.lng()) / 2
			);
			var qthQth1 = fromQth(qth + "00AA00AA".substring(qthLen - 2));
			var qthQth2 = fromQth(
				qth.substring(0, qthLen - 2) +
				chr(1 + qth.charCodeAt(qthLen - 2)) +
				chr(1 + qth.charCodeAt(qthLen - 1)) +
				"00AA00AA".substring(qthLen - 2)
			);
			var qthQth = new GLatLng(
				(qthQth1.lat() + qthQth2.lat()) / 2,
				(qthQth1.lng() + qthQth2.lng()) / 2
			);
			var polyOptions = {geodesic:true};
			line = new GPolyline(
				[
					dstQth,
					qthQth
				],
				"#00ff00",
				2,
				0.8,
				polyOptions
			);
			var bounds = line.getBounds();
			if (! no_zoom) {
	    	map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds) - 1);
	    	no_zoom = true;
			}
			map.addOverlay(line);

			/* bearing */

			lat1 = dstQth.lat();
			lon1 = dstQth.lng();
			lat2 = qthQth.lat();
			lon2 = qthQth.lng();

			dLon = (lon2-lon1).toRad();

			var y = Math.sin(dLon) * Math.cos(lat2.toRad());
			var x = Math.cos(lat1.toRad())*Math.sin(lat2.toRad()) -
			        Math.sin(lat1.toRad())*Math.cos(lat2.toRad())*Math.cos(dLon);

			bearing = Math.round(100 * ((Math.atan2(y, x).toDeg() + 360.0) % 360.0)) / 100;

			var Bx = Math.cos(lat2.toRad()) * Math.cos(dLon);
			var By = Math.cos(lat2.toRad()) * Math.sin(dLon);
			midlat = (Math.atan2(Math.sin(lat1.toRad())+Math.sin(lat2.toRad()),
			                      Math.sqrt( (Math.cos(lat1.toRad())+Bx)*(Math.cos(lat1.toRad())+Bx) + By*By) )).toDeg();
			midlon = (lon1.toRad() + Math.atan2(By, Math.cos(lat1.toRad()) + Bx)).toDeg();

			dLon = (lon1-lon2).toRad();

			var y = Math.sin(dLon) * Math.cos(lat1.toRad());
			var x = Math.cos(lat2.toRad())*Math.sin(lat1.toRad()) -
			        Math.sin(lat2.toRad())*Math.cos(lat1.toRad())*Math.cos(dLon);

			rev_bearing = Math.round(100 * ((Math.atan2(y, x).toDeg() + 360.0) % 360.0)) / 100;

			return qthQth.distanceFrom(dstQth);

		} else {
			window.alert('From locator should be 2, 4, 6, 8 or 10 valid characters.');
			return 0;
		}
	}
	function setFrom(qth) {
		document.getElementById('qthDst').value = qth;
	}

	/** Convert numeric degrees to radians */
	if (typeof(String.prototype.toRad) === "undefined") {
	  Number.prototype.toRad = function() {
	    return this * Math.PI / 180;
	  }
	}

	/** Convert radians to numeric (signed) degrees */
	if (typeof(String.prototype.toDeg) === "undefined") {
	  Number.prototype.toDeg = function() {
	    return this * 180 / Math.PI;
	  }
	}

//]]>

