/**
 * GoogleMap wrapper class
 */
GoogleMap=Class.create({
  smallMapControl: true,
  overviewMapControl: false,
  mapTypeControl: null,
  mapType: 		G_PHYSICAL_MAP,   //G_PHYSICAL_MAP, G_NORMAL_MAP
  zoom: 		null,
  polylines:	null,
  gpoints:		null, 		//polyline
  glevels:		null,
  infoHtmlTemplate: "<b>@{id} - @{name}</b><br/>@{address}", //html info template
  icon:			null, 		// marker icon
  bigIcon:		null, 		// marker big icon
  markerIcon:	null, 		// marker icon image
  startMarkerIcon:null,		// start marker icon image
  endMarkerIcon:null,		// end marker icon image
  points:		[],  		// marker geo points
  cmarkers:		[],
  hmarkers:		[],  
  /* 
   * constructor 
   */
  constructor: function GoogleMap(div,object){
    this.map=new GMap2(typeof(div)=="string"?document.getElementById(div):div);
    //assegno le proprietà passate al construttore con l'oggetto object
    //nb alcune proprietà potrebbero non essere ancora disponibili sull'oggetto GMap2...(es mapType)
    if(object!=null){
     for(var p in this)
      if(object[p]!=null)
        this[p]=object[p];
    }
    if(this.icon==null)
      this.icon=new GIcon({
 		    shadow : "http://labs.google.com/ridefinder/images/mm_20_shadow.png",
 		    iconSize : new GSize(8, 8),
 		    shadowSize : new GSize(12, 12),
 		    iconAnchor : new GPoint(4, 4),
 		    infoWindowAnchor : new GPoint(4, 4)
      });         
    this.icon.image=(this.markerIcon!=null?this.markerIcon:this.icon.image);  
    if(this.bigIcon==null){   
      this.bigIcon = new GIcon(this.icon);
      this.bigIcon.iconSize = new GSize(12, 12);
    }
    
    if (GBrowserIsCompatible()) {
      if(this.smallMapControl)
      	this.map.addControl(new GSmallMapControl());
      
      
      this.map.removeMapType(G_HYBRID_MAP);
      this.map.addMapType(G_PHYSICAL_MAP);
      
      if(!this.mapTypeControl){					//se non passato, istanzio il classico GmapTypeControl
    	this.map.addControl(new GMapTypeControl());
    	}
      else{
    	this.map.addControl(this.mapTypeControl);//se passato da chi istanzia, uso quello (es: ExtMapTypeControl)
      }
      
      this.map.setMapType(object['mapType']);//setta il tipo mappa passato da chi istanzia, o il default NORMAL
      
	  if(this.overviewMapControl){
		this.map.addControl(new GOverviewMapControl());
		/*ovcontrol=new GOverviewMapControl();
		this.map.addControl(ovcontrol);
		ovcontrol.hide(true);*/
		}
	  this.map.enableDoubleClickZoom();
      //settaggio centro iniziale... 
	  this.map.setCenter(new GLatLng(45.07393,7.67220),13);
	  this.map.setZoom((this.zoom!=null?this.zoom:13));
	  
	if (this.polylines!=null){
		    for(var i=0; i<this.polylines.length;i++){
		      var polyline = new Polyline(this.polylines[i]);
		      this.map.addOverlay(polyline._source);
		    }
			if(this.gpoints!=null){
			       var polyline = new GPolyline.fromEncoded({
				      color:"#FF0000", weight:10, opacity:0.5, zoomFactor:2, numLevels:18,
				      points:this.gpoints, levels:this.glevels		
			       });		    
			       var bounds = polyline.getBounds();
			       this.map.setZoom(this.map.getBoundsZoomLevel(bounds));
			       this.map.setCenter(bounds.getCenter(),this.map.getBoundsZoomLevel(bounds),this.mapType);		    
			      //this.glevels=this.gpoints=null;
			      }
	}else if(this.gpoints!=null){
	      var polyline = new GPolyline.fromEncoded({
		      color:"#FF0000", weight:10, opacity:0.5, zoomFactor:2, numLevels:18,
		      points:this.gpoints, levels:this.glevels		
	      });
        this.map.addOverlay(polyline);
	      var bounds = polyline.getBounds();
	      this.map.setZoom(this.map.getBoundsZoomLevel(bounds));
	      this.map.setCenter(bounds.getCenter(),this.map.getBoundsZoomLevel(bounds),this.mapType);
	    }else if(this.points!=null && this.points.length>=1){
	      this.map.setCenter(new GLatLng(this.points[0].wgsLat, this.points[0].wgsLng), 13,this.mapType);
	      this.map.setZoom((this.zoom!=null?this.zoom:15));
	    }
    }      
  },
  addControl: function(ctl){
	  this.map.addControl(ctl);
  },
  /** load & design markers on the map */
  load: function() {
	  var flag_icon = new GIcon();
	  flag_icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
	  flag_icon.iconSize = new GSize(26, 26);
	  flag_icon.shadowSize = new GSize(12, 12);
	  flag_icon.iconAnchor = new GPoint(13,26);
	  flag_icon.infoWindowAnchor = new GPoint(4, 4);
	  var points=this.points;
	  var size=(points.length>0?(points[points.length-1]==null?points.length-1:points.length):0)
	  for(var i=0;i<points.length;i++){
	   if(points[i]!=null){
	     if(i==0 && this.startMarkerIcon!=null){
	       var flag_icon_start = new GIcon(flag_icon, this.startMarkerIcon);
	       this.map.addOverlay(new GMarker(new GLatLng(points[i].wgsLat ,points[i].wgsLng),
	                           {icon:flag_icon_start, title:'partenza'}));
	     }else if (i==(size-1) && this.endMarkerIcon!=null){
	       var flag_icon_end = new GIcon(flag_icon, this.endMarkerIcon);
	       this.map.addOverlay(new GMarker(new GLatLng(points[i].wgsLat ,points[i].wgsLng),
	                           {icon:flag_icon_end, title:'arrivo'}));
	     }
	     this.map.addOverlay(this.createMarker(new GLatLng(points[i].wgsLat ,points[i].wgsLng),points[i]));
	   }
	  }
     
  },
  /**create map marker.
   */
  createMarker: function(point, object){
    var name=object.name;
	  var icon = this.icon;
	  if(object.icon!=null){
	    if(typeof(object.icon)=="string")
	      icon=new GeoIcon({image:object.icon,iconSize : new GSize(20, 16)});//width=20,height=16
		  else
	    	icon=object.icon;
	  }
    var marker = new GMarker(point,{icon:icon, title:name});
    marker.object=object;
    var self=this;
    GEvent.addListener(marker, "click", function() {
         var html=self.infoHtmlTemplate;
         var object=marker.object;
         if(object.infoHtmlTemplate!=null)
           html=object.infoHtmlTemplate;
         for(var p in object){
           var pattern="@\\{"+p+"\\}";
           var regexp=new RegExp(pattern,"g")
           html=html.replace(regexp,object[p]);
         }
         marker.openInfoWindowHtml(html);
       }
     );
    // save two markers for each point, one with each of the possible icons
    this.cmarkers[object.id] = marker;
    var hmarker=new GMarker(point,{icon:icon, title:name}/*this.bigIcon*/);
    this.hmarkers[object.id] = hmarker;
    GEvent.addListener(hmarker, "click", function() {
         var html=self.infoHtmlTemplate;
         var object=hmarker.object;
         if(object.infoHtmlTemplate!=null)
           html=object.infoHtmlTemplate;
         for(var p in object){
           var pattern="@\\{"+p+"\\}";
           var regexp=new RegExp(pattern,"g")
           html=html.replace(regexp,object[p]);
         }
         hmarker.openInfoWindowHtml(html);
       }
     );    
    this.hmarkers[object.id].object=object;
    return marker;
  },
  /** doclick */
  doclick:function(id, name) {
    this.mouseover(id);
    var object=this.cmarkers[id].object;
    var html=this.infoHtmlTemplate;
    if(object.infoHtmlTemplate!=null)
      html=object.infoHtmlTemplate;
    for(var p in object){
      var pattern="@\\{"+p+"\\}";
      var regexp=new RegExp(pattern,"g")
      html=html.replace(regexp,object[p]);
    }    
    this.hmarkers[id].openInfoWindowHtml(html);
  },
  /** do mouseover */
  mouseover:function mymouseover(id) {
    this.map.removeOverlay(this.cmarkers[id]);
    this.map.addOverlay(this.hmarkers[id]);
  },
  /** do mouseout */
  mouseout:function mymouseout(id) {
    this.map.removeOverlay(this.hmarkers[id]);
    this.map.addOverlay(this.cmarkers[id]);
  },
  setZoom:function(zoomLevel){
    this.map.setZoom(zoomLevel);
  }
});
/**
 * Google polyline wrapper.
 */
Polyline=Class.create({
	color:"#FF0000", 
	weight:7, 
	opacity:0.8, 
	zoomFactor:2, 
	numLevels:18,
	points:null, 
	levels:null,
  /** constructor */
	constructor: function Polyline(object){
    for(var p in this)
      if(object[p]!=null)
        this[p]=object[p];
	  var polyline = new GPolyline.fromEncoded(this);    	  
	  this._source=polyline;
	},
	getBounds: function() {
	  return this._source.getBounds();
	}
});
/**
 * Google geo icon wrapper 
 */
 GeoIcon=Class.create({
	 superclass: GIcon,
	 //shadow : "http://labs.google.com/ridefinder/images/mm_20_shadow.png",
  	 //shadowSize : new GSize(12, 12),
 	 iconAnchor : new GPoint(4, 4), 	 
 	 infoWindowAnchor : new GPoint(4, 4),   
 	 //constructor
 	 constructor: function GeoIcon(object) {
	 	GeoIcon.superclass.apply(this,arguments);
   	 }
 });