/**
 * geo-viz.js
 * 
 * In order to work properly, this script needs jQuery
 */

/**
 * configuration parameters for the dialog
 */

var geo_viz_dialog_options = {
	
	dialogClass: 'geo_viz_dialog',
	autoOpen: false, //do not change this property!!
	width: 800,
	modal: false,
	padding: 0,	
	show: null,
	hide: null,
	resizable: false,
	draggable: true,
	position: ['center', 75],
	title: ''
	
};


var geo_viz_tooltip_options = {
	
	dialogClass: 'geo_viz_tooltip',
	height: 50,
	modal: false,
	padding: 0,	
	show: null,
	hide: null,
	resizable: false,
	draggable: false,
	title: ''
	
};


var num_markers = 0;


//global variables
//@TODO: load map preferences from a config file
var MARKER_URL = 'http://' + document.domain + '/wp-content/plugins/geo-viz/markers';



/**
 * Class GeoViz holds the representation of the map and provides all needed functionality
 * for adding shapes.
 * @param {String} host_element defines the id of an html host element, hosting the map
 */

function GeoViz(host_element, lang){
	

		
	if (!GBrowserIsCompatible()) {
		
		
		return null;	
	}
	
	if(lang)
		this.lang = lang;
	
	else
		this.lang = 'de';
	
	this.currently_visible_path = null;
	
	
	this.host_element = host_element;
	this.layers = [];	//contains a number of layers
	this.layer_names = new Object(); //contains layer names
	this.shapes = []; //holds the map's shapes -- NOTE that also a layer knows about the shapes it contains
		
	this.xml_overlays = []; //contains xml_overlay objects
	
	this.icon_tips = {}; //holds a number of jQuery div objects representing additional information
						//for added markers
	
	this.map = new GMap2(document.getElementById(host_element));
	//this.map.enableGoogleBar();
	
	this.show_marker_tips = false;
	
	this.custom_icon_folder = 'region';
	this.icon = null;
	this.side_map = false;
	this.zoom = 10; // is changed in the initialization
	this.center = null; // is assigned a GLatLng in the initialization
	this.side_map_zoom = 13;
	this.show_shapes = true;
	
	this.tooltip = document.createElement('div');
	this.tooltip.className = 'tooltip';
	
	
			
	
	
	this.region_marker_clusterer = new ClusterMarker(this.map, {
		intersectPadding: 10
	}
	);
		
	this.region_marker_clusterer.clusterMarkerTitle = '%count Regionen';
	
	this.events_marker_clusterer = new ClusterMarker(this.map,
		{
		
			intersectPadding: 15
		}
	
	
	);
	
	
		
	this.events_marker_clusterer.clusterMarkerTitle = '%count Veranst.';
	
	this.bestof_marker_clusterer = new ClusterMarker(this.map);
	this.bestof_marker_clusterer.clusterMarkerTitle = '%count Angebote';
	
	this.businesses_marker_clusterer = new ClusterMarker(this.map, 
	
	{
		intersectPadding: 15
	
		
	}
	
	);
	this.businesses_marker_clusterer.clusterMarkerTitle = '%count Betriebe';
	
	
	 
	this.tours_marker_clusterer =  new ClusterMarker(this.map );
	this.tours_marker_clusterer.clusterMarkerTitle = '%count Wege';
	
	
	this.data_url;	
	
	//defining some standard_layers for the map;
	
	this.regions_layer = null;
	this.events_layer = null;
	this.bestof_layer = null;
	this.businesses_layer = null;
	this.tours_layer = null;
	
	this.max_cluster_level = null;
	
	
	
	this.last_displayed_layer = "";
	
	this.layer_data_buffer = null;		  
	
	
		//register functions for the class
	if (typeof(this.GeoViz_prototype_called) == 'undefined') {
		
			
		GeoViz.prototype.initializeMap = initializeMap;
		GeoViz.prototype.addLayer = addLayer;
		GeoViz.prototype.addShape = addShape;
		GeoViz.prototype.getLayers = getLayers;
		GeoViz.prototype.hideLayer = hideLayer;
		GeoViz.prototype.showLayer = showLayer;
		GeoViz.prototype.getLayerByName = getLayerByName;
		GeoViz.prototype.getShapeById = getShapeById;
		GeoViz.prototype.createMarker = createMarker;
		GeoViz.prototype.createPolyline = createPolyline;
		GeoViz.prototype.createPolygon = createPolygon;
		GeoViz.prototype.setIcon = setIcon;
		GeoViz.prototype.importXMLOverlay = importXMLOverlay;
		GeoViz.prototype.addXMLOverlay  = addXMLOverlay; 
		GeoViz.prototype.addRegions = addRegions;
		GeoViz.prototype.addEvents = addEvents;
		GeoViz.prototype.addBusinesses  = addBusinesses;
		GeoViz.prototype.addLocation = addLocation;
		GeoViz.prototype.addTours = addTours;
		GeoViz.prototype.addBestOf = addBestOf;
		GeoViz.prototype.displayDescription = displayDescription;
		GeoViz.prototype.displaySingleTour = displaySingleTour;
		GeoViz.prototype.ClusterIcon = ClusterIcon;
		GeoViz.prototype.bindClustererToMaxZoom = bindClustererToMaxZoom;
		GeoViz.prototype.hideAllRegions = hideAllRegions;
		GeoViz.prototype.showRegions = showRegions;
		GeoViz.prototype.addMarkerTip = addMarkerTip;
		GeoViz.prototype.showMarkerTips = showMarkerTips;
		GeoViz.prototype.hideMarkerTips = hideMarkerTips;
		
		
		GeoViz.prototype.GeoViz_prototype_called = true;
		

		//when the page is unloaded, all google maps data shall be deleted
		//to save memory
		jQuery(window).unload(function(){
			
			GUnload();
			
		});
	}
	
	
	
	this.search_layer = this.addLayer();
	
	
	this.setIcon();	
	
	/**
	* initializeMap() initializes the map
	* @param {Object} options is an object containing the map options
	*/
	function initializeMap(options){
	
	
		
	
		//change this! just for testing! needs to be clean, e.g as argument passed in the options!!!
		
		
		this.map.enableContinuousZoom();
		
		if (options) {
		
			try {
			
				var center;
				
				if (options.lat && options.lng) 
					center = new GLatLng(options.lat, options.lng);
				
				else 
					center = new GLatLng(options.center_lat, options.center_lon);
				
				
				this.map.setCenter(center);
				
				this.center = center;
				
				if (options.show_shapes) {
				
					this.show_shapes = options.show_shapes;
				}
				
				this.data_url = options.data_url;
				this.kml_file_repository = options.kml_file_repository;
				
			} 
			catch (e) {
			
			}
			
			
			
			if (options.alpstein_map == 'true') {
			
			
			
				//add outdooractive map
				alp.gmap.api.add(this.map);
				
				var alpstein_map = this.map.getCurrentMapType();
				
				var map_types = this.map.getMapTypes();
				
				var the_map = this.map;
				
				var map_obj = this;
				
				jQuery.each(map_types, function(){
				
					if (this != alpstein_map) 
						the_map.removeMapType(this);
				});
				
				
				
				this.map.addMapType(G_PHYSICAL_MAP);
				this.map.setMapType(G_PHYSICAL_MAP);
				
				if (options.min_zoom) {
				
					jQuery.each(map_types, function(){
						
						this.getMinimumResolution = function(){return options.min_zoom;};
					
					});
					
				}
				
				
		
				
								
				GEvent.addListener(this.map, 'zoomend', function(old_zoom, new_zoom){
				
					
							
					if (new_zoom <= 8) {
						if (the_map.getCurrentMapType() != G_PHYSICAL_MAP && old_zoom >= 8 ) 
							the_map.setMapType(G_PHYSICAL_MAP);
					}
					
					else {
						if (the_map.getCurrentMapType() != alpstein_map && old_zoom <= 8) 
							the_map.setMapType(alpstein_map);
					}
					
					/**
					 * marker tip functionality for certain zoom levels
					 */
					
					if(new_zoom > 6 && new_zoom < 10){
						
						map_obj.show_marker_tips = true;
						map_obj.showMarkerTips('number');
						
					}
					
					if(new_zoom >= 10){
						
						map_obj.show_marker_tips = true;
						map_obj.showMarkerTips('all');
						
					}
					
					
					if(new_zoom <= 6){
						
						map_obj.hideMarkerTips();
						map_obj.show_marker_tips = false;
					}
										
				});
				
																
				//this.map.addControl(new GMenuMapTypeControl(false) );
				
				
				
				
			}
			else {
				this.side_map = true;
			}
			
			
				if (options.map_type) {
					
					this.map.setMapType(eval(options.map_type));
					
				}			
			
			
			
			if (options.zoom) {
			
				this.map.setZoom(options.zoom);
				
				this.zoom = parseInt( options.zoom, 10 );
				
				
			}
			
			if (options.side_map_zoom && this.side_map) {
				
				this.side_map_zoom = options.side_map_zoom;
				this.map.setZoom(options.side_map_zoom);
				
			}
		}
		
		if(options.max_cluster_level){
			
			this.max_cluster_level = options.max_cluster_level;
					
			
		}
		
		
		if (options.search_control == 'true') {
		
			this.search_control = new SearchControl(this.lang);
			
			this.search_control.map_handler = this;
			
			this.map.addControl(this.search_control);
			
			this.search_control.setMapObject(this);
		}		
		
		//this.importXMLOverlay('http://automatisiere.info/wp-content/plugins/geo-viz/austria_invers.kmz');

		//var sw = new GLatLng(45.31228089776944, 9.20277912965957);
		//var ne = new GLatLng(49.43579135592488, 17.73537603876007);
		//bundeslaender = new GGroundOverlay('http://automatisiere.info/wp-content/plugins/geo-viz/bundeslaender.png', new GLatLngBounds(sw, ne)); 
		//this.map.addOverlay(bundeslaender);
		
		/*
		
		var cluster = new ClusterMarker(this.map);
		var marker, markersArray=[];
		
		var layer = this.addLayer();
		
		
	 
	 	for (j = 0; j < 50; j++) {
			
			var content = '<h1>Salzburg</h1>';
			content = content + '<p>In Salzburg gibt es viele schöne Berge</p>';
			content = content + '<img src="http://schulschachstiftung.schulschach-bayern.de/uploads/salzburg.jpg"></img>';
						
			var marker = this.createMarker(new GLatLng(47.09306407263186 + j / 50, 15.40283203125 + j / 50),null ,"marker", content );
			
			cluster.addMarkers([marker]);
			
						
			var shape = new Shape('point', null, marker);
						
		}
	
							
		
		
		cluster.fitMapToMarkers();
		*/
		
		

		
	}
	
	
	/**
	 * binds the clusterer to a maximum zoom level
	 */
	
    function bindClustererToMaxZoom (clusterer, max_zoom){
    
        if (!clusterer || !max_zoom) 
            return;
        
        GEvent.addListener(this.map, 'zoomend', function(old_zoom, new_zoom){
        
        
            if (new_zoom > max_zoom) {
                if (clusterer.clusteringEnabled == true) 
                    clusterer.clusteringEnabled = false;
               		clusterer.refresh(true);
            }
            
            else {
                
                
                if (clusterer.clusteringEnabled == false) {
                
                    clusterer.clusteringEnabled = true;
                    clusterer.refresh(true);
                    
                }
            }
            
            
            
        });
        
        
        
        
        
    }
	
	
	/**
	 * addLayer() adds a new shape layer to the map
	 * 
	 */
	
	function addLayer(layer_name){
		
		var new_layer = null;
		
			
		if (layer_name) {
			
			if (this.getLayerByName(layer_name) ) {
				
				new_layer = this.getLayerByName(layer_name);
			}
			
			else {
				new_layer = new Layer();
				this.layers.push(new_layer);
				
				this.layer_names[layer_name] = new_layer;
			}
			
			
			
		}
		else {
			var new_layer = new Layer();
			this.layers.push(new_layer);
		}
		
		return new_layer;
	}
	
	
	/**
	 * returns a layer by its name
	 * @param {String} name the layers name.
	 */
	
	function getLayerByName(name){
		
		return this.layer_names[name];
		
		
	}
	
	/**
	 * 
	 * @param {Object} id
	 */
	function getShapeById(id){
					
		return this.shapes[id];	
		
	}
	
	
	/**
	 * add a shape to the map and store it in the appropriate layer. If no layer is 
	 * specified, a new one is created
	 * @param {Object} shape
	 * @param {Object} layer
	 */
	
	function addShape(shape, layer, clusterer){
		
			
		
		if (!layer) {
			layer = this.addLayer();
				
		}
		
		var marker = shape.getMarker();
		var shape_obj = shape.getShapeObj();
		var id = shape.getId();
		
				
		if (marker) {
			
			
			if (clusterer) {
					
				clusterer.addMarkers([marker]);
			} else {
				// TODO dicke exception im ie7
				this.map.addOverlay(marker);
			}
		}
		
		if (shape_obj) {
			this.map.addOverlay(shape_obj);
		}
		
		if(id){
			
			
			this.shapes[id] = shape;
			
			
		}	
		
			layer.addShape(shape);
		
		if(marker !== null && shape_obj !== null && this.show_shapes == false){
						
			shape_obj.hide();
			
			GEvent.addListener(marker, "mouseover", function(){
				
				shape_obj.show();
				}
				);
			
			GEvent.addListener(marker, "mouseout", function(){
				
				shape_obj.hide();
				}
				);
	
		}
		
		
	
		
	}
	
	
	/**
	 * hideLayer(Layer) hides all shapes contained in a specific layer.
	 * @param {String} layer_name can be 'regions', 'businesses', 'events', 'bestof' or 'tours'
	 */
	function hideLayer(layer_name){
		
		if(!layer_name)
			return;	
		
		var clusterer;	
					
		if (layer_name == 'regions') {
			layer = this.regions_layer;
			clusterer = this.region_marker_clusterer;
			
		}
				
		if (layer_name == 'events') {
			layer = this.events_layer;
			clusterer = this.events_marker_clusterer;
		}
			
		if (layer_name == 'businesses') {
			layer = this.businesses_layer;
			clusterer = this.businesses_marker_clusterer;
		}
		
		if (layer_name == 'bestof') {
			layer = this.bestof_layer;
			clusterer = this.bestof_marker_clusterer;
		}
			
		if (layer_name == 'tours') {
			
			layer = this.tours_layer;
			clusterer = this.tours_marker_clusterer;
			
		}
		
		
		
		if(!layer)
			return;	
	
		clusterer.clearMarkers();
		clusterer = null;
		
		var shapes = layer.getShapes();
		
				
		for(index = 0; index < shapes.length ; index++){
			
			try {
				
				shapes[index].hide();
			}
			catch(e){
				
				
			}
		}
		
		
		
		if (layer.xml_overlay) {
			layer.xml_overlay.hide();
		}
				
	}
	
	
	/**
	 * showLayer(layer_name) shows all shapes contained in a specific layer.
	 * @param {String} layer_name can be 'regions', 'businesses', 'events', 'bestof' or 'tours'
	 */
	function showLayer(layer_name){
		
		if(!layer_name)
		return;	
			
		
		
		var clusterer;	
					
		if (layer_name == 'regions') {
			layer = this.regions_layer;
			clusterer = this.region_marker_clusterer = new ClusterMarker(this.map);
		}
				
		if (layer_name == 'events') {
			layer = this.events_layer;
			clusterer = this.events_marker_clusterer = new ClusterMarker(this.map);
		}
			
		if (layer_name == 'businesses') {
			layer = this.businesses_layer;
			clusterer = this.businesses_marker_clusterer = new ClusterMarker(this.map);
		}
		
		if (layer_name == 'bestof') {
			layer = this.bestof_layer;
			clusterer = this.bestof_marker_clusterer = new ClusterMarker(this.map);
		}
			
		if (layer_name == 'tours') {
			layer = this.tours_layer;
			clusterer = this.tours_marker_clusterer = new ClusterMarker(this.map);
		}

		if(!layer)
			return;	
			
		var shapes = layer.getShapes();
		
	
				
		for(index = 0; index < shapes.length ; index++){
			
			try {
				
				shapes[index].show();
				marker = shapes[index].getMarker();
				if(marker){
					clusterer.addMarker(marker);
					
					}
					
					
			}
			catch(e){
				
				
			}
		}
		
		
		
			
		if (layer.xml_overlay) {
			layer.xml_overlay.show();
		}
				
	}
	
	
	/**
	 * getLayers() gets a GeoViz object's layers
	 * @return {Layer []} layers is an array of layers contained in the map
	 */
	function getLayers(){
		
		return this.layers;
	}
	
	/**
	 * createMarker(latlng, title, description)returns a GMarker object with 
	 * a given position and a given title. When clicking the marker, the description is shown
	 * @param {GLatLng} latlng
	 * @param {GIcon} icon is an optional GIcon for the marker
	 * @param {String} title
	 * @param {String} post_url
	 */
	
	function createMarker(latlng, icon,  title, post_url){
		
		var map = this;
			
				
		
	   var marker_options = {};
	   // ie7 fix
	   if( icon != null ) marker_options['icon'] = icon;
	   
	  
	   
	   var marker = new GMarker(latlng, marker_options);
	   
	 
	   
	   if (post_url && typeof(post_url) != 'undefined') {
	   		GEvent.addListener(marker, "click", function(){
	   			map.displayDescription(post_url);
	   		});
	   }
	  	  
		 if (title) {
		 	
					 	
			GEvent.addListener(marker, "mouseover", function(latlng){
			
			//if no latlng is specified, the event was probably triggered from outside	
			if(!latlng)
				latlng = marker.getLatLng();	
				
				
			
			var pos = map.map.fromLatLngToDivPixel(latlng);
			
			var pos_container = map.map.fromLatLngToContainerPixel(latlng);
			
			//register tooltip
			//-----------------------------------------
							
			pos.x = pos.x + 10;
			pos.y = pos.y + 10;
			
					
							
			if(pos_container.x > ( jQuery(document).width() ) /2 )
				pos.x = pos.x - 200;
					
			var height = jQuery('#'+map.host_element).height() ;
			
			
			if(pos_container.y > height - 50)
				pos.y = pos.y - 80;
        
			
					
								
			var div = map.tooltip;
			try {
				map.map.getPane(G_MAP_FLOAT_PANE).removeChild(div);
			}
			catch(e){};				
	      
	        
			
			if(map.lang == 'en')
				div.innerHTML = '<h4 class="tooltip">'+title+'</h4>'+'<p>click for more info...</p>';
			
			else if(map.lang == 'cs')
				div.innerHTML = '<h4 class="tooltip">'+title+'</h4>'+'<p>Klikněte pro více informací...</p>';
			
			else
				div.innerHTML = '<h4 class="tooltip">'+title+'</h4>'+'<p>klicken für mehr Infos...</p>';
	        
			
			div.style.position = "absolute";
			div.style.top = pos.y + 'px';
			div.style.left = pos.x + 'px';
			
						
			
	        map.map.getPane(G_MAP_FLOAT_PANE).appendChild(div);
			
					
		//----------------------------
       				
			
		 	});
		 	
		
			
			GEvent.addListener(marker, "mouseout", function(){
		 	
				var div = map.tooltip;
				try {
					map.map.getPane(G_MAP_FLOAT_PANE).removeChild(div);
				}
				catch(e){}
		 		
		 	});
			
			GEvent.addListener(marker, "click", function(){
				
		 	
		 			//$('#' + map.host_element + '_tooltip').dialog('destroy');		 		
		 		
		 	});
		 }
		  	   
		
		num_markers ++ ;
	
		return marker;
	}
	
	
	
	
	
	/**
	 * createPolyline(latlngs, color, weight, opacity) allows to create a path
	 * @param {GLatLng[]} latlngs point coordinates
	 * @param {String} color is an optinal hexadecimal color string in the form #RRGGBB
	 * @param {String} weight defines an optional width of the line
	 * @param {String} opacity defines the line's opacity by specifying a number between 0 and 1
	 * @return {GPolyline} line is the created line object
	 */
	
	function createPolyline(latlngs, color, weight, opacity){
		
		var line = null;
		
		
		try{
			line = new GPolyline(latlngs, color, weight, opacity);
			return line;
		}
		//if the line cannot be created with the provided parameters, 
		//try to create a line with default parameters
		catch(e){
			
			try {
				line = new GPolyline(latlngs);
				return line;
			}
			catch(ex){
				return null;
			}
		}
	}
	
	
	/**
	 * allows to create a Polygon by specifying a set of points, line- and fill colors, line- and fill opacity
	 * @param {GLatLng[]} latlngs defines the polygon's points
	 * @param {String} stroke_color defines the line color (e.g. #FF0011)
	 * @param {Number} stroke_weight defines the stroke weight
	 * @param {Number} stroke_opacity defines the stroke opacity (from 0 to 1)
	 * @param {String} fill_color defines the fill color (e.e. #FF0011)
	 * @param {Number} fill_opacity defines the fill opacity (from 0 to 1)
	 */
	
	function createPolygon(latlngs, stroke_color, stroke_weight, stroke_opacity, fill_color, fill_opacity){
		
		var polygon = null;
		
		
		try{
			polygon = new GPolygon(latlngs, stroke_color, stroke_weight, stroke_opacity, fill_color, fill_opacity);
			return polygon;
		}
		//if the polygon cannot be created with the provided parameters, 
		//try to create a polygon the with default parameters
		catch(e){
			
			try {
				polygon = new GPolygon(latlngs);
				return polygon;
			}
			catch(ex){
				return null;
			}
		}
		
		
	}
	
	/**
	 * createCustomIcon(options) creates a custom icon
	 * @param {Object} options contains an arbitrary number of options which define the 
	 * custom icon in a JSON style object notation, e.g {image : "pic.jpg", shadow: "shadow.jpg"}
	 */
	
	function setIcon(options){
		
	var marker = new GMarker( new GLatLng(0, 0));
	var icon = marker.getIcon();
	
	
		
		if(typeof(options) != 'object')
			return icon;
		
		jQuery.each(options, function(key, value){
						
			
			icon[key] = value;
					
		});
		
		//@TODO: set this size outside, as parameter as this changes from icon to icon
				
		
		if(!options['iconSize'])
		 icon.iconSize = icon.shadowSize = new GSize(41, 49);
		
		
		
		if(!options['imageMap'])	
			icon['imageMap'] = [0,0, 41,0, 41, 49, 0, 49];
 			
		
		this.icon = icon;
				
	}
	
	/**
	 * returns the icon used for clustering
	 */
	
	function ClusterIcon(){
			
			
		var imageMap = [0,0, 151,0, 151, 116, 0, 116];
	
		var icon_size = new GSize(151, 116);
		var shadow_size = icon_size;
		
		
	
		var options = {
			'image': MARKER_URL + '/clusterer/image.png',
			'shadow': MARKER_URL + '/clusterer/shadow.png',
			'transparent': MARKER_URL + '/clusterer/transparent.png',
			'imageMap': imageMap,
			'iconSize': icon_size
		} ;	
			
			
		var marker = new GMarker( new GLatLng(0, 0));
		var icon = marker.getIcon();
		
		
		
		jQuery.each(options, function(key, value){
							
				
				icon[key] = value;
						
		});
			
			
		return icon;
		
	}
	
	
	/**
	 * adds an XML shape layer to the map
	 * @param {String} url defines the url of a xml (e.g. KML) file
	 */
	function importXMLOverlay(url){
		
					
		var xml_overlay = new GGeoXml(url);
		this.map.addOverlay(xml_overlay);
			
		//add an xml overlay to the internal data representation
		
		
		this.addXMLOverlay(xml_overlay);			
		
		return xml_overlay;	

	}
	
	
	/**
	 * adds an xml_overlay object to the data structure of the map
	 * @param {GGeoXML} xml_overlay
	 */
	function addXMLOverlay(xml_overlay){
		
		this.xml_overlays.push(xml_overlay);
		
	}
	
 /***
 * addRegions(regions) adds regions to the map
 * @param {Object[]} regions is an array of objects. Each objects contains information about one
 * region to be added to the map.
 */

function addRegions(regions){
	
 var region_number = 1;
		
	if(!regions)
		return;
	
 	if (this.region_marker_clusterer == null) {
		
		
	


		this.region_marker_clusterer = new ClusterMarker(this.map);
		
		
	}
	

	//var imageMap = [44,9,50,10,53,11,55,12,57,13,58,14,59,15,60,16,61,17,61,18,62,19,62,20,63,21,63,22,63,23,63,24,63,25,63,26,63,27,63,28,63,29,63,30,63,31,63,32,63,33,63,34,63,35,63,36,63,37,63,38,63,39,63,40,63,41,63,42,63,43,63,44,63,45,63,46,63,47,62,48,62,49,61,50,60,51,59,52,58,53,57,54,56,55,54,56,51,57,46,58,19,58,14,57,12,56,10,55,8,54,7,53,6,52,5,51,5,50,4,49,3,48,3,47,3,46,2,45,2,44,2,43,1,42,1,41,1,40,1,39,1,38,1,37,1,36,1,35,1,34,1,33,1,32,1,31,1,30,1,29,1,28,1,27,1,26,1,25,2,24,2,23,2,22,3,21,3,20,3,19,4,18,5,17,5,16,6,15,7,14,9,13,10,12,12,11,15,10,21,9];	
			
	var imageMap = [0,0, 24,0, 24,24 ,0,24];
	
	var icon_size = new GSize(24, 24); //was 64, 64
	var shadow_size = icon_size;
	
	
	
	
	this.regions_layer  = this.addLayer();
	
	
	var map = this;

		//var loaded_ids = {};
		
		jQuery.each(regions, function(index){
		
		// was wenn keine id da?
		var id = null;
		if(this.id)
			id = this.id;
		
			/*if( typeof loaded_ids[id] != "undefined" ) return;
			loaded_ids[id] = id;*/
			
			if (this.position != null) {
				
				//if( typeof console != "undefined" ) console.log(this);
				
				var post_url;
				
				if(this.url)
				 	post_url = this.url;
					
				else
					post_url = buildPostUrl(this.geog_name);
				
				
				var image = MARKER_URL + '/regionen/image.png';
				
				if(this.icon){
					
					image = this.icon;
				}
					
				map.setIcon({'image' : image, 'shadow' : MARKER_URL + '/regionen/shadow.png', 'transparent': MARKER_URL +  '/regionen/transparent.png', 'imageMap': imageMap , 'iconSize': icon_size, 'shadowSize': shadow_size});		
				
				var marker = map.createMarker(new GLatLng(this.position.lat, this.position.lng), null, this.geog_name, post_url);
				
								
				GEvent.addListener(marker, "mouseover", function(){
	   				
					marker.setImage(MARKER_URL + '/regionen/region_pin_highlight.png');
					map.hideMarkerTips(id);
					
										
					
	   			});
				
				GEvent.addListener(marker, "mouseout", function(){
	   				
					marker.setImage(image);
					map.showMarkerTips('all',id);
	   			});
				
								
								
				var shape = new Shape('point', null, marker, id);
				
				//try {
				
				//map.addShape(shape, map.regions_layer, map.region_marker_clusterer);
				
				//regions are added without clustering for now!!!!!!!
				
				/**
				 * if no particular layer is specified (e.g for bundesland etc.) 
				 * the shape is added to the global regions_layer
				 */
				
				if(this.layer_name ){ // legt das den layer nicht mehr mals an?
					
					var new_layer = map.addLayer(this.layer_name);
					
															
					map.addShape(shape, new_layer);
										
				}
				else
					map.addShape(shape, map.regions_layer);
				
				/*} catch(exception) {
			
					alert(exception.message)
			
				}*/	
				
				var marker_number = region_number + ''; //convert to number to a string
				if(marker_number.length == 1)
					marker_number = '0'+region_number;
				
				//TODO fix properly, this is just a quickfix!!
								
				map.addMarkerTip({
					
						marker: marker,
						number: marker_number,
						id: id,
						tip: this.geog_name
				})
					
				
				
							
			} else {
				//if( typeof console != "undefined" ) console.log(this);
			}
	
				region_number ++ ; // das sollt ma immer incrementen - und bitte versuchen ifs auf a seite höhe zu beschränken, damit ma a bissal den überblick hat
				
			

			
			
			
		});
		
	
		
		
		
		/*
		
		map.hideAllRegions();
		
		var layers_to_show = [];
		
		layers_to_show.push( map.getLayerByName('Tirol') );
		
		
		map.showRegions(layers_to_show);
		*/
		
					
			
	//this.region_marker_clusterer.resetViewport();
}


/**
 * adds a div to be displayed above a marker
 * @param {Object} config is the configuration object
 * e.g. config = {marker: marker, id: id, number: 1, tip: 'region Wildschönau',
 *  
 */
function addMarkerTip(config){
	
	if(!config.marker)
		return;

	var latlng = config.marker.getLatLng();	
								
	var div = document.createElement('div');
							
	div.innerHTML = '<span class="number">'+config.number+'</span><span class="tip">'+config.tip+'</span>';
			
	div.style.position = "absolute";
	div.style.backgroundColor = '#FFFFFF';								
			
	this.map.getPane(G_MAP_FLOAT_PANE).appendChild(div);
	jQuery(div).hide();
	
	
	div = jQuery(div);
	jQuery.data(div, 'position', latlng);
					
	if(config.id && typeof(div) != 'undefined')
		this.icon_tips[config.id] = div;
				
}


/**
 * displays all marker tips
 * @param {String} what defines wheter the whole tip should be shown or just 
 * the number. Possible values are 'number' | 'all'
 * if no id is provided, all markers are shown, otherwise only the marker with the specified
 * id
 */
function showMarkerTips(what, id){
		
	if(this.show_marker_tips == false)
		return;
		
	var map = this;
	
	if (!id) {		
			
		jQuery.each(this.icon_tips, function(key, value){
			
						
			if (typeof(jQuery(this.icon_tips) != 'undefined')) {
			
			
				if (map.shapes[key]) {
				
					if (!map.shapes[key].getMarker().isHidden()) {
					
					
						if (typeof(value) != 'undefined') {
							var latlng = jQuery.data(value, 'position');
							
							var pos = map.map.fromLatLngToDivPixel(latlng);
							
							
							
							if (what == 'number') {
								value.find('.tip').hide();
								
								value.css({
									'font-family': 'Arial',
									'padding': '0px',
									'left': pos.x - 3 + 'px',
									'top': pos.y - 29 + 'px',
									'background': 'none',
									'color': '#FFFFFF',
									'font-size': '10px'
								
								});
								
								
							}
							
							else {
								value.find('.tip').show();
								
								value.click(function(){
								
									try {
									
										GEvent.trigger(map.shapes[key].getMarker(), 'click');
									} 
									
									catch (e) {
									}
								})
								
								
								value.css({
									'font-family': 'Arial',
									'height': 'auto',
									'background': '#E8E8E8',
									'opacity': '0.8',
									'padding': '3px',
									'left': pos.x + 13 + 'px',
									'top': pos.y - 20 + 'px',
									'background': 'none',
									'color': '#000000',
									'background-color': '#FFFFFF',
									'font-size': '12px',
									'cursor': 'pointer'
								
								});
								
							}
							
							value.show();
							
						}
						
						
						
					}
					
					
				}
			}

		});
		
	}
	
	else{
		
		try{
			
			this.icon_tips[id].show();
		}
		
		catch(e){
			
			//nothing for now. 
		}
	}
	
	
}

/**
 * if an id is specifiey a particular marker tip is hidden
 * if no id is provided, all marker tips are hidden
 */

function hideMarkerTips(id){
	
	if (!id) {
	
		jQuery.each(this.icon_tips, function(key, value){
		
			//get the correct marker over the tip's id
			if (typeof(value) != 'undefined') 
				value.hide();
		});
		
	}
	
	else{
		
		try{
			
			this.icon_tips[id].hide();
		}
		
		catch(e){
			
			//nothing for now. 
		}
	}
}




/**
 * hides all regions on the map
 */

function hideAllRegions(){
	
	var layers = this.layer_names;	
		
	
		
		jQuery.each(layers, function(index){
						
			this.hide();
			
				
		});
		

	
		
	this.hideMarkerTips();	
}

/**
 * shows all Regions on the map specified in the regions parameter
 * @param {Object} regions to be displayed. If null, all regions are displayed.
 * Regions is an array of shape layer objects.
 * 
 */

function showRegions(regions){
	
	var map = this;	
		
	//if no particular regions are specified, show all
	if(!regions){
		
		var layers = this.layer_names;	
		
			
		jQuery.each(layers, function(index){
						
			this.show();
			
				
		});
		
		if(map.map.getZoom() > 6 && map.map.getZoom() < 10 )		
			map.showMarkerTips('number');
			
		else
			map.showMarkerTips('all');
		
	}
	
	else{
		
		jQuery.each(regions, function(){
			
			
			this.show();
			
		})
		
		
		if(map.map.getZoom() > 6 && map.map.getZoom() < 10 )		
			map.showMarkerTips('number');
			
		else
			map.showMarkerTips('all');
		
		
		return;
	}
	

}


 /***
 * addPoints
 * @param {Object[]} is an array of objects.
 * 
 */

this.addPoints = function (points, draw_path){
	
	
		
	if(!points)
		return;
	
 	if (this.marker_clusterer == null) {
		
		this.marker_clusterer = new ClusterMarker(this.map);
		
	}
	
	var path = [];
			

	//var imageMap = [44,9,50,10,53,11,55,12,57,13,58,14,59,15,60,16,61,17,61,18,62,19,62,20,63,21,63,22,63,23,63,24,63,25,63,26,63,27,63,28,63,29,63,30,63,31,63,32,63,33,63,34,63,35,63,36,63,37,63,38,63,39,63,40,63,41,63,42,63,43,63,44,63,45,63,46,63,47,62,48,62,49,61,50,60,51,59,52,58,53,57,54,56,55,54,56,51,57,46,58,19,58,14,57,12,56,10,55,8,54,7,53,6,52,5,51,5,50,4,49,3,48,3,47,3,46,2,45,2,44,2,43,1,42,1,41,1,40,1,39,1,38,1,37,1,36,1,35,1,34,1,33,1,32,1,31,1,30,1,29,1,28,1,27,1,26,1,25,2,24,2,23,2,22,3,21,3,20,3,19,4,18,5,17,5,16,6,15,7,14,9,13,10,12,12,11,15,10,21,9];	
			
	//this.setIcon({'image' : MARKER_URL + '/region/image.png', 'shadow' : MARKER_URL + '/region/shadow.png', 'transparent': MARKER_URL +  '/region/transparent.png', 'imageMap': imageMap });	
	
	this.setIcon();
	
	var layer  = this.addLayer();
	
	
	var map = this;
	
			
		jQuery.each(points, function(index){
						
		
			
			if (this.position != null) {
				var post_url;
				
				if(this.url)
				 	post_url = this.url;
					
								
								
				var marker = map.createMarker(new GLatLng(this.position['lat'], this.position['lng']), null, this.title, post_url);
										
										
				
				var shape = new Shape('point', null, marker);
				
				
				map.addShape(shape, layer);
				
				if(draw_path){
					
					path.push( new GLatLng(this.position['lat'], this.position['lng']) );
				}
				
			
			}							
		
			
		});
		
		
		if(draw_path)
			this.map.addOverlay(new GPolyline(path));
		
					
}

/***
 * addEvents(Events) adds events to the map
 * @param {Object[]} regions is an array of objects. Each objects contains information about one
 * region to be added to the map.
 * @TODO: check exact data structure of events object to correctly display markers
 */

function addEvents(events){
	
	if(!events)
		return;
		
	if(this.max_cluster_level)
		this.bindClustererToMaxZoom(this.events_marker_clusterer, this.max_cluster_level);	
		
		
	
	this.setIcon({'image' : MARKER_URL + '/' + this.custom_icon_folder +'/image.png', 'shadow' : MARKER_URL + '/' + this.custom_icon_folder +'/shadow.png', 'transparent': MARKER_URL +  '/' + this.custom_icon_folder + '/transparent.png'});	
	
	this.events_layer = this.addLayer();
	 
	
	var map = this;
				
		jQuery.each(events, function(index){
			
			
							
			try {
				 
				//jQuery.each(this.entries, function (index){
							
					var name = '';
					
					if(this.name)		
						name = this.name;
					
					var post_url = "";
						
					if(this.url)
						post_url = this.url;
						
					var marker = map.createMarker(new GLatLng(this.position.lat, this.position.lng), null, this.name, post_url);
				
				
					var shape = new Shape('point', null, marker);
				
				
					map.addShape(shape, map.events_layer, map.events_marker_clusterer);
				
					
				
				//});
								
			}
			catch(exception){
				
								
			}
			
		
		});
			
}

/**
 * adds Businesses to the map
 * @param {Object} businesses
 */

function addBusinesses(businesses){
	
	if(!businesses)
		return;
	
	if(this.max_cluster_level)
		this.bindClustererToMaxZoom(this.businesses_marker_clusterer, this.max_cluster_level);	
			
	// businesses.data contains a number of objects
	//object_container_element1840_object_def354 defines the business name
	
	this.setIcon({'image' : MARKER_URL + '/' + this.custom_icon_folder +'/image.png', 'shadow' : MARKER_URL + '/' + this.custom_icon_folder +'/shadow.png', 'transparent': MARKER_URL +  '/' + this.custom_icon_folder + '/transparent.png'});	
	
	this.businesses_layer = this.addLayer();
	 	
	var map = this;

			
	jQuery.each(businesses, function(index){
			
										
			try {
				
				var post_url;
				
				if(this.url)
					post_url = this.url;
					
				else
					post_url = 	buildPostUrl(this.object_container_element1840_object_def354);	
								
				var marker = map.createMarker(new GLatLng(this.position.lat, this.position.lng), null, this.object_container_element1840_object_def354, post_url);
				var shape = new Shape('point', null, marker);
				
				map.addShape(shape, map.businesses_layer, map.businesses_marker_clusterer);
				
																
			}
			catch(exception){
				
								
			}
			
		
		});
	
}


/**
 * adds a location
 * @param {Object} lat
 * @param {Object} lng
 * @param String name is optional
 * @param String bubble if specified, the content of bubble is displayed in a speech bubble
 * open by default
 */
function addLocation(lat, lng, name, bubble){
		
	
	this.setIcon({'image' : MARKER_URL + '/' + this.custom_icon_folder +'/image.png', 'shadow' : MARKER_URL + '/' + this.custom_icon_folder +'/shadow.png', 'transparent': MARKER_URL +  '/' + this.custom_icon_folder + '/transparent.png'});	
	
	if(!lat || !lng)
		return;

	if(!name)
		name = "";

	var marker = this.createMarker(new GLatLng(lat, lng), null, name);

	if(bubble){
				
		marker.bindInfoWindowHtml(bubble, {'PixelOffset': new GSize(20,20)} );
		
		marker.openInfoWindowHtml(bubble, {pixelOffset: new GSize(20,20)} );
				
	}
				
	var shape = new Shape('point', null, marker);
	
	this.addShape(shape);
	

	
	if (this.side_map == true) {
		
		
		this.map.setCenter(new GLatLng(lat, lng));
		
		var width = jQuery('#'+ this.host_element).width();
		var height = jQuery('#'+ this.host_element).height();
		
		var new_x = width - width/5;
		var new_y = height - height/3;
				
		var new_center = this.map.fromContainerPixelToLatLng(new GPoint(new_x, new_y) );
			
		
		this.map.setCenter(new_center);
				
		
				
	}
	


}

/***
 * addTours adds tours to the map
 * @param {Object} tours
 */

function addTours(tours){

	
	//@TODO: should KML files really be accessible by URL?
	

			
	if(!tours || tours == '')
		return;
		
	if(this.max_cluster_level)
		this.bindClustererToMaxZoom(this.tours_marker_clusterer, this.max_cluster_level);	
		
	
	
	this.setIcon({'image' : MARKER_URL + '/' + this.custom_icon_folder +'/image.png', 'shadow' : MARKER_URL + '/' + this.custom_icon_folder +'/shadow.png', 'transparent': MARKER_URL +  '/' + this.custom_icon_folder + '/transparent.png'});	
	
	this.tours_layer = this.addLayer();
		
	var map = this;
	
			
		jQuery.each(tours, function(index){
						
		try {
			
			var post_url;
			
			if(this.url)
				post_url = this.url;
			
			else
				post_url = buildPostUrl(this.title);	
						
			var marker = map.createMarker(new GLatLng(this.start_lat, this.start_lng), null, this.title, post_url);
			
			
			var shape = new Shape('xml', null, marker);
			map.addShape(shape, map.tours_layer, map.tours_marker_clusterer);
			
			var tour_id = this.tour_id;
			var tour_title = this.title;
		
									
			if (tour_id) {
	   
	   			GEvent.addListener(marker, "mouseover", function(){
					
				if(map.currently_visible_path != null){
					
					map.currently_visible_path.hideShapeObj();
				}	
				
				map.currently_visible_path = shape;
	   			
				if(shape.getShapeObj() == null){
				
					
				shape.shape_obj = map.importXMLOverlay(map.kml_file_repository + '/' + tour_id + '.kml');
	   			
				
				}
				else
					shape.showShapeObj();
					
			
			});
			
			GEvent.addListener(marker, "mouseout", function(){
	   			
				
				shape.hideShapeObj();
				
	   		});
	   
	   }
			
			
		}
		catch(exception){
			
		}
			
								
		
			
		});
		
			
	
}

/**
 * adds Best of data to the map
 * @param {Object} bestof
 */

function addBestOf(bestof){


	if(!bestof || bestof == "")
		return;
		
	if(this.max_cluster_level)
		this.bindClustererToMaxZoom(this.bestof_marker_clusterer, this.max_cluster_level);	
		
			
	this.setIcon({'image' : MARKER_URL + '/' + this.custom_icon_folder +'/image.png', 'shadow' : MARKER_URL + '/' + this.custom_icon_folder +'/shadow.png', 'transparent': MARKER_URL +  '/' + this.custom_icon_folder + '/transparent.png'});	
	
	this.bestof_layer  = this.addLayer();
		
	var map = this;
	
				
		jQuery.each(bestof, function(index){
										
			try {
				 
				//jQuery.each(this.entries, function (index){
					
					
												
					var post_url;
					
					if(this.url)
						post_url = this.url;
						
					else
						post_url = buildPostUrl(this.bestof_name);		
					
																	
					var marker = map.createMarker(new GLatLng(this.position.lat, this.position.lng), null, this.bestof_name, post_url);
								
					var shape = new Shape('point', null, marker);
								
					map.addShape(shape, map.bestof_layer, map.bestof_marker_clusterer);
					
					//if(this.position.lat == 47.516231 && this.position.lng == 14.550072)
						//console.log(post_url);
				
		
				
				//});
								
			}
			catch(exception){
				
							
			}
			
		
		});
		
}

/**
 * displays a single tour on the map
 * @param tour_kml
 * @param file_repository
 */

function displaySingleTour(kml_url, center){
	

	
	//@TODO: should KML files really be accessible by URL?
	
	if( !kml_url)
		return;
		
	//alert(kml_url);	
					
	var kml_overlay = this.importXMLOverlay(kml_url);	
	
	var zoom = this.zoom;
	
	if(!center)
		center = this.center;
	
	if (center) {
		this.map.setCenter(center, zoom);
	 		
	}
		
	
						
			
	
}

/**
 * returns the layer object corresponding to the layer type
 * @param {Object} type
 */


this.getLayerByType = function(type){
	
	if(!type)
		return null;
	
	switch (type) {
		case "regions":
			return this.regions_layer;
			
		case "businesses":
			return this.businesses_layer;
			
		case "bestof":
			return this.bestof_layer;
			
		case "events":
			return this.events_layer;
			
		case "tours":
			return this.tours_layer;
			
		default:
			return null;
			
	}
}


/***
 * if the regions layer already exists, it is shown, otherwise data is loaded 
 * @type string defines the type of data to be shown
 * 'regions', 'businesses', 'bestof', 'events' or 'tours'
 */

this.showDataLayer = function(type){


	if(!type)
		return;	
		
	if(type == this.last_displayed_layer)
		return;
			
	
		
	if(this.last_displayed_layer != "")
		this.hideLayer(this.last_displayed_layer);	
		
	
	var img_src = 'http://' + document.domain + '/wp-content/plugins/geo-viz/images/loading.gif';
	$('#'+this.host_element).block({ css: { 
            border: 'none', 
            padding: '15px',
			top: '74px',
			left: '0px',
			height: '372px',
			width: '100%',
			backgroundColor: '#e5e4e3', 
            opacity: .4, 
            color: '#000000' 
			},			
			message: '<img style="position:absolute; top: 150px;" src="' + img_src + '"></img>'
        });
      
	//zoom level is decreased by 1. after the data have been loaded, the zoom level
	//is increased again. This is a simple trick to force the clusterer to cluster
	//the pins in the right way, as clusterer.resetViewport() does not work properly
	//for this case
	
	this.map.setZoom( this.map.getZoom() - 1, true);
	
	  
		 	
	var map = this;	
		
	var layer = this.getLayerByType(type);
			
	if(layer == null){
		
		
			jQuery.ajax({
				url: this.data_url,
				data: {'type' : type},
				
				success: function(data){
					
					try { // is der silent block ent a bissal evil? :)
						switch (type) {
						
							case "regions":
								map.addRegions(eval(data));
								break;
								
							case "businesses":
								map.addBusinesses(eval(data));
								break;
								
							case "bestof":
								map.addBestOf(eval(data));								
								break;
								
							case "events":
								map.addEvents(eval(data));
								break;
								
							case "tours":
								map.addTours(eval(data));
								break;
								
						}
					}
					catch(e){
						
						map.map.setZoom( map.map.getZoom() + 1, true);						
						$('#'+map.host_element).unblock();
					}
					
					map.last_displayed_layer = type;	
					
					map.map.setZoom( map.map.getZoom() + 1, true);		
					$('#'+map.host_element).unblock();
					
				}
			});
			
			
		
		
	}
	
		
		
	else{
			
		
		this.showLayer(type);
		this.last_displayed_layer = type;
		
		this.map.setZoom( this.map.getZoom() + 1, true);
		setTimeout( ($('#'+this.host_element).unblock() ), 100);
	}
}


/**
 * slides the map from right to left
 */

this.slideMapIn = function(){
	
	var map  = '#' +  this.host_element;
	
	$(map).animate( {'margin-left': '5%' , 'height': '300px'} , 'slow' ).animate( {'opacity': '1'} , 'slow' );
	
}

/**
 * adds a search resutlt to the map
 * @param {Object} response
 */

this.addSearchResult  = function(result){
		
					
			
		if(!result)
			return;
			
		this.map.savePosition();	
		
		var shapes = this.search_layer.getShapes();
	
			//@TODO: do not hide shape, do actually delete it!!
		if(shapes.length > 0){
		
			shapes[shapes.length - 1].hide();
		
		}
		
		var search_icon= new GIcon();
		
		search_icon.image= MARKER_URL + '/search/image.png',
		search_icon.iconSize=  new GSize(31, 39);
		search_icon.iconAnchor =new GPoint(15, 39);
		
		search_icon.infoWindowAnchor=new GPoint(0, 0);
		
		search_icon.shadow= MARKER_URL + '/search/shadow.png',
		search_icon.shadowSize= search_icon.iconSize;
		
									
			
			
			
		var latlng = new GLatLng(result.Point.coordinates[1], result.Point.coordinates[0]);
						
		var marker = this.createMarker( latlng, search_icon, result.address, null);
	
	
		
		var shape = new Shape('point', null, marker);
				
				
		this.addShape(shape, this.search_layer);
		
	
			
		this.map.setCenter(latlng);
			
	
		
}

/**
 * clears a search result and resets the map view
 */

this.clearSearchResult = function(){
	
	
	var shapes = this.search_layer.getShapes();
	
	//@TODO: do not hide shape, do actually delete it!!
	if(shapes.length > 0){
		
		shapes[shapes.length - 1].hide();
		
	}
	
	this.map.returnToSavedPosition();
}


/**
 * displayDescription(description) displays a text in a fancy box
 * @param {Object} description
 */
	
function displayDescription(post_url){
	

		
	var map = this;
	
	
	var fancy_box_link = jQuery('<a href="'+post_url+'"></a>');
	fancy_box_link.fancybox();
	fancy_box_link.click();
	return;
	/*
			
	var position = geo_viz_dialog_options.position;
	
		
	var offset = ($('#' + map.host_element)).offset();
	var scroll_top = jQuery(window).scrollTop();
	
	offset.top = offset.top - scroll_top;
	geo_viz_dialog_options.position = ['center' ,offset.top];
	
	
	
	$('#' + map.host_element + '_dialog').html('wird geladen...');
	$('#' + map.host_element + '_dialog').dialog(geo_viz_dialog_options);
	$('#' + map.host_element + '_dialog').dialog('open');
	
	jQuery.ajax({ url: post_url, success: function(data){
       
			$('#' + map.host_element + '_dialog').html(data);
			
		
     }});
	*/
	

}
	


	
}




/**
 * class Layer defines a shape layer to be displayed on the map. A shape layer can contain
 * an arbitrary number of shapes.
 */

function Layer(){
	
	this.content = []; //an array of markers
	
	
	if (typeof(this.Layer_prototype_called) == 'undefined') {
	
		Layer.prototype.addShape = addShape;
		Layer.prototype.getShapes = getShapes;
		Layer.prototype.hide = hide;
		Layer.prototype.show = show;
		
		Layer.prototype.Layer_prototype_called = true;	
	}

	/**
	 * addShape(shape) allows to add a marker to the layer
	 * @param {Object} shape
	 */
	
	function addShape(shape){
		
		this.content.push(shape);		
	}
	
	/**
	 * hides all shapes contained in the layer
	 */
	function hide(){
		
		var shapes = this.getShapes();
		
		
		
		if(shapes.length != 0){
			
			for(index = 0; index < shapes.length ; index++){
			
			try {
				
				shapes[index].hide();
			}
			catch(e){
				
				
			}
		}
		}
				
				
		
		
	}
	
	
	/**
	 * shows all shapes contained in the layer
	 */
	function show(){
		
		var shapes = this.getShapes();
		
		
		
		if(shapes.length != 0){
			
			for(index = 0; index < shapes.length ; index++){
			
			try {
				
				shapes[index].show();
			}
			catch(e){
				
				
			}
		}
		}
				
				
		
		
	}
	
	/**
	 * getShapes() returns the Layer's shapes
	 * @return {shapes[]} shapes
	 */
	function getShapes(){
		
		return this.content;
	}	
	
	
	function clear(){
		
		this.content = [];
	}
	
}


/**
 * class Shape defines a single shape on the map. A shape consists of a geometric 
 * shape (GPolyline or GPolygon) and a Gmarker. The shape type can be 'point', 'line' or
 * 'polygon' 
 * @param {String} type defines the shape's type ['point', 'line', 'polygon' or 'xml']
 * @param {GPolyline | GPolygon | XMLOverlay} defines a google maps shape (optional)
 * @param {GMarker} defines a google maps marker (optional)
 */


function Shape(type, shape_obj, marker, id){
	
	if(id)
		this.id = id;
		
	this.type = type;
	this.shape_obj = shape_obj; //either GPolyline, GPolygon or null
	this.marker = marker; //either a GMarker or null
	
	if (typeof(Shape_prototype_called) == 'undefined') {
	
		Shape.prototype.getMarker = getMarker;
		Shape.prototype.getShapeObj = getShapeObj;
		Shape.prototype.getType = getType;
		Shape.prototype.show = show;
		Shape.prototype.hide = hide;
		Shape.prototype.getId = getId;
		Shape.prototype.showShapeObj = showShapeObj;
		Shape.prototype.hideShapeObj = hideShapeObj;
		Shape.prototype.Shape_prototype_called = true;
	}
	
	/**
	 * returns a shape's id
	 */
	function getId(){
		
		if(this.id)
			return this.id;
			
		else
			return null;
	}
	
	
	/**
	 * returns the marker
	 */
	function getMarker(){
		
		return this.marker;
	}
		
	/**
	 * returns the shape object
	 */
	function getShapeObj(){
		
		return this.shape_obj;
	}
	
	/**
	 * returns the shape's type
	 */
	function getType(){
		
		return this.type;
	}
	
	/**
	 * hides a shape
	 */
	
	function hide(){
		
	
		if(this.marker){
			this.marker.hide();
		}
		
		if(this.shape_obj){
			
			this.shape_obj.hide();
		}
		
		
	}
	
	/**
	 * hides the shape_obj
	 */
	
	function hideShapeObj(){
		
		if(this.shape_obj){
			
			this.shape_obj.hide();
		}
	}
	
	
	/**
	 * shows the shape_obj
	 */
	
	function showShapeObj(){
		
		if(this.shape_obj){
			
			this.shape_obj.show();
		}
	}
	
	/**
	 * shows a shape
	 */
	
	function show(){
		
		if(this.marker){
			this.marker.show();
		}
		
		//if(this.shape_obj){
			
			//this.shape_obj.show();
		//}
		
		
	}
	
	
}



/**
 * initializeMap(host_element) initializes the Map
 * @input string host_element html element hosting the map
 */

function initializeMap(host_element, options) {
	

	if(typeof(options) == 'undefined')
		options = null;	
			
	  map = new GeoViz(host_element);
	  	 	 
	  map.initializeMap(options);
	  
	  map.setIcon({'image' : MARKER_URL + '/' + map.custom_icon_folder +'/image.png', 'shadow' : MARKER_URL + '/' + map.custom_icon_folder +'/shadow.png', 'transparent': MARKER_URL +  '/' + map.custom_icon_folder + '/transparent.png'});	  
 



 //map.importXMLOverlay('http://www.outdooractive.com/de/kml_generate?pois=true&i=1556510672613084018');
   
	
	
		 
  //just for testing
		 
	 
	/* for (i = 0; i < 1; i++) {
	 var layer = map.addLayer();
	 	for (j = 0; j < 5; j++) {
			
			var content = '<h1>Salzburg</h1>';
			content = content + '<p>In Salzburg gibt es viele schöne Berge</p>';
			content = content + '<img src="http://schulschachstiftung.schulschach-bayern.de/uploads/salzburg.jpg"></img>';
						
			var marker = map.createMarker(new GLatLng(i + 47.09306407263186 + j / 4, i+ 15.40283203125 + j / 4),null ,"marker", content );
						
			var shape = new Shape('point', null, marker);
			map.addShape(shape, layer);
			
		}
			
	 	
	 }
	  
	  
	   var content = '<h1>Salzburg</h1>';
			content = content + '<p>In Salzburg gibt es viele schöne Berge</p>';
			content = content + '<img src="http://schulschachstiftung.schulschach-bayern.de/uploads/salzburg.jpg"></img>';
						
			var marker = map.createMarker(new GLatLng( 47.09306407263186 , 15.40283203125 ),null ,"marker", content );
						
			var shape = new Shape('point', null, marker);
			map.addShape(shape);
	  
	  var track = map.createPolyline( [new GLatLng(47,15), new GLatLng(48,16), new GLatLng(50,14)], "#FF0000", 25, 1 );
	  var marker = map.createMarker( new GLatLng(47, 15) );
	  var shape = new Shape('line', track, marker);
	  map.addShape(shape, layer);
	  
	  
	  var area = map.createPolygon( [new GLatLng(47.1,15), new GLatLng(48.1,16), new GLatLng(50.1,14), new GLatLng(47.1,15)], "#00FF00", 10, 1, "#0000FF", 0.5 );
	  var marker = map.createMarker( new GLatLng(47.1, 15) );
	  var shape = new Shape('polygon', area, marker);
	  map.addShape(shape, layer);

	  
	
	content = '<h1>Steiermark</h1>';
	content = content + '<p>In der Steiermark gibt es viele Wälder</p>';
	content = content + '<img src="http://www.gery-hofer.com/ennstal/Images/steiermark.gif"></img>';
	  	  
	 var custom_icon = map.createCustomIcon({'image' : MARKER_URL + '/hiker/image.png', 'shadow' : MARKER_URL + '/hiker/shadow.png', 'transparent': MARKER_URL + '/hiker/transparent.png'});	  

	 var new_marker = map.createMarker( new GLatLng(47.2, 15), custom_icon, "special marker", content );
	 var new_shape = new Shape('point', null, new_marker);
	 map.addShape(new_shape);
	 
	
	 
	 map.importXMLOverlay('http://bbs.keyhole.com/ubb/download.php?Number=438084');
	 map.importXMLOverlay('http://www.outdooractive.com/de/kml_generate?pois=true&i=471968756071032102');
	 map.importXMLOverlay('http://www.outdooractive.com/de/tour.georss.kml.jsp?owner=19bx526y1xey2&limit=10&start-index=1&pois=true'); 

  
	 // map.showLayer(layer);
	 
	 */

	

 }


/**
 * class SearchControl defines the class for a search control to be displayed on the map
 * It consists of an input field, allowing to search for addresses. In case of ambiguities,
 * a list is presented to the user, where he or she can select the most appropriate result
 */

function SearchControl(lang){

	this.lang = lang;
}

SearchControl.prototype = new GControl();


SearchControl.prototype.initialize = function(map) {
	
  this.map = map;
  
      
	//needed because in the context of event handling 'this' has a different meaning	
  var search_control = this;

  var container = document.createElement("div");
  container.className = 'geo-viz-search-control';
  
   
  var search_container = document.createElement('div');
  search_container.className = 'search-container';
  
  container.appendChild(search_container);
   
  
   var search_button = document.createElement("button");
   
   
   
   if(search_control.lang == 'cs')
   	search_button.className = 'search-button-cs';
   
   else if(search_control.lang == 'en')
   	search_button.className = 'search-button-en';
   
   else
   	search_button.className = 'search-button';
   
  
  var search_box_background = document.createElement('div');
  search_box_background.className = 'search-box-background';
  
  var search_box = document.createElement("input");
  search_box.className = 'search-box';
 
  jQuery(search_box).keydown(function(event){
  	
	//if enter was pressed start the search
		if(event.keyCode == '13'){
			
			
			if(search_box.value != "")
			search_control.searchLocation( search_box.value + ' , Austria' );
		}
  })
  
  
  search_box_background.appendChild(search_box);
  
  
   
  
  var clear_button = document.createElement('button');
  
  this.clear_button = clear_button;
  
    
  
  clear_button.appendChild(document.createTextNode('x'));
  
  jQuery(clear_button).addClass('clear-button');
  jQuery(clear_button).css('visibility', 'hidden');
  
  var handler = this.map_handler;
  
   var disambiguation_box = document.createElement('div');
   disambiguation_box.className = 'disambiguation-box';
  
  this.disambiguation_box = disambiguation_box;
  
    
  (jQuery(disambiguation_box) ).hide();
   
 
  
  
  jQuery(clear_button).click(function(){
  	
	handler.clearSearchResult();
	jQuery(this).css('visibility', 'hidden');
	
  })
  
  

  search_container.appendChild(disambiguation_box);
  search_container.appendChild(search_box_background);
  search_container.appendChild(search_button);
  search_container.appendChild(clear_button);
 
 
  
  

  
  GEvent.addDomListener(search_button, "click", function() {
    
	if(search_box.value != "")
		search_control.searchLocation( search_box.value + ' , Austria' );
	
	
  });
  
 
 
  map.getContainer().appendChild(container);

  return container;
}

// By default, the control will appear in the top left corner of the

SearchControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(0, 51));
}


/**
 * performs a location search given a Location string.
 * If a location is 
 * @param {Object} location_string
 */

SearchControl.prototype.searchLocation = function (location_string){
	
	var geocoder = new GClientGeocoder();
			
	if(!location_string)
		return;
	
	var handler = this.map_handler;
	var search_control = this;
	
	geocoder.getLocations(location_string, function(response){
		
		
		if(response.Status.code != 200){
			
			alert('leider kein Suchergebnis');
			return;
			
		}
								
		
		//more than one result found... disambiguation is needed
		if(response.Placemark.length > 1){
			
			
			(jQuery(search_control.disambiguation_box) ).html('');
			(jQuery(search_control.disambiguation_box) ).show();
			
			var clear_button = document.createElement('button'); 
  			clear_button.appendChild(document.createTextNode('x'));
			clear_button.className = 'clear-button';
			
			
			jQuery(clear_button).click(function(){
				(jQuery(search_control.disambiguation_box) ).hide();
			})
				
			search_control.disambiguation_box.appendChild(clear_button);
			
			jQuery.each(response.Placemark, function(){
				
				link = document.createElement('a');
				link.href="#";
				link.appendChild(document.createTextNode(this.address));
				
				search_control.disambiguation_box.appendChild(link);
				
				var placemark = this;
				
				jQuery(link).click(function(){
					
					handler.addSearchResult(placemark);
					
					(jQuery(search_control.disambiguation_box) ).hide();
					(jQuery(search_control.clear_button) ).css('visibility', 'visible');					
					return false;
				});
				
				
			});
			
						
			
		}
		
		//only one location found. display it on the map
		else if(response.Placemark.length == 1){
			
			
			handler.addSearchResult(response.Placemark[0]);
			(jQuery(search_control.clear_button) ).css('visibility', 'visible');
				
				
		}
		
	});
	
}

/**
 * 
 * @param {Object} map_obj
 */

SearchControl.prototype.setMapObject = function (map_obj){
	
	SearchControl.prototype._map_obj = map_obj;
	
}



	
/**
 * unloadMap() cleans up, when the map is no longer needed.
 * This function simply calls the "GUnload()" method from the Google Maps API
 */	
function unloadMap(){
	
	GUnload();
	
}



/**
 * builds the post url given a post's title
 * @param {Object} posttitle
 */

function buildPostUrl(post_title){
	
	return document.domain + "/" + ( post_title.toLowerCase() ).replace(/ /g, '-') + '?ajax=1';	
	
}





