var ggeoxml_path;
var map;
var legendDiv;
var currentLang;

var gzoomevent = false;
var gdragevent = false;

var paddedMinX;
var paddedMaxX;
var paddedMinY;
var paddedMaxY;
var scaledZoom;

var ne;
var sw;

var centerX = null;
var centerY = null;
var pastCenterX;
var pastCenterY;

var paddingX;
var paddingY;

var gOverlay;

var address_suffix;

var timer;



function getCenter() {
	pastCenterX = centerX;
	pastCenterY = centerY;

	centerX = map.getCenter().lng();
	centerY = map.getCenter().lat();

	$('#gdebug').append('<p>center: '+centerX+', '+centerY+'</p>');
	$('#gdebug').append('<p>past center: '+pastCenterX+', '+pastCenterY+'</p>');
}

function getZoom(zoomLevel) {
	var zoom;
	if (zoomLevel) zoom = zoomLevel;
	else zoom = map.getZoom();

	// scaled range
	scaledZoom = 100-Math.round(zoom*5.8824);

	$('#gdebug').append('<p>zoom: '+zoom+' ('+scaledZoom+')</p>');
}

function getPaddedEdges() {
	ne = map.getBounds().getNorthEast();
	sw = map.getBounds().getSouthWest();

	var minX = sw.lng();
	var maxY = ne.lat();
	var maxX = ne.lng();
	var minY = sw.lat();

	paddingX = (maxX - minX) * 2;
	paddingY = (maxY - minY) * 2;

	$('#gdebug').append('<p>paddingX: '+paddingX+'<br />paddingY: '+paddingY+'</p>');

	paddedMinX = minX - paddingX;
	paddedMaxX = maxX + paddingX;
	paddedMinY = minY - paddingY;
	paddedMaxY = maxY + paddingY;

	$('#gdebug').append('<p>paddedMinX: '+paddedMinX+'<br />paddedMaxX: '+paddedMaxX+'<br />paddedMinY: '+paddedMinY+'<br />paddedMaxY: '+paddedMaxY+'</p>');
}

/*
function getRange() {
    var nw = new GLatLng(maxY, minX);
    var se = new GLatLng(minY, maxX);

    var mapMetersX = sw.distanceFrom(se);
    var mapMetersY = sw.distanceFrom(nw);

    var mapMaxMeters = mapMetersY;
    if (mapMetersX < mapMetersY) mapMaxMeters = mapMetersX;
    mapRange = mapMaxMeters/3;
	var scaledRange = Math.round(mapRange/100)*100;

    // range hack
    if (scaledRange < 1 || scaledRange > 2000000) scaledRange = 2000000;

	$('#gdebug').append('<p>nw: '+nw+'<br />ne: '+ne+'<br />se: '+se+'<br />sw: '+sw+'</p>');
    $('#gdebug').append('<p>mapMetersX: '+mapMetersX+'<br />mapMetersY: '+mapMetersY+'</p>');
    $('#gdebug').append('<p>range: '+mapRange+' ('+scaledRange+')</p>');
}
*/

function setupEnviroment(newZoomLevel) {
	$('#gdebug').empty();

	getCenter();
	getZoom(newZoomLevel);
	getPaddedEdges();
	//getRange();
}

function zoomToViewport(minX, maxX, minY, maxY) {
	var bounds = new GLatLngBounds;
	bounds.extend(new GLatLng(minY,minX));
	bounds.extend(new GLatLng(maxY,maxX));

	var current_center = bounds.getCenter();
	var current_zoom_level = map.getBoundsZoomLevel(bounds);

	map.setCenter(current_center, current_zoom_level);
}

// a causa di un'incompatibilitù fra gmap e jquery
// document.ready() causa random una bordo grigio
window.onload=function(){
	ggeoxml_path = $('#ggeoxml_path').val();

	var mapDiv = $('#gmap').get(0);
	var mapConfigX = parseFloat($('#gmap_config_x').val());
	var mapConfigY = parseFloat($('#gmap_config_y').val());
	var mapConfigZoom = parseInt($('#gmap_config_zoom').val());
	currentLang = $('#currentLang').val();

	legendDiv = $('#glegend').get(0);
	address_suffix = $('#gaddress_suffix').val();

	map = new GMap2(mapDiv);
	map.setCenter(new GLatLng(mapConfigY,mapConfigX), mapConfigZoom, G_NORMAL_MAP);
	map.addControl(new GLargeMapControl());
	map.addControl(new GScaleControl());
	//map.addControl(new GHierarchicalMapTypeControl());
	map.addControl(new GMapTypeControl(true));
	//map.enableScrollWheelZoom();

	setupEnviroment(false);

	GEvent.addListener(map, 'zoomend', function(oldZoomLevel, newZoomLevel) {
		setupEnviroment(newZoomLevel);
		callGenerateKml(false);
	});

	GEvent.addListener(map, 'dragend', function() {
		setupEnviroment(false);
		callGenerateKml(true);
	});

	// hack to open kml description links in the current window ("a" target substitution)
	GEvent.addListener(map,"infowindowopen",function() {
		var info_window=map.getInfoWindow();
		var nodes=info_window.getContentContainers();
		for (var node in nodes) {
			var anchors=nodes[node].getElementsByTagName('a');
			for (var a in anchors) {
				if (anchors[a].tagName) anchors[a].setAttribute("target","_top");
			}
		}
	});
}

function callGenerateKml(drag) {
	var doCall = true;

	var centerXDiff = Math.abs(pastCenterX-centerX);
	var centerYDiff = Math.abs(pastCenterY-centerY);

	$('#gdebug').append('<p>centerXDiff: '+centerXDiff+'<br />centerYDiff: '+centerYDiff+'</p>');

	if (drag && centerXDiff<paddingX && centerYDiff<paddingY) doCall = false;

	var imploded_checked_geotypes = getImplodedCheckedGeotypes();
	if (legendDivExists() && allUnchecked()) doCall = false;

	if (doCall) {

		map.clearOverlays();

		$('#gmap').block({ message: '<img src="http://localhost/googlemap/loading.gif" />' });
		$(legendDiv).find('input:checkbox').each(function(){
			$(this).attr('disabled',true);
		});

		var ggeoxml_url = ggeoxml_path+'&minX='+paddedMinX+'&maxX='+paddedMaxX+'&minY='+paddedMinY+'&maxY='+paddedMaxY+'&scaledZoom='+scaledZoom;
		if (imploded_checked_geotypes) ggeoxml_url += '&imploded_checked_geotypes='+imploded_checked_geotypes;
		//ggeoxml_url += '&lang='+currentLang;

		var ggeoxml_url_debug = ggeoxml_url + '&google_debug=1';

		$('#gdebug').append('<p>'+ggeoxml_url+'<br />'+ggeoxml_url_debug+'</p>');
		$('#gdebug').append('<p id="gdebug_load"><span style="color:#ff9900">loading...</span></p>');

		gOverlay = new GGeoXml(ggeoxml_url,ggeoxml_callback);
		map.addOverlay(gOverlay);

		timer = setTimeout('halt_callback()', 10000);
	}
}

function ggeoxml_callback() {
	clearTimeout(timer);
	$('#gdebug_load').html('<span style="color:#66cc00">loaded!</span>');
	$('#gmap').unblock();
	$(legendDiv).find('input:checkbox').each(function(){
		$(this).attr('disabled',false);
	});
}

function halt_callback() {
	$('#gdebug_load').html('<span style="color:#cc0000">error: timer has expired</span>');
	$('#gmap').unblock();
	$(legendDiv).find('input:checkbox').each(function(){
		$(this).attr('disabled',false);
	});
}

function legendDivExists() {
	if (legendDiv) return true;
	return false;
}

function allUnchecked() {
	if ($(legendDiv).find('input:checkbox:checked').length == 0) {
		map.clearOverlays();
		return true;
	}
	return false;
}

function getImplodedCheckedGeotypes() {
	if (legendDivExists()) {
		var geosubtypeArray = new Array();
		var i = 0;
		$(legendDiv).find('input:checkbox').each(function(){
			if ($(this).is(':checked')) {
				geosubtypeArray[i]=$(this).attr('id');
				i++;
			}
		});
		if (i > 0) return geosubtypeArray.join('|');
	}
	return false;
}

function toggleOverlays() {
	setupEnviroment(false);
	callGenerateKml(false);
}










////////////////////////////////////////////////////////////////////////////
// geocoder
////////////////////////////////////////////////////////////////////////////

var gdir;

function showAddress(address) {

	if (address!='') {

		var geocoder=new GClientGeocoder();

		address+=address_suffix;
		geocoder.getLatLng(address,function(point) {
			if (!point) {
				alert(address+" not found");
			} else {
				map.setCenter(point, 13);
				var marker=new GMarker(point);
				map.addOverlay(marker);
				marker.openInfoWindowHtml(address);
			}
		});
	}
}


function setDirections(fromAddress,toAddress,locale) {

	if (fromAddress!='' && toAddress!='') {

		var pathDiv = $('#gpath').get(0);
		$(pathDiv).show();

		gdir = new GDirections(map,pathDiv);
		GEvent.addListener(gdir,'error',handleErrors);

		fromAddress+=address_suffix;
		toAddress+=address_suffix;

		gdir.load("from: "+fromAddress+" to: "+toAddress,{"locale": locale});
	}
}


function handleErrors() {
	if (gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
		alert("No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect.\nError code: " + gdir.getStatus().code);
	else if (gdir.getStatus().code == G_GEO_SERVER_ERROR)
		alert("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + gdir.getStatus().code);
	else if (gdir.getStatus().code == G_GEO_MISSING_QUERY)
		alert("The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + gdir.getStatus().code);
	//else if (gdir.getStatus().code == G_UNAVAILABLE_ADDRESS)  <--- Doc bug... this is either not defined, or Doc is wrong
		//alert("The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons.\n Error code: " + gdir.getStatus().code);
	else if (gdir.getStatus().code == G_GEO_BAD_KEY)
		alert("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + gdir.getStatus().code);
	else if (gdir.getStatus().code == G_GEO_BAD_REQUEST)
		alert("A directions request could not be successfully parsed.\n Error code: " + gdir.getStatus().code);
	else
		alert("An unknown error occurred.");
}
