var map = null;
var geocoder = null;
var cp = null;
var markers = new Object();

var icon = new GIcon();
icon.image = "/images/mappery-marker.png";
icon.shadow = "/images/shadow-mappery-marker.png";
icon.iconSize = new GSize(18, 19);
icon.shadowSize = new GSize(28, 19);
icon.iconAnchor = new GPoint(9, 9);
icon.infoWindowAnchor = new GPoint(9, 9);

function loadCoder() {
	geocoder = new GClientGeocoder();
}

// report map changes to document at large
function map_changed() {
	if (map != null) {
		var mapchanged = jQuery.Event('mapchanged');
		mapchanged.lat = map.getCenter().lat();
		mapchanged.lng = map.getCenter().lng();
		mapchanged.zoom = map.getZoom();
		$(document).trigger(mapchanged);
	}
}

function load() {
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GLargeMapControl3D());
		map.addControl(new GHierarchicalMapTypeControl());
                map.addMapType(G_PHYSICAL_MAP);
		map.addMapType(G_SATELLITE_3D_MAP);
		map.addControl(new GScaleControl());
		map.enableDoubleClickZoom();
		map.enableContinuousZoom();

		var form = $("#add")[0];
		var _lat = (typeof(form.mapLat.value) == 'undefined' || form.mapLat.value == "") ? 46 : parseFloat(form.mapLat.value);
		var _long = (typeof(form.mapLong.value) == 'undefined' || form.mapLong.value == "") ? -31 : parseFloat(form.mapLong.value);
		var _zoom = (typeof(form.mapZoom.value) == 'undefined' || form.mapZoom.value == "") ? 2 : parseInt(form.mapZoom.value);
		map.setCenter(new GLatLng(_lat, _long), _zoom);
		geocoder = new GClientGeocoder();

		// on stop drag of the map, update geo ads and reverse-geocode
		var _reverse_geocoder = undefined;
		GEvent.addListener(map, "moveend", function(){
			setTimeout(function(){getMapInfo(form)}, 10);// run async so map not bogged down
			if (_reverse_geocoder
			   && _reverse_geocoder.readyState > 0
			   && _reverse_geocoder.readyState < 4)
			{
				_reverse_geocoder.abort();
			}
			$("#reverse-geocoding").val("y");// mark for server
			_reverse_geocoder = $.getJSON("/geographical.php?reverse-geocode-json&lat="+map.getCenter().lat()+"&lng="+map.getCenter().lng(), reverseGeocode);
			map_changed();
			return false;
		});
	}
}

// put this as the hidden input
function reverseGeocode(doc) {
	$("#reverse-geocoding").val("n");// mark for server
	//console.info("Reverse geocoded: "+doc);
	//var jsonData = eval('(' + doc + ')');
	var jsonData = doc;
	loc = "";
	if (jsonData.geonames[0]) with (jsonData.geonames[0]) {
        	$("#add [name=countryCode]").val(countryCode);
	        $("#add [name=adminName]").val(adminName1);
        	$("#add [xbname=cityName]").val(cityName);
	        $("#add [name=cityID]").val(cityID);
		var name = (cityName ? cityName+", " : "");
		if (countryName == "United States")
			loc = name+adminName1;
		else
			loc = name+countryName;
	        $("#add [name=alternatePlace]").val(loc);
	}
}

function detail_map_loader() {
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GLargeMapControl3D());
		map.addControl(new GHierarchicalMapTypeControl());
                map.addMapType(G_PHYSICAL_MAP);
		map.addMapType(G_SATELLITE_3D_MAP);
		map.addControl(new GScaleControl());
		map.enableDoubleClickZoom();
		map.enableContinuousZoom();

		var geoLat = document.getElementById('geoLat').childNodes[0].nodeValue;
		var geoLong = document.getElementById('geoLong').childNodes[0].nodeValue;
		var zoomLevel = document.getElementById('zoomLevel').childNodes[0].nodeValue;
		var mapType = document.getElementById('mapType')
		            ? document.getElementById('mapType').childNodes[0].nodeValue
		            : undefined;
		positionDetails(geoLat, geoLong, zoomLevel, mapType);
		geocoder = new GClientGeocoder();
	}
}

function loadDetail() {
	if ($("#map").is(":visible"))
		detail_map_loader();
	else// may happen more than once, but otherwise could get interrupted
		$("#view-chooser .view-toggle a").click(detail_map_loader);
}

function positionDetails(geoLat, geoLong, zoomLevel, mapType) {
	if (typeof(mapType) == 'undefined') mapType = G_NORMAL_MAP;
	else switch (mapType) {
	   case 'hybrid': mapType = G_HYBRID_MAP; break;
	case 'satellite': mapType = G_SATELLITE_MAP; break;
	  case 'terrain': mapType = G_TERRAIN_MAP; break;
	   case 'normal':
	         default: mapType = G_NORMAL_MAP; break;
	}
	if (typeof(icon) == 'undefined') icon = G_DEFAULT_ICON;
	map.setCenter(new GLatLng(geoLat, geoLong), parseInt(zoomLevel), mapType);
	var point = new GLatLng(geoLat, geoLong);
	var marker = new GMarker(point, {icon:icon});
	map.addOverlay(marker);
}

function loadGmap() {
	if (GBrowserIsCompatible()) {
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GLargeMapControl3D());
		map.addControl(new GHierarchicalMapTypeControl());
                map.addMapType(G_PHYSICAL_MAP);
		map.addMapType(G_SATELLITE_3D_MAP);
		map.addControl(new GScaleControl());
		map.enableDoubleClickZoom();
		map.enableContinuousZoom();

		geocoder = new GClientGeocoder();

		loadPoints();
	}
}

function lookUp() {
	var address = $("[name=location]").val();
	if (address.match(/^[ \t\r\n]*$/))
		notify("Fill in an address");
	else if (geocoder) {
		geocoder.getLatLng(address, function(point) {
			if (!point)
				notify(address + " not found");
			else
				map.setCenter(point, 10);
		});
	}
	else	notify("Geocoder not available, can not look up address");
	return false;
}

function compactSearch() { var _search_info_class = "empty";
	var compactsearch = document.forms.compactsearch;
	if ($(compactsearch.kw).hasClass(_search_info_class)) return false;
	var loc_or_kw = compactsearch.kw.value;
	if (loc_or_kw.match(/^[[:space:]]*$/)) return false;
	// try location search first; if it fails try kw search
	if (!geocoder) loadCoder();
	if (geocoder) {
		geocoder.getLatLng(loc_or_kw, function(point){
			if (point) { // location search
				compactsearch.locLat.value = point.lat();
				compactsearch.locLong.value = point.lng();
				// lock to block actions.js inserting info text
				compactsearch.kw.className = "locked";
				compactsearch.kw.value = "";
				// including this with the form interferes with lookUp on the addmaps page
				$(compactsearch).append('<input type="hidden" value="'+loc_or_kw+'" name="location" />');
				compactsearch.submit();
			}
			else // keyword search
				compactsearch.submit();
		});
	}
	else	compactsearch.submit(); // keyword search
	return false;
}

function searchLoc() {
	if (geocoder) {
		var address = document.forms.search.location.value;
		if (address != "") {
			geocoder.getLatLng(address, function(point) {
				if (!point)
					notify(address + " not found");
				else {
					document.forms.search.locLat.value = point.lat();
					document.forms.search.locLong.value = point.lng();
					document.forms.search.submit();
				}
			});
		} else
			document.forms.search.submit();
	}
	return false;
}
//<button onclick="javascript:return searchLoc()">Search</button>
function getMapInfo(form) {
	form.mapLat.value = map.getCenter().lat();
	form.mapLong.value = map.getCenter().lng();
	form.mapZoom.value = map.getZoom();
}

var popped_up = false; // shared by all markers
function createMarker(point, title, popup_html, tooltip_html) {
	var marker = new GMarker(point, {/*title:title.toString().replace("&#039;","'"),*/icon:icon});
	var container = document.createElement('div');
	$(container).html(tooltip_html);
	var tooltip = new Tooltip(marker,container,4);
	marker.tooltip = tooltip;
	GEvent.addListener(marker, "click", function() {
		marker.openInfoWindowHtml(popup_html);
	});
	GEvent.addListener(marker, "infowindowopen", function(){
		popped_up = true;
	});
	GEvent.addListener(marker, "infowindowclose", function(){
		popped_up = false;
	});
	GEvent.addListener(marker, 'mouseover', function(){
		if (popped_up == false) {
			this.tooltip.redraw(true);
			this.tooltip.show();
		}
	});
	GEvent.addListener(marker, 'mouseout', function(){ this.tooltip.hide() });
	return marker;
}

function setPointsHome(doc) {
	var jsonData = eval('(' + doc + ')');
	var bounds = new GLatLngBounds;
	for (var i=0; i<jsonData.markers.length; i++) {
		var point = new GLatLng(jsonData.markers[i].lat, jsonData.markers[i].lng);
		bounds.extend(point);
		var marker = createMarker(point, jsonData.markers[i].title, jsonData.markers[i].html, jsonData.markers[i].tooltip_html);
		markers[point] = marker;
		map.addOverlay(marker);
		if (marker.tooltip) map.addOverlay(marker.tooltip);
	}
	newZoom = map.getBoundsZoomLevel(bounds);
	map.setZoom(newZoom > 10 ? newZoom-1 : newZoom);
	if (jsonData.markers.length > 0)
		map.setCenter(bounds.getCenter());
	else
		map.setCenter();
	GEvent.addListener(map, "moveend", function(){
		map_changed();
		refindBounds();
	});
}

// stops gmaps api from breaking console debugging:
//$(document).ready(function(){ console.info("Rolling") });

function setPoints(doc, rezoom) {
	//console.info("Doc: "+doc);
	rezoom = (rezoom == undefined) ? true : rezoom;
	//console.info("Set points "+(rezoom ? "rezoom" : "no zooming"));
	var jsonData = eval('('+doc+')');
	//console.info("Doc: "+doc);
	if (jsonData == null || jsonData.markers.length < 1) {
		//console.info("Evident parsing difficulty");
		// show error
		theUrl = document.location.search.substring(1);
		reg = /kw=([^&#]*)/i;
		errorMsg = "No maps found. Please try again.";
		try {
			kw = decodeURIComponent(theUrl.match(reg)[1]);
			if (kw) errorMsg = "No maps found with keywords "+kw.replace(/\+/g," ")+". Please try again.";
		} catch(e) {};
		var _eb = document.getElementById('errorBlock');
		if (_eb) {
			_eb.innerHTML = errorMsg;
			_eb.style.display = "block";
		}
	} else {
		//console.info("Traversing markers");
		var bounds = new GLatLngBounds;
		for (var i=0; i<jsonData.markers.length; i++) {
			var point = new GLatLng(jsonData.markers[i].lat, jsonData.markers[i].lng);
			bounds.extend(point);
			var marker = createMarker(point, jsonData.markers[i].title, jsonData.markers[i].html, jsonData.markers[i].tooltip_html);
			markers[point] = marker;
			map.addOverlay(marker);
			if (marker.tooltip) map.addOverlay(marker.tooltip);
			//console.info("Added marker "+i);
		}
		//markers.count = jsonData.markers.length;
		if (rezoom) {
			newZoom = map.getBoundsZoomLevel(bounds);
			map.setZoom(newZoom > 10 ? newZoom-1 : newZoom);
		}
		if (jsonData.markers.length > 0)
			map.setCenter(bounds.getCenter());
		else
			map.setCenter();
		map.move_listener = GEvent.addListener(map, "moveend", function(){
			map_changed();
			refindBounds();
		});
	}
}

function setPointsNoNewZoom(doc) { return setPoints(doc, false); }

function setPointsLocal(doc) {
	var jsonData = eval('(' + doc + ')');
	var bounds = new GLatLngBounds;
	for (var i=0; i<jsonData.markers.length; i++) {
		var point = new GLatLng(jsonData.markers[i].lat, jsonData.markers[i].lng);
		bounds.extend(point);
		var marker = createMarker(point, jsonData.markers[i].title, jsonData.markers[i].html, jsonData.markers[i].tooltip_html);
		markers[point] = marker;
		map.addOverlay(marker);
		if (marker.tooltip) map.addOverlay(marker.tooltip);
	}
	GEvent.addListener(map, "moveend", function(){
		map_changed();
		refindBounds();
	});
}

function setHomePoints(doc) {
	var jsonData = eval('(' + doc + ')');
	for (var i=0; i<jsonData.markers.length; i++) {
		var point = new GLatLng(jsonData.markers[i].lat, jsonData.markers[i].lng);
		var marker = createMarker(point, icon, jsonData.markers[i].html, jsonData.markers[i].tooltip_html);
		map.addOverlay(marker);
		if (marker.tooltip) map.addOverlay(marker.tooltip);
	}
}

function resetPoints(doc) {
	var jsonData = eval('(' + doc + ')');
	//console.info("Resetting based on "+doc);
	for (var i=0; i<jsonData.markers.length; i++) {
		var point = new GLatLng(jsonData.markers[i].lat, jsonData.markers[i].lng);
		var marker = createMarker(point, jsonData.markers[i].title, jsonData.markers[i].html, jsonData.markers[i].tooltip_html);
		// if marker doesn't already exist, add it
		if (!markers[point]) {
			map.addOverlay(marker);
			markers[point] = marker;
			if (marker.tooltip) map.addOverlay(marker.tooltip);
		}
	}
}

function setLimitedPointsRezoom(doc) {
	var jsonData = eval('(' + doc + ')');
	//window.console.info("Rezooming...");
	var bounds = new GLatLngBounds;
	for (eachone in markers) {
		if (markers[eachone] != null)
			bounds.extend(markers[eachone].getLatLng());
	}
	var limitedSet = new Object;
	for (var i=0; i<jsonData.markers.length; i++) {
		var point = new GLatLng(jsonData.markers[i].lat, jsonData.markers[i].lng);
		limitedSet[point] = true;
		bounds.extend(point);
		if (!markers[point]) {
			var marker = createMarker(point, jsonData.markers[i].title, jsonData.markers[i].html, jsonData.markers[i].tooltip_html);
			markers[point] = marker;
			map.addOverlay(marker);
			if (marker.tooltip) map.addOverlay(marker.tooltip);
		}
	}
	// clear markers not in limited set
	for (eachone in markers) {
		if (markers[eachone] != null && !limitedSet[eachone]) {
			map.removeOverlay(markers[eachone]);
			if (markers[eachone].tooltip)
				map.removeOverlay(markers[eachone].tooltip);
			markers[eachone] = null;
		}
	}
	//debugger;
	GEvent.removeListener(map.move_listener);
	newZoom = map.getBoundsZoomLevel(bounds);
	map.setZoom(newZoom > 10 ? newZoom-1 : newZoom);
	if (jsonData.markers.length > 0)
		map.setCenter(bounds.getCenter());
	GEvent.addListener(map, "moveend", function(){
		map_changed();
		refindBounds();
	});
}

function removeOutMarkers() {
	theseBounds = map.getBounds();
	for (eachone in markers) {
		if (  markers[eachone] != null
		  && !theseBounds.contains(markers[eachone].getPoint()) ) {
			map.removeOverlay(markers[eachone]);
			if (markers[eachone].tooltip)
				map.removeOverlay(markers[eachone].tooltip);
			markers[eachone] = null;
		}
	}
}

// brute force removal
function clearMarkers() {
	for (eachone in markers) {
		//console.info("Removing "+markers[eachone]);
		if (markers[eachone] != null) {
			map.removeOverlay(markers[eachone]);
			if (markers[eachone].tooltip)
				map.removeOverlay(markers[eachone].tooltip);
			markers[eachone] = null;
		}
	}
}	

// will not work because markers are saved in an object, can not count
function reduceMarkersTo(limit) {
	//console.info("From "+markers.length+" to "+limit)
	for (extra = markers.length; extra > limit; --extra) {
		// check for null and remove
	}
}

function getnext(which, startwith) {
	c = document.getElementById("thing_"+which);
	len = c.childNodes.length - 1;
	c.childNodes[startwith].style.display = "none";
	c.childNodes[startwith+1].style.display = "block";

	// up count
	d = document.getElementById("count_"+which);
	d.getElementsByTagName("span")[0].innerHTML = eval(d.getElementsByTagName("span")[0].innerHTML) + 1;

	// if it doesn't exist already, add "previous" link
	prevlink = document.getElementById("nav_prev");
	if (prevlink.innerHTML == "") {
		prevlink.innerHTML = "&laquo;previous";
	}
	prevlink.setAttribute("href","javascript:getprev("+which+","+(startwith+1)+");");

	nextlink = document.getElementById("nav_next");
	// if there are no more child nodes, remove "next" link
	if (startwith+1 == len) {
		nextlink.innerHTML = "";
		nextlink.setAttribute("href","");
	} else {
		// up the startwith count
		nextlink.setAttribute("href","javascript:getnext("+which+","+(startwith+1)+");");
	}
}

function getprev(which, startwith) {
	c = document.getElementById("thing_"+which);
	len = c.childNodes.length - 1;
	c.childNodes[startwith].style.display = "none";
	c.childNodes[startwith-1].style.display = "block";

	// up count
	d = document.getElementById("count_"+which);
	d.getElementsByTagName("span")[0].innerHTML = eval(d.getElementsByTagName("span")[0].innerHTML) - 1;

	// if it doesn't exist already, add "next" link
	nextlink = document.getElementById("nav_next");
	if (nextlink.innerHTML == "") {
		nextlink.innerHTML = "next&raquo;";
	}
	nextlink.setAttribute("href","javascript:getnext("+which+","+(startwith-1)+");");

	prevlink = document.getElementById("nav_prev");
	// if there are no more child nodes, remove "next" link
	if (startwith == 1) {
		prevlink.innerHTML = "";
		prevlink.setAttribute("href","");
	} else {
		// up the startwith count
		prevlink.setAttribute("href","javascript:getprev("+which+","+(startwith-1)+");");
	}
}

GMap2.prototype.centerAndZoomOnBounds = function(bounds) {
	var center = bounds.getCenter();
	/*var _ne = bounds.getNorthEast();
	var _sw = bounds.getSouthWest();
	//console.info("Showing polyline for "+_ne+" "+_sw);
	this.addOverlay(new GPolyline([ _ne, _sw ]), "#ff0000", 10);*/
	var newZoom = this.getBoundsZoomLevel(bounds, this.viewSize);
	if (this.getZoom() != newZoom) {
		//this.setZoom(newZoom);
		this.setCenter(center, newZoom > 10 ? newZoom - 1 : newZoom);
	}
	else
		this.panTo(center);
}
