// JavaScript Document google map function

var ka_GoogleMap = new Class({

	Implements: [Chain, Options],

	options: {
		map_type: 'G_NORMAL_MAP',		//type of the map
		map_lat: -32.69486597787506,						// standard center lat
		map_long: -65.390625,					// standard center long
		map_zoom: 4						// standard zoom
	},

	initialize: function(el,options){
		this.setOptions(options);  

		if(!GBrowserIsCompatible()){
			window.alert('browser not GoogleMap compatible');
			return false;
		}
		
		if(!$(el)) {
			window.alert('GoogleMap Container not found');
			return false;
		}
		this.map = false;
		this.finder = false;
		this.mapContainer = $(el);
		this.mapType();
		this.loadMap();
		this.marker = new Array();
	},

	mapType: function(){
		switch(this.options.map_type){
			case 'G_NORMAL_MAP':
				this.maptype = G_NORMAL_MAP;
			break

			case 'G_SATELLITE_MAP':
				this.maptype = G_SATELLITE_MAP;
			break

			case 'G_HYBRID_MAP':
				this.maptype = G_HYBRID_MAP;
			break

			case 'G_PHYSICAL_MAP':
				this.maptype = G_PHYSICAL_MAP;
			break

			default:
				window.alert('Sorry, unknown map type');
			break
		}
	},

	loadMap: function(){
		this.mapContainer.setStyle('background','none');
		this.map = new GMap2(this.mapContainer);
		this.map.setMapType(this.maptype);
		this.map.addControl(new GMapTypeControl());
		this.map.addControl(new GLargeMapControl());
		//this.map.addControl(new biggerMapControl());
		if(this.options.map_lat !== false && this.options.map_long !== false) {
			this.map.setCenter(new GLatLng( parseFloat(this.options.map_lat), parseFloat(this.options.map_long) ), parseInt(this.options.map_zoom));
		}
	},
	
	latLongFinder: function(lat,long) {
		if(this.finder)
			this.map.removeOverlay(this.finder);
		if(!this.validLatLong(lat,long)) {
			lat = 47.518600;
			long = 12.550005;
		}
		this.finder = new GMarker(new GLatLng(lat, long),{draggable: true});
		this.map.setCenter(this.finder.getLatLng(), this.options.map_zoom);
		this.map.addOverlay(this.finder);
	},
	
	latLongFinder_coords: function() {
		if(!this.finder)
			return false;
		else {
			newpoint = this.finder.getLatLng();	
			return {lat: newpoint.lat(), long: newpoint.lng()}
		}
	},
	
	validLatLong: function(lat,long) {
		if(!lat || !long)
			return false;
		lat = lat.toFloat();
		long = long.toFloat();
		if(isNaN(lat) || isNaN(long))
			return false;
		else
			return true;
	},
	
	showPoints: function(data) {  // obj of index lat,long,title,text
		bounds = new GLatLngBounds(); // new instance for centering
		boundcount = 0;
		points = [];
		data.each(function(obj,index) {
			//thepoint = new GLatLng(parseFloat(lat),parseFloat(long));
			//themarker = new GMarker(thepoint);
			themarker = new HaltenMarker(obj);
			points.push(new GLatLng(parseFloat(obj.lat),parseFloat(obj.long)));
			this.marker[index] = themarker;
			bounds.extend(themarker.getPoint());
			this.map.addOverlay(themarker);
			boundcount++;
		},this);
		this.map.addOverlay(new GPolyline(points, "#F7EE53", 1, 0.8));
		// when bounds are not empty do the new centering
		if(!bounds.isEmpty()) {
			//this.map.setZoom(this.map.getBoundsZoomLevel(bounds)-1);
			this.map.panTo(bounds.getCenter());
			if(boundcount < 2) {
				setMaxZoomCenter(this.map,bounds.getSouthWest());
			}
		}
		else
			window.alert("keine bounds");
		
	},
	
	zoomToPoint: function(m) {
		window.alert(m);
		return;
		bounds = new GLatLngBounds();
		bounds.extend(m.getPoint());
		this.map.setZoom(this.map.getBoundsZoomLevel(bounds)-1);
		this.map.panTo(bounds.getCenter());
	}

});


//********************** MyMarker class ******************

var HaltenMarker = new Class({
    initialize: function(obj){
		// icon
		this.icon = new GIcon(G_DEFAULT_ICON, "placemark/yellow_mark.png");
		this.icon.iconSize = new GSize(32,32);
		// coords
		this.point = new GLatLng(parseFloat(obj.lat),parseFloat(obj.long));
		this.marker = new GMarker(this.point, { icon: this.icon, title:obj.title});
		this.html = '<div class="logbook_pouptext">'+obj.text+'</div>';
		this.html += '<ul>';
		if(obj.link_href)
			this.html += '<li><a href="'+obj.link_href+'">hier gehts zum Bericht</a></li>';
		this.html += '</ul>';
		GEvent.bind(this.marker, "click", this, this.onMarkerClick);
		return this.marker;
    },
	onMarkerClick: function() {
		this.marker.openInfoWindowHtml(this.html);
	}
});


//******************** END MyMarker Class ******************


/** ADDITIONAL FUNCTIONS **/

function geocodeAddress(searchstr,latfield,longfield) {
	geocoder = new GClientGeocoder();
	geocoder.getLatLng(searchstr, function(point) {
		if(!point) {
 			latfield.highlight('#990000');
			longfield.highlight('#990000');
		}
		else {
			latfield.set('value',point.lat());
			longfield.set('value',point.lng());
			latfield.highlight('#009900');
			longfield.highlight('#009900');
		}
	});
}

function geocodeLatLng(lat,lng,textfield) {
	latlng = new GLatLng(lat,lng);
	geocoder = new GClientGeocoder();
	geocoder.getLocations(latlng, function(addresses) {
		if(addresses.Status.code != 200) {
			textfield.highlight('#990000');
		}
		else {
			if(addresses.Placemark[0].address) {
				textfield.set('value',addresses.Placemark[0].address);
				textfield.highlight('#009900');
			}
			else
				textfield.highlight('#990000');
		}
	});	
}

function setMaxZoomCenter(map, latlng) {
  map.getCurrentMapType().getMaxZoomAtLatLng(latlng, function(response) {
    if (response && response['status'] == G_GEO_SUCCESS) {
      map.setCenter(latlng, response['zoom']);
    }
  });
}


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/*  Latitude/longitude spherical geodesy formulae & scripts (c) Chris Veness 2002-2009            */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */

/*
 * Use Haversine formula to Calculate distance (in km) between two points specified by 
 * latitude/longitude (in numeric degrees)
 *
 * from: Haversine formula - R. W. Sinnott, "Virtues of the Haversine",
 *       Sky and Telescope, vol 68, no 2, 1984
 *       http://www.census.gov/cgi-bin/geo/gisfaq?Q5.1
 *
 * example usage from form:
 *   result.value = LatLon.distHaversine(lat1.value.parseDeg(), long1.value.parseDeg(), 
 *                                       lat2.value.parseDeg(), long2.value.parseDeg());
 * where lat1, long1, lat2, long2, and result are form fields
 */
function calculateDistance(lat1, lon1, lat2, lon2) {
  var R = 6371; // earth's mean radius in km
  var dLat = (lat2-lat1).toRad();
  var dLon = (lon2-lon1).toRad();
  lat1 = lat1.toRad(), lat2 = lat2.toRad();

  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(lat1) * Math.cos(lat2) * 
          Math.sin(dLon/2) * Math.sin(dLon/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;
  return d;
}

// extend Number object with methods for converting degrees/radians

Number.prototype.toRad = function() {  // convert degrees to radians
  return this * Math.PI / 180;
}

Number.prototype.toDeg = function() {  // convert radians to degrees (signed)
  return this * 180 / Math.PI;
}

Number.prototype.toBrng = function() {  // convert radians to degrees (as bearing: 0...360)
  return (this.toDeg()+360) % 360;
}


// extend String object with method for parsing degrees or lat/long values to numeric degrees
//
// this is very flexible on formats, allowing signed decimal degrees, or deg-min-sec suffixed by 
// compass direction (NSEW). A variety of separators are accepted (eg 3 37' 09"W) or fixed-width 
// format without separators (eg 0033709W). Seconds and minutes may be omitted. (Minimal validation 
// is done).

String.prototype.parseDeg = function() {
  if (!isNaN(this)) return Number(this);                 // signed decimal degrees without NSEW
  
  var degLL = this.replace(/^-/,'').replace(/[NSEW]/i,'');  // strip off any sign or compass dir'n
  var dms = degLL.split(/[^0-9.,]+/);                     // split out separate d/m/s
  for (var i in dms) if (dms[i]=='') dms.splice(i,1);    // remove empty elements (see note below)
  switch (dms.length) {                                  // convert to decimal degrees...
    case 3:                                              // interpret 3-part result as d/m/s
      var deg = dms[0]/1 + dms[1]/60 + dms[2]/3600; break;
    case 2:                                              // interpret 2-part result as d/m
      var deg = dms[0]/1 + dms[1]/60; break;
    case 1:                                              // decimal or non-separated dddmmss
      if (/[NS]/i.test(this)) degLL = '0' + degLL;       // - normalise N/S to 3-digit degrees
      var deg = dms[0].slice(0,3)/1 + dms[0].slice(3,5)/60 + dms[0].slice(5)/3600; break;
    default: return NaN;
  }
  if (/^-/.test(this) || /[WS]/i.test(this)) deg = -deg; // take '-', west and south as -ve
  return deg;
}
// note: whitespace at start/end will split() into empty elements (except in IE)


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */




/************* NEW GMAP CONTROL ***************/


function biggerMapControl() {
}

biggerMapControl.prototype = new GControl();

biggerMapControl.prototype.initialize = function(map) {
  var container = document.createElement("div");
  var zoomInDiv = document.createElement("div");
  this.setButtonStyle_(zoomInDiv);
  container.appendChild(zoomInDiv);
  zoomInDiv.appendChild(document.createTextNode("Map-Groesse"));
  GEvent.addDomListener(zoomInDiv, "click", function() {
	toggleMapView()
  });

  map.getContainer().appendChild(container);
  return container;
}

biggerMapControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(100, 7));
}

// Sets the proper CSS for the given button element.
biggerMapControl.prototype.setButtonStyle_ = function(button) {
  button.style.textDecoration = "none";
  button.style.color = "#000000";
  button.style.backgroundColor = "white";
  button.style.font = "small Arial";
  button.style.border = "1px solid black";
  button.style.padding = "2px";
  button.style.marginBottom = "3px";
  button.style.textAlign = "center";
  button.style.width = "6em";
  button.style.cursor = "pointer";
}
