/////// COPYRIGHT 2009 by icomedias gmbh, All rights reserved ////////

MapView=function(config){
//if (config.canvasId) this.canvasId=config.canvasId;
if (config){
	for (var p in config){
		this[p]=config[p];
	}
}
};

MapView.prototype={
defaultMarkerWidth:24,
defaultMarkerHeight:34,
defaultLat:47,
defaultLng:15,
defaultZoom:5,
routePlanning:true,
customControls:[],
canvasId:'map_canvas',
datalistId:'datalist',
data:null,
map:null,
markers:[],
standardMarker:'Marker-rot.png',
standardMarkerNumber:'Marker-rot.png',
standardMarkerHighlight:'Marker-gruen.png',
standardMarkerNumberHighlight:'Marker-gruen.png',
overlays:null,
highlightMarker:null,
markerMapping:{},
directions:null,
selected_marker_glatlng:null,
geocoder:null,
mapTypeControl:'NORMAL', // MENU | NORMAL | null,
center:null, // {lat:NUMBER,lng:NUMBER} , if null: center will be calculated
zoom:null, // if null zoom will be calculated
bubbleMaxWidth:'300',
bubbleMaxHeight:'300',
showBubble:true,
listeners:{}, // marker_click | map_mouseenter | map_mouseout | map_mousemove
numberMarker:false,
path:'/georss/geo/',
cluster:true,
retry:false,
showShadow:true,
imgCache:{}, // for fast finding width and height

getCoordinates:function(data){
	if (!data) return;

    var coordinates = {
        lat_center: 0.0,
        lng_center: 0.0,
        lat_min: 90,
        lat_max: -90,
        lng_min: 180.0,
        lng_max: -180.0
    }
    
    for (var i = 0; i < data.length; i++) {
				
		var lat=parseFloat(data[i].lat);
		var lng=parseFloat(data[i].lng);
		
        if (lat < coordinates.lat_min) 
            coordinates.lat_min = lat;
        if (lng < coordinates.lng_min) 
            coordinates.lng_min = lng;
        if (lat > coordinates.lat_max) 
            coordinates.lat_max = lat;
        if (lng > coordinates.lng_max) 
            coordinates.lng_max = lng;

    }
    coordinates.lat_center = (coordinates.lat_max - coordinates.lat_min) / 2 + coordinates.lat_min;
    coordinates.lng_center = (coordinates.lng_max - coordinates.lng_min) / 2 + coordinates.lng_min;
    
    return coordinates;
},

mapMarkers:function(){
    // markerMapping matches the marker ids with the indexes of the marker array for faster searching
    for (var i = 0; i < this.markers.length; i++) 
        this.markerMapping[this.markers[i].id] = '' + i + '';
},

getMarker:function(id){
    // markerMapping maps the marker ids with the indexes of the marker array for faster searching
    if (!this.markerMapping[id]) 
        this.mapMarkers();
    return this.markers[this.markerMapping[id]];
},

createMarkers:function(data){

    for (var i = 0; i < data.length; i++) {
        var marker = this.createMarker(data[i]);
        this.markers.push(marker);
    }
    return this.markers;
},

resetHighlights:function(){
    var entrydivs = jQuery("div#"+this.datalistId).find('div');
    entrydivs.removeClass('item_highlight');
},

removeHighlight:function(){
    jQuery('div#entry' + this.highlightMarker.id).removeClass('item_highlight');
    this.map.removeOverlay(this.highlightMarker);
},

highlightFromMarker:function(id){
    this.highlight(id);
},

highlightFromList:function(id, click){
    if (!this.map) return;
	
	this.highlight(id);
	
	if (!this.getMarker(id)) return; // marker not found
	
    this.map.panTo(this.highlightMarker.getLatLng());
    this.map.panTo(this.highlightMarker.getLatLng());
	var marker = this.getMarker(id);
    if (click && marker.description) {	
		
		var description=marker.description;
		if (this.routePlanning) description+=this.getRouteHtmlCode(marker);
	
        selected_marker_glatlng = marker.getLatLng(); //new GLatLng(marker.lat, marker.lng); 
        this.highlightMarker.openInfoWindowHtml("<b>" + marker.title + "</b><br/><br/>" + description, {
            maxWidth: this.bubbleMaxWidth,
			maxHeight: this.bubbleMaxHeight,
			autoScroll:true
        });
    }
},

highlight:function(id){
	
	if (!this.map) return;
    // removing old highlight
    if (this.highlightMarker) 
        this.removeHighlight();
    
    jQuery('div#entry' + id).addClass('item_highlight');
    
    var marker = this.getMarker(id);
	if (!marker) return;
    this.highlightMarker = this.createHighlightMarker(marker);
    this.map.addOverlay(this.highlightMarker, {
        zIndexProcess: function(){
            return 1000;
        }
    });
},

initDataList:function(){
    for (var i = 0; i < this.data.length; i++) {
        var output = '<div onClick="highlightFromList(' + this.data[i].id + ',true)" onMouseover="highlightFromList(' + this.data[i].id + ', false)" id="entry' + this.data[i].id + '" class="item">'
        output += this.data[i].num + " "; 
        output += this.data[i].title;
        output += "</div>";
        jQuery("div#"+this.datalistId).append(output);
        //        console.debug(data[i]);
        //        html = "<b>" + data[i].title + "</b><br/><br/>" + data[i].description;
        //        $("div#entry" +  data[i].id).bind('click', function (e) { highlightMarker.openInfoWindowHtml(html) });
    }
},

initDataFromUrl:function(url){
	var scope=this;
    $.getJSON(url, function(response){
        data = response.items;
        if (!data && !this.retry) { // one retry to init cache on server
        	this.retry=true;
        	$.get(document.location.href, function(response){
				$.getJSON(url, function(response){
					data=response.items;
					if (data){
						if (response.overlays) overlays=response.overlays;
						if (data.length > 0) {
							scope.data=data;
							scope.initGMap();
							scope.initDataList();
							}
					}
				});       		
        	});
        }
		if (!data) return;
        if (response.overlays) overlays=response.overlays;
        if (data.length > 0) {
			scope.data=data;
            scope.initGMap();
            scope.initDataList();
        }
    });
},

initList:function(url){
    setData(url);
},

initData:function(data){
    if (data.overlays) this.overlays=data.overlays;
	this.data = data.items;	
    this.initGMap();
    if (this.data) this.initDataList();
},

addItems:function(items){
	
	for (var i=0; i<items.length; i++){
		//console.log(items[i]);
		for (var u=0; i<this.data.length; u++){
			//console.log(data.id);
		}
	}
},

getImgSize:function(imgPath){

	var img=null;
	var width=null;
	var height=null;
	var size=null;
	if (this.imgCache[imgPath]) {
		img=this.imgCache[imgPath];
		width=img.width;		
		height=img.height;
		size=new GSize(width,height);
	}
	else {
		img=new Image();
		img.src=imgPath;
		width=img.width;
		height=img.height;
		size=new GSize(width,height);
		this.imgCache[imgPath]=img;
	}
	return size;
},

createHighlightMarker:function(marker){
    
	if (!marker) return;
	var data=marker.data;
	
	var latlng = marker.getLatLng();
    var icon = new GIcon(G_DEFAULT_ICON);
	if (!this.showShadow) icon.shadow=this.path+"marker/transparent.png";
		
    var text = marker.num;

	var iconImg=this.standardMarkerHighlight;
	
	if (this.numberMarker) iconImg=this.standardMarkerNumberHighlight;
	
	if (data.icon) iconImg=data.icon;	
	if (data.iconOver) iconImg=data.iconOver; 
	
	if (this.numberMarker && marker.num!=false){
		icon.image = this.path+"marker.php?text=" + text + "&image="+iconImg;
	}
	else{
		icon.image = this.path+"marker/"+iconImg;
	}

	var size=this.getImgSize(icon.image);
	if (size.width==0 && size.height==0) size=new GSize(this.defaultMarkerWidth,this.defaultMarkerHeight);

	//console.log(icon.image);
	
	icon.iconSize=size;
	icon.shadowSize=new GSize(size.width*2,size.height);
	icon.iconAnchor=new GPoint(size.width/2,size.height);
	
	
	highlightMarker = new google.maps.Marker(latlng, {
        icon: icon,
        title: marker.title
    });
    highlightMarker.id = '' + marker.id + '';
    highlightMarker.num = marker.num;
	highlightMarker.link=marker.link;
    
	if (marker.description) highlightMarker.description=marker.description;
		
	
	var scope=this;
	
	if (this.listeners.marker_click){
		google.maps.Event.addListener(highlightMarker, "click", function(){scope.listeners.marker_click(highlightMarker)});
	}

	if (highlightMarker.description && this.showBubble){
		
		var description=highlightMarker.description;
		
		if (this.routePlanning) description+=this.getRouteHtmlCode(highlightMarker);
		
		google.maps.Event.addListener(highlightMarker, "click", function(){
        selected_marker_glatlng = latlng; 
        highlightMarker.openInfoWindowHtml('<b>' + marker.title + "</b><br/><br/>" + description+'', {
            maxWidth: scope.bubbleMaxWidth,
			maxHeight: scope.bubbleMaxHeight,
			autoScroll:true
        });
    });
	}
    
    return highlightMarker;
},

createMarker:function(data){
    var latlng = new google.maps.LatLng(data.lat, data.lng);
    var icon = new GIcon(G_DEFAULT_ICON);
	if (!this.showShadow) icon.shadow=this.path+"marker/transparent.png";
	
    var text = data.num;
	
	var iconImg=this.standardMarker;
	
	if (this.numberMarker) iconImg=this.standardMarkerNumber;
	
	if (data.icon) iconImg=data.icon; 
	
	if (this.numberMarker  && data.num!=false){
		icon.image = this.path+"marker.php?text=" + text + "&image="+iconImg;
	}
	else{
		icon.image = this.path+"marker/"+iconImg;
	}

	var size=this.getImgSize(icon.image);
	icon.iconSize=size;

	icon.shadowSize=new GSize(size.width*2,size.height);
	icon.iconAnchor=new GPoint(size.width/2,size.height);
	
	var config={
        icon: icon,
        title: data.title
    };
	if (data.hidden && data.hidden==true) config.hide=true;	
	
    var marker = new google.maps.Marker(latlng, config);
	
	
    marker.title = data.title;
    marker.id = data.id;
    marker.num = data.num;
	marker.link=data.link;
	
	marker.data=data;

	scope=this;
	
	if (data.description && this.showBubble){
	
	marker.description = data.description;
	
	var description=data.description;
	if (this.routePlanning) description+=this.getRouteHtmlCode(marker);
	
	
    google.maps.Event.addListener(marker, "click", function(){
        selected_marker_glatlng = latlng; 
        marker.openInfoWindowHtml("<b>" + data.title + "</b><br/><br/>" + description, {
            maxWidth: scope.bubbleMaxWidth,
			maxHeight: scope.bubbleMaxHeight,
			autoScroll:true
        });
    });	

	}
	
	var scope=this;
	google.maps.Event.addListener(marker, "mouseover", function(marker){scope.highlightFromMarker(this.id);});
	
	
	return marker;
},

getRouteHtmlCode:function(marker){
var code = '<br/><br/>'
		code += '<div id="direction_get_link_'+marker.id+'"><a href="#" onclick="jQuery(\'#direction_get_link_'+marker.id+'\').hide(); jQuery(\'#direction_saddr_'+marker.id+'\').show();">Route berechnen</a></div>';

		code += '<div id="direction_saddr_'+marker.id+'" style="display: none;">';
		code += 'Route berechnen: <b>Hierher</b> - <a href="#" onclick="jQuery(\'#direction_saddr_'+marker.id+'\').hide(); jQuery(\'#direction_daddr_'+marker.id+'\').show();">Von hier</a>';
		code += '<br/>Startadresse: <br/><input onkeyup="if (event.keyCode==13) mapView.getDirectionAddress(jQuery(\'#saddr_'+marker.id+'\').val(), false);" id="saddr_'+marker.id+'" name="saddr" type="text" style="width: 13.45em" />';
		code += '<input type="button" value="Los!" onclick="mapView.getDirectionAddress(jQuery(\'#saddr_'+marker.id+'\').val(), false)" /><br/>';
		//code += '<a href="#" onclick="jQuery(\'#direction_saddr_'+marker.id+'\').hide(); jQuery(\'#direction_get_link_'+marker.id+'\').show();">Zurück</a>';
		code += '</div>';

		code += '<div id="direction_daddr_'+marker.id+'" style="display: none;">';
		code += 'Route berechnen: <a href="#" onclick="jQuery(\'#direction_daddr_'+marker.id+'\').hide(); jQuery(\'#direction_saddr_'+marker.id+'\').show();">Hierher</a> - <b>Von hier</b>';
		code += '<br/>Zieladresse: <br/><input onkeyup="if (event.keyCode==13) mapView.getDirectionAddress(jQuery(\'#daddr_'+marker.id+'\').val(), true);"  id="daddr_'+marker.id+'" name="daddr" type="text" style="width: 13.45em" />';
		code += '<input type="button" value="Los!" onclick="mapView.getDirectionAddress(jQuery(\'#daddr_'+marker.id+'\').val(), true)" /><br/>';
		//code += '<a href="#" onclick="jQuery(\'#direction_daddr_'+marker.id+'\').hide(); jQuery(\'#direction_get_link_'+marker.id+'\').show();">Zurück</a>';
		code += '</div>';
		
		code +='<br/><br/><br/>';
		return code;
},
getClippingDistance:function(coordinates){
    var lat_distance = coordinates.lat_max - coordinates.lat_min;
    var lng_distance = coordinates.lng_max - coordinates.lng_min;
    var distance = Math.sqrt(lat_distance * lat_distance + lng_distance * lng_distance);
    return distance;
},

getMapCanvasSize:function(){
    return {width:jQuery("div#"+this.canvasId).css("width"),
            height:jQuery("div#"+this.canvasId).css("height")};
},

getZoomLevel:function(distance){
    //var mapCanvasSize=getMapCanvasSize();
    //var factor=parseInt(mapCanvasSize.width);
    //if (mapCanvasSize.width>mapCanvasSize.height) factor=parseInt(mapCanvasSize.height);
	var add=1;
    var factor=1;
    if (distance < 0.005*factor)
        return 17+add;
    if (distance < 0.007*factor)
        return 16+add;
    if (distance < 0.01*factor)
        return 15+add;
    if (distance < 0.03*factor)
        return 14+add;
    if (distance < 0.06*factor)
        return 13+add;
    if (distance < 0.1*factor)
        return 12+add;
    if (distance < 0.15*factor)
        return 11+add;
    if (distance < 0.3*factor)
        return 10+add;
    if (distance < 0.8*factor)
        return 9+add;
    if (distance < 2*factor)
        return 8+add;
    if (distance < 2.4*factor)
        return 7+add;
    if (distance < 4.7*factor)
        return 6+add;
    if (distance < 9*factor)
        return 5+add;
    if (distance < 17*factor)
        return 4+add;   
    if (distance < 30*factor)
        return 3+add;

        return 2+add;
},

zoomIn:function(){
    map.zoomIn();
    contextmenu.style.visibility = "hidden";
},

zoomOut:function(){
    map.zoomOut();
    contextmenu.style.visibility = "hidden";
},

centreMapHere:function(){
    var point = this.map.fromContainerPixelToLatLng(clickedPixel)
    this.map.setCenter(point);
    contextmenu.style.visibility = "hidden";
},

getDirectionAddress:function(address, swap_direction) {
	scope=this;
	this.geocoder.getLatLng(address, function(point) {

		if (!point) {
			alert("Adresse konnte nicht gefunden werden!");
			return;
		}
        scope.directions.clear();
		if (swap_direction) {
			scope.directions.loadFromWaypoints(new Array(selected_marker_glatlng, point));
            google.maps.Event.addListener(scope.directions, 'addoverlay', function() {
                scope.directions.getMarker(0).hide();
                scope.directions.getMarker(1).show();
            });
		} else {
            scope.directions.loadFromWaypoints(new Array(point, selected_marker_glatlng));
            google.maps.Event.addListener(scope.directions, 'addoverlay', function() {
                scope.directions.getMarker(0).show();
                scope.directions.getMarker(1).hide();
            });
		}
		
		scope.highlightMarker.closeInfoWindow();
	});
},

getDirection:function(swap_direction) {
	
	if (!this.selected_marker_glatlng) {
		alert('Bitte wählen Sie zuerst Objekt aus.');
		return;
	}
	
    selected_point = map.fromContainerPixelToLatLng(clickedPixel);
	this.directions.clear();

	if (swap_direction) {
		this.directions.loadFromWaypoints(new Array(selected_marker_glatlng, selected_point));
        google.maps.Event.addListener(this.directions, 'addoverlay', function() {
            this.directions.getMarker(0).hide();
            this.directions.getMarker(1).show();
        });
	} else {
        this.directions.loadFromWaypoints(new Array(selected_point, selected_marker_glatlng));
        google.maps.Event.addListener(this.directions, 'addoverlay', function() {
			this.directions.getMarker(0).show();
            this.directions.getMarker(1).hide();
        });
	}

    contextmenu.style.visibility = "hidden";
},

highlight_context:function(obj) {
    var entrydivs = jQuery("div#contextmenu").find('div');
    entrydivs.removeClass('item_highlight');
	jQuery(obj).addClass('item_highlight');
},

createContextMenu:function(map) {
return;
      contextmenu = document.createElement("div");
      contextmenu.id = 'contextmenu';
	  contextmenu.style.visibility="hidden";
      contextmenu.style.background="#ffffff";
      contextmenu.style.border="1px solid #8888FF";
		mapscope=this;
      contextmenu.innerHTML = '<!--<div class="item" onmouseover="mapscope.highlight_context(this)" onclick="mapscope.getDirection(false)"> Route von hier </div>'
        + '<div class="item" onmouseover="mapscope.highlight_context(this)" onclick="mapscope.getDirection(true)"> Route hierher </div>-->'
        + '<div class="item" onmouseover="mapscope.highlight_context(this)" onclick="mapscope.zoomOut()"> Verkleinern  </div></a>'
        + '<div class="item" onmouseover="mapscope.highlight_context(this)" onclick="mapscope.zoomIn()"> Vergrößern </div></a>'
        + '<div class="item" onmouseover="mapscope.highlight_context(this)" onclick="mapscope.centreMapHere()"> Karter hier zentrieren  </div></a>';

      map.getContainer().appendChild(contextmenu);
      GEvent.addListener(map, "singlerightclick", function(pixel, tile) 
      {
          clickedPixel = pixel;
          var x=pixel.x;
          var y=pixel.y;
          if (x > map.getSize().width - 120) { 
            x = map.getSize().width - 120 
          }
          if (y > map.getSize().height - 100) { 
            y = map.getSize().height - 100 
          }
		  
          var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(x,y));  
          pos.apply(contextmenu);
          contextmenu.style.visibility = "visible";
     });
     GEvent.addListener(map, "click", function() 
     {
          contextmenu.style.visibility="hidden";
     });
 },
 
zoomIn:function(){
     this.map.zoomIn();
     contextmenu.style.visibility = "hidden";
 },
 
zoomOut:function(){
     this.map.zoomOut();
     contextmenu.style.visibility = "hidden";
 },

initGMap:function(){
    
	if (!GBrowserIsCompatible()) {
        return;
    }	
	
	// default
	var lat=this.defaultLat;
	var lng=this.defaultLng;
	var zoom=this.defaultZoom;
	
	if (this.data && this.data.length!=0){
			// list of coordinates of all items
			var coordinates = this.getCoordinates(this.data);
	
			
			if (!this.center)
			{	
				// calc center of all items	
				this.center={lat:coordinates.lat_center, lng:coordinates.lng_center};
			}

			if (!this.zoom) {
				// calc zoom
				var clippingDistance = this.getClippingDistance(coordinates);
				this.zoom = this.getZoomLevel(clippingDistance);
			}
			lat=this.center.lat;
			lng=this.center.lng;
			zoom=this.zoom;
	}
	

		
    this.map = new google.maps.Map2(document.getElementById(this.canvasId));

    this.map.setCenter(new GLatLng(lat, lng), zoom);
	
    this.map.addControl(new GLargeMapControl());
	
	
	var scope=this;
	if (this.listeners.map_mouseover){
		google.maps.Event.addListener(this.map, "mouseover", function(){
			scope.listeners.map_mouseover();
		});
	}
	
	if (this.listeners.map_mouseout){
		google.maps.Event.addListener(this.map, "mouseout", function(){
			scope.listeners.map_mouseout();
		});
	}
	
	if (this.listeners.map_mousemove){
		google.maps.Event.addListener(this.map, "mousemove", function(){
			scope.listeners.map_mousemove();
		});
	}
	
	if (this.listeners.map_drag){
		google.maps.Event.addListener(this.map, "drag", function(){
			scope.listeners.map_drag();
		});
	}
	
	
	if (this.mapTypeControl=="MENU") this.map.addControl(new GMenuMapTypeControl());
	else if (this.mapTypeControl=="NORMAL") this.map.addControl(new GMapTypeControl());
    
	
	// custom controls
	for (var i=0; i<this.customControls.length; i++){
		this.map.addControl(this.customControls[i]);
	}
	
    this.map.enableScrollWheelZoom();
	
	if (!this.data || this.data.length==0) return;
	
	
    this.geocoder = new GClientGeocoder();
    this.directions = new GDirections(this.map);

    var markers = this.createMarkers(this.data);
    if (this.cluster) var markerClusterer = new MarkerClusterer(this.map,markers);
    else {
    	for (var i=0; i<markers.length; i++) this.map.addOverlay(markers[i]);
    	}
    this.createContextMenu(this.map);

    if (this.overlays){
        var circles=[];
        for (var i=0; i<this.overlays.length; i++){
            if (this.overlays[i].type="circle") circles.push(this.overlays[i]);
        }

        if (circles.length>0) this.initCircles(this.map, circles);
    }
},

getDestLatLng:function(latLng, bearing, distance) {
 var EARTH_RADIUS = 6378.137;
 var lat1 = latLng.latRadians();
 var lng1 = latLng.lngRadians();
 var brng = bearing*Math.PI/180;
 var dDivR = distance/EARTH_RADIUS;
 var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dDivR) + Math.cos(lat1)*Math.sin(dDivR)*Math.cos(brng) );
 var lng2 = lng1 + Math.atan2(Math.sin(brng)*Math.sin(dDivR)*Math.cos(lat1), Math.cos(dDivR)-Math.sin(lat1)*Math.sin(lat2));
 return new GLatLng(lat2/ Math.PI * 180, lng2/ Math.PI * 180);
},

getBoundaries:function(centrePt, radius) { 
 var hypotenuse = Math.sqrt(2 * radius * radius);
 var sw = getDestLatLng(centrePt, 225, hypotenuse);
 var ne = getDestLatLng(centrePt, 45, hypotenuse);
 return new GLatLngBounds(sw, ne);
},

drawCircle:function(map, centrePt, rangeValue) {
 var boundaries = getBoundaries(centrePt, rangeValue);
 //var circle = new GGroundOverlay("geo/marker/circle"+rangeValue+".png", boundaries);
 var img="geo/marker/circle"+rangeValue*1000+".png";
 //console.log(img);
 var circle = EInsert.groundOverlay(img,boundaries,-1);
 map.addOverlay(circle);
},

initCircles:function(map, circles){
    for (var i=0; i<circles.length; i++){
        var latLng=new GLatLng(circles[i].lat,circles[i].lng);
        var distance=25;

        if (circles[i].distance<=0.5) distance=0.5;
        else if (circles[i].distance<=1) distance=1;
        else if (circles[i].distance<=2) distance=2;
        else if (circles[i].distance<=10) distance=10;
        else if (circles[i].distance<=25) distance=25;

        drawCircle(map, latLng, distance);
        }
},
showItems:function(ids){
	if (!ids) return;
	for (var u=0; u<this.markers.length; u++){
		var marker=this.getMarker
		for (var i=0; i<ids.length; i++){
			if (this.markers[u].id==ids[i]) this.markers[u].show();
		}
	}	
},
hideItems:function(ids){
	if (!ids) return;
		for (var i=0; i<ids.length; i++){
			var marker=this.getMarker(ids[i]);
			if (marker) marker.hide();
			if (this.highlightMarker && this.highlightMarker.id==ids[i]) this.highlightMarker.hide();
		}	
}
}

