/**
* Map
*/
function Map( gmap, canvas ) {
	/**
	* @private
	* Referenz des aktuellen Objektes
	*/
	var self = this;
		
	/**
	* @public
	* ID des Elements das die Karte aufnimmt
	*/
	this.canvasId = canvas;
	
	/**
	* @public
	* GoogleMaps Objekt
	*/
	this.gmap = gmap;
	
	/**
	* @public
	* Kartenzentrum
	*/
 	this.mapCenter = null;
	
	/**
	* @public
	*/
	this.mapIsCentered = false;
	
	/**
	* @public
	* Geocoder-Callbacks
	*/
	this.setLocationsGeoencoderCallbacks = new Array();
	
	/**
	* @public
	* setLocationCallbacks
	*/
	this.setLocationCallbacks = new Array();
		
	/**
	* @private
	* Auf der Karte registrierte Orte
	*/
	var locations = new Array();
	
	/**
	* @public
	* Location für die Karte registrieren
	*/
	this.registerLocation = function( location, isCenter ){
		if( isCenter ) {
			if( location.lat && location.lng ) {
				this.mapCenter = new google.maps.LatLng( location.lat, location.lng);
			} else {
				this.registersetLocationsGeoencoderCallback( function( options ) {
					if( !self.mapIsCentered ) {
						self.mapCenter = new google.maps.LatLng( options.lat, options.lng );
						self.mapIsCentered = true;
						self.gmap.setCenter( self.mapCenter );
					}
				});
			}
		}
		locations.push( location );
	}
	
	/**
	* @public
	* Register GeoencoderCallbacks für setLocations
	*/
	this.registersetLocationsGeoencoderCallback = function( callback ) {
		this.setLocationsGeoencoderCallbacks.push( callback );
	}
	
	/**
	* @public
	* Die der Karte zugeordnet Plätze setzen und Karte zentrieren
	* Wenn keine Location bewusst auf der Karte zentriert werden soll wird die erste Location zentriert
	*/
	this.setLocations = function() {
		var geocoder = new google.maps.Geocoder();
		var marker = new Array(locations.length);

		$.each( locations, function( i, location ) {
			if( location.lat == null || location.lng == null ) {
				var address = "";
				
				switch( location.address ) {
					case "Cape Point":
						address = "Cape Point Cape Town";
						break;

					case "Cape Town International Airport":
						address = "Cape Town";
						break;

					default:
						address = location.address + " South Africa";
				}
								
				geocoder.geocode( { "address": address }, function( results, status ) {
					if( status == google.maps.GeocoderStatus.OK) {
						location.lat = results[0].geometry.location.Tf;
						location.lng = results[0].geometry.location.Wf;
						
						if( self.setLocationsGeoencoderCallbacks.length > 0 ) {
							var callbackOptions = {
								lat : location.lat, 
								lng : location.lng
							}
							$.each( self.setLocationsGeoencoderCallbacks, function( j, callback ) {
								callback( callbackOptions );

								if( ( j + 1 ) == self.setLocationsGeoencoderCallbacks.length ) {
									self.setLocation( location, i );
								}
							});	
						} else {
							self.setLocation( location, i );
						}
					}else{
					}
				});
			}
			else {
				if( !this.mapIsCentered ) {
					if( self.mapCenter )
					{
						self.mapIsCentered = true;
						self.gmap.setCenter( self.mapCenter );
					}
				}
				self.setLocation( location, i );	
			}
		});		
	}
	
	/**
	* @public
	* Einen Platz setzen
	*/
	this.setLocation = function( location, i ) {
	//	var image = new google.maps.MarkerImage( location.condition.icon, new google.maps.Size(20, 20), new google.maps.Point(0,0), new google.maps.Point(0, 20) );
		
		if( location.showMarker ) {
		
			if( location.iconMarker ) {
				var imageIcon = new google.maps.MarkerImage(
					location.condition.icon,
					new google.maps.Size(75, 75),
					new google.maps.Point(0,0),
					new google.maps.Point(0, 0)
				);
		
				var city = new google.maps.Marker( {
					map: self.gmap, 
					position: new google.maps.LatLng( location.lat, location.lng ),
					title: location.address,
					icon: imageIcon
				});
			} else {
				city = new google.maps.Marker( {
					map: self.gmap, 
					position: new google.maps.LatLng( location.lat, location.lng ),
					title: location.address
				});
			}
		
			if( this.showInfoBox ) {
				var link = "";
				
				if( location.targetLink ) {
					link = '<a href="' + location.targetLink + '">Komplette Vorhersage</a>';
				}
				
				var info = new google.maps.InfoWindow( {
					content: '<div><img src="' + location.condition.icon + '" style="float: left; margin: 4px;" /> <strong>' + location.address + '</strong><br />' + location.condition.name + '<br />' + location.condition.tempVal + ' °C<br />' + link + '</div>'
				});
				if( location.infoWinAutoOpen ) {
					info.open( self.gmap, city );
				}
				
				google.maps.event.addListener( city, "click", function() {
					info.open( self.gmap, city );
				});
			}		
		}
		if( self.setLocationCallbacks.length > 0 ) {
			var callbackOptions = {
				"location": location,
				"map" : self 
			}
			$.each( self.setLocationCallbacks, function( j, callback ) {
				callback( callbackOptions );
			});	
		}
	}
	
	/**
	* @public
	* Register setLocationCallbacks für setLocation
	*/
	this.registerSetLocationCallbacks = function( callback ) {
		this.setLocationCallbacks.push( callback );
	}
	
	/**
	* @public
	* Register Map click
	*/
	this.registerMapClick = function( mapClick ) {
		google.maps.event.addListener( self.gmap, "click", function() {
			mapClick();
		});
	}
	
	/**
	* @public
	* Lädt KML und übergibt die Daten an Callback
	*/
	this.loadKML = function( kml, callback ) {		
		var geoXml = new geoXML3.parser({
			map: this.gmap,
			singleInfoWindow: true,
			afterParse: function( doc ) {
				if( callback ) {
					callback( doc );
				}
			}
		});
		geoXml.parse( kml );
	}
}

/**
* SmallMap
*/
function SmallMap( canvas, zoom ) {
	/**
	* @private
	* Referenz des aktuellen Objektes
	*/
	var self = this;
	
	/**
	* @public
	* show weather Icons
	*/
	this.showInfoBox = false;
	
	/**
	* @private
	* GoogleMaps Ausgangseinstellungen
	*/
	var options = {
		gmap : {
			zoom: zoom,
			center: new google.maps.LatLng( 0, 0),
			mapTypeId: google.maps.MapTypeId.ROADMAP,
			disableDefaultUI: true
	   }
	}
		
	// Konstrukt
	this.constructor( new google.maps.Map( document.getElementById( canvas ), options.gmap ), canvas );
	
	/**
	* @public
	* Location für die Karte registrieren
	*/
	this.init = function( infoBox ) {
		this.showInfoBox = infoBox;
		self.setLocations();
	}
}
SmallMap.prototype = new Map();

/**
* BigMap
*/
function BigMap( canvas, zoom ) {
	/**
	* @private
	* Referenz des aktuellen Objektes
	*/
	var self = this;
	
	/**
	* @public
	* show weather Icons
	*/
	this.showInfoBox = false;
	
	/**
	* @private
	* GoogleMaps Ausgangseinstellungen
	*/
	var options = {
		gmap : {
			zoom: zoom,
			center: new google.maps.LatLng( 0, 0),
			mapTypeId: google.maps.MapTypeId.SATELLITE,
			disableDefaultUI: false
	   }
	}
	
	/**
	* @private
	* Markup für die große Karte erzeugen
	*/
	var createMarkup = function() {
		$( "body" ).append( "<div id=\"" + canvas + "\"></div>" );
		if( document.body.scrollHeight ) {
			height = document.body.scrollHeight;
		} else {
			height = "100%";
		}
		$( "#" + canvas ).css( "height", height ).css( "left", "-10000px" );
	}
	
	// Konstrukt
	createMarkup();
	this.constructor( new google.maps.Map( document.getElementById( canvas ), options.gmap ), canvas );
	
	/**
	* @public
	* Location für die Karte registrieren
	*/
	this.init = function( infoBox ) {
		this.showInfoBox = infoBox;
		
		self.registerSetLocationCallbacks( function( options ) {
			var wikipedia = new WikipediaMarkers( options.map , options.location );
			wikipedia.getData();
		});
		
		self.setLocations();
		
		$( window ).keydown( function(e) {
			if( e.which == 27 ) {
				if( $( "#" + self.canvasId ).css( "display" ) == "block" )
				{
					self.hide();
				}
			} 
	    });	
	
	//	this.loadKML( "http://dev2.weather.co.za/js/data.php?service=sat" );
	}
	
	/**
	* @public
	* Zeigt die Karte an
	*/
	this.show = function() {
		var canvas = $( "#" + self.canvasId );
		if( canvas.css( "left" ) == "-10000px" ) {
			canvas.css( "left", "0" ).hide();
		}
		canvas.show( "slow" );
	}
	
	/**
	* @public
	* Versteckt die Karte an
	*/
	this.hide = function() {
		$( "#" + self.canvasId ).hide( "slow" );
	}
}
BigMap.prototype = new Map();

/**
* WikipediaMarkers
*/
function WikipediaMarkers( map, location ) {
	/**
	* @private
	* Referenz des aktuellen Objektes
	*/
	var self = this;
	
	/**
	* @public
	* Karte auf der die Marker gezeigt werden sollen
	*/
	this.map = map;
	
	/**
	* @public
	* Ajax JSON Dataprovicer
	*/
	this.dataProvider = "http://dev2.weather.co.za/js/data.php?service=wiki";
	
	/**
	* @public
	* Wikipedia Marker
	*/
	this.markers = null;
	
	/**
	* @public
	* Infowindows
	*/
	this.infosWindows = null;
	
	/**
	* @public
	* Wikipedia Icon
	*/
	this.markerImage = "http://dev2.weather.co.za/img/wikipedia-marker.png";
	
	/**
	* @public
	* Location
	*/
	this.location = location;
	
	/**
	* @public
	* JSON->Array
	*/
	this.data = null;
	
	/**
	* @public
	* Radius
	*/
	this.radius = 45;
		
	/**
	* @public
	* Laods Wikipedia JSON
	*/
	this.getData  = function() {
		$.getJSON( this.dataProvider + "&lat=" + this.location.lat + "&lng=" + this.location.lng + "&radius=" + this.radius, function( data ) {
			self.data = data;
			self.setMarkers();
		});
	};
	
	/**
	* @public
	* SetMarker
	*/
	this.setMarkers = function() {	
		self.markers = new Array( self.data.geonames.length );
		self.infoWindows = new Array( self.data.geonames.length );
		
		$.each( self.data.geonames, function(i, item) {
			self.markers[i] = new google.maps.Marker( {
				map: self.map.gmap, 
				position: new google.maps.LatLng( item.lat, item.lng ),
				title: item.title,
				icon: self.markerImage
			});

			self.infoWindows[i] = new google.maps.InfoWindow( {
				content: "<div class=\"info_window\"><h1>" + item.title + "</h1><img class=\"info_img\" src=\"" + item.thumbnailImg + "\"/><p>" + item.summary + " <a target=\"_blank\" href=\"http://" + item.wikipediaUrl	 + "\"><img src=\""+ self.markerImage +"\"/>" + item.title + "@ Wikipedia</a></p><br class=\"clf\"/>"
			});
			
			google.maps.event.addListener( self.markers[i], "click", function() {
				$.each( self.infoWindows, function( j, infoWindow ) {
					infoWindow.close();
				});
				self.infoWindows[i].open( self.map.gmap, self.markers[i] );
			});
		});
	}
}