var GMApp = Class.create({
	
	initialize: function( div, url ){
		
		if( !GBrowserIsCompatible() ) return; // fail silently
		
		this.canvas 	= $(div);
		this.maxZoom	= 16; // max available from google is 19
		this.map		= new GMap2( this.canvas );
		this.dataUrl	= url;
		this.bounds 	= new GLatLngBounds();
		this.locations	= [];
		this.singleMode = false;

		// configure the map display
		this.map.enableContinuousZoom();
		this.map.enableScrollWheelZoom();
		this.map.addMapType( G_PHYSICAL_MAP );
		this.map.setMapType( G_NORMAL_MAP );
		this.map.addControl( new GMapTypeControl());
		this.map.addControl( new GLargeMapControl3D() );
		
		// init other objects
		this.iconBaumaterial = this.getIcon( "IconBaumaterial" );
		this.iconWandBoden = this.getIcon( "IconWandBoden" );
		
		this.filterBM = $("Baumaterial");
		this.filterWB = $("WandBoden");
		
		paramSelektion = this.getUrlParam(new Array('Selektion'));
		
		if( this.filterBM  ){
			if(paramSelektion.Selektion == 'Baumaterial' || !paramSelektion.Selektion) this.filterBM.checked = true; 
			this.filterBM.observe( "click", this.initMapWithData.bind(this) );
		}	
		if( this.filterWB ){
			if(paramSelektion.Selektion == 'WandBodenbelaege' || !paramSelektion.Selektion) this.filterWB.checked = true;
			this.filterWB.observe( "click", this.initMapWithData.bind(this) );
		}
	},
	
	getUrlParam: function ( paramName ) {
		var params = document.location.search.substr(1, document.location.search.length);
		if (params == '') return new Object;

		var urlParams = new Object;
		var uPs = new Object;

		//-- get all url params (for internal use)
		gets = params.split('&'); // array with 'key=value'
		for (var i = 0; i < gets.length; ++i) {
			var keyAndValue = gets[i];
			keyAndValue = keyAndValue.split('='); // array with 0 = 'key' and 1 = 'value'

			var key = null;
			var value = null;

			key = keyAndValue[0];
	 		if (keyAndValue[1]) value = keyAndValue[1];

			uPs[key] = value;
		}
		//--

		//-- filter params when wanted
		var behaviour = arguments.length; // 0 : no filter; all url params asked, 1 : filter; array with asked param names
		switch (behaviour) {
			case 1 : // array given, loop over all and collect only wanted for return
				for (var idx in paramName) {
					key = paramName[idx];
					if (uPs[key]) urlParams[key] = uPs[key];
				}
				break;

			case 0 :
			default:
				urlParams = uPs;
		}
		//--

		return urlParams;
	},	
	
	loadAddressData: function( callback, id ){
		
		var params = {
			Id: id ? id : ""
		};
		
		// if we have an Id, we'll display the detail view
		this.singleMode = parseInt( id ) != 0;

		var req = new Ajax.Request( this.dataUrl + ( this.dataUrl.indexOf('?') == -1 ? "?" : "" )+ Object.toQueryString( params ), {
			onSuccess: function( transport ){
				var content = transport.responseText.evalScripts();
				callback( null, content[0] ).bind(this);
			}.bind(this)
		});
	},
	
	initMapWithData: function( event, jsonData ){
		
		if( jsonData != null ) this.locations = jsonData;
		
		var addedAny = false;
		this.map.clearOverlays();

		for( var i = 0; i < this.locations.length; i++ ){
		
			var location = this.locations[i];
			var valid = false;
			
			if( !location.geokoordinaten ) continue;
				
			if( !location.marker ){
					
				var coords = GLatLng.fromUrlValue( this.extractInvertedLatLng( location.geokoordinaten ) );
				var icon = new GIcon( location.bereich == "Baumaterial" ? this.iconBaumaterial : this.iconWandBoden );
				var marker = new GMarker( coords, {icon: icon} );

				GEvent.addListener( marker, "click", this.markerAction.bind( location ) );
				location.marker = marker;
				location.app = this;
			}
			
			if( !this.singleMode ){
				var validBM = Boolean(this.filterBM.checked) && this.filterBM.value == location.bereich;
				var validWB = Boolean(this.filterWB.checked) && this.filterWB.value == location.bereich;
				valid = validBM || validWB;
			}
				
			if( this.singleMode || valid ){
				this.map.addOverlay( location.marker );
				this.bounds.extend( location.marker.getLatLng() );
				addedAny = true;
			}
		}

		if( addedAny )
			this.map.setCenter( this.bounds.getCenter(), Math.min( this.map.getBoundsZoomLevel( this.bounds ), this.maxZoom ) );
		else
			this.map.setCenter( new GLatLng( 46.818188, 8.227512 ), 7 ); // fallback to switzerland if no markers
	},
	
	extractInvertedLatLng: function( lngLatString ){
		var split = lngLatString.split(',');
		return split[1] + ',' + split[0];
	},
	
	getIcon: function( imageId ){
		
		var imageURL = $( imageId ).readAttribute("src");
		
		if( imageURL.indexOf("http://") == -1 ){
			var basePath = $$("base")[0].readAttribute("href");
			imageURL = basePath + imageURL;
		}
		
		var icon = new GIcon(G_DEFAULT_ICON);
		icon.image = imageURL;
		icon.transparent = icon.image;
		icon.iconSize = new GSize(20, 34);
		icon.iconAnchor = new GPoint(5, 34);
		return icon;
	},
	
	markerAction: function( e ){
		// is bound to the location data, this = location
		if( !this.app.singleMode ){
			window.location.href = this.detailURL;
		}
		else{
			if( !this.bubbleContent ){
				this.bubbleContent = $(this.nodeId);
				this.bubbleContent.select('a')[0].writeAttribute('href', this.app.getGoogleMapsURL( this ));
			}
			this.marker.openInfoWindow( this.bubbleContent );
		}
	},
	
	getGoogleMapsURL: function( data ){

		var urlParams = {
			sll: this.map.getBounds().getSouthWest().toUrlValue(),
			ll: data.marker.getLatLng().toUrlValue(),
			t: this.map.getCurrentMapType().getUrlArg(),
			q: data.name + " " + data.adresse,
			iwloc: "A" //takes A (the first) result from the search and displays it in the popup
		}

		return "http://maps.google.com/maps?" + Object.toQueryString( urlParams );
	}	
});