function MobicsGeo(gmap,srvURL,imgURL) {
  this.MAP_UPDATE_INTERVAL = 500; //milliseconds before performing map updates when map state is changed

  this.map = gmap;
  this.serverURL = srvURL;
  this.imageURL = imgURL;
  this.callback = null;
  this.markerList = [];
  this.poiman = new POIManager(gmap,srvURL);
  this.pharmacies = new Pharmacies(gmap,srvURL,imgURL);
  this.routeentry = null;
  this.mapUpdateTimer = null;

  this.id = MobicsGeo.instanceIdx++;
  MobicsGeo.instance[this.id] = this;
  this.mapSnapshotZoom = this.map.getZoom();
  this.mapSnapshotBounds = this.map.getBounds();

  this.geocodeAddress = function(cback,division,area,streetName,streetNumber,postcode,opt) {    
      var params = {'division':division, 'area':area, 'streetname':streetName, 'streetnumber':streetNumber, 'postcode':postcode};
      RemoteAjax.call({
        'url': this.serverURL+'/geocodeAddress.jsp',
        'data': params,
        'success': function(data) {          
          cback(data,opt);
        }
      });
  }

  this.reverseGeocode = function(cback,pointX,pointY,poiId) {    
	    var params = {'pointX':pointX, 'pointY':pointY};
	    RemoteAjax.call({
	      'url': this.serverURL+'/reverseGeocode.jsp',
	      'data': params,
	      'success': function(data) {
	        cback(data,poiId);
	      }
	    });
	  }

  this._markers = {
    'markerblue': {'iconurl':this.imageURL+'/blue_Marker.png'},
    'markerbrown': {'iconurl':this.imageURL+'/brown_Marker.png'},
    'markerdarkgreen': {'iconurl':this.imageURL+'/darkgreen_Marker.png'},
    'markergreen': {'iconurl':this.imageURL+'/green_Marker.png'},
    'markerorange': {'iconurl':this.imageURL+'/orange_Marker.png'},
    'markerpaleblue': {'iconurl':this.imageURL+'/paleblue_Marker.png'},
    'markerpink': {'iconurl':this.imageURL+'/pink_Marker.png'},
    'markerpurple': {'iconurl':this.imageURL+'/purple_Marker.png'},
    'markerred': {'iconurl':this.imageURL+'/red_Marker.png'},
    'markeryellow': {'iconurl':this.imageURL+'/yellow_Marker.png'},
    'pharmacy': {'iconurl':this.imageURL+'/markers/Scaled_Pharmacy.png'},
    'routefrom': {'iconurl':this.imageURL+'/markers/Scaled_Start.png'},
    'routeto': {'iconurl':this.imageURL+'/markers/Scaled_Stop.png'},
    'Default':{'iconurl':this.imageURL+'/markers/Scaled_Default.png'}
  };

  this._markerIcons = {};

  this._getMarkerIcon = function(markertype) {
    var res = G_DEFAULT_ICON;
    var t = this._markers[markertype];
    if (t!==undefined) {
      res = this._markerIcons[markertype];
      if (res===undefined) {
        res = new GIcon();
        res.image = this._markers[markertype].iconurl;
        res.shadow = this.imageURL+'/shadow50.png';
        res.iconSize = new GSize(26, 40);
        res.shadowSize = new GSize(37, 34);
        res.iconAnchor = new GPoint(9, 34);
        res.infoWindowAnchor = new GPoint(9, 2);
        res.infoShadowAnchor = new GPoint(18, 25);
        this._markerIcons[markertype] = res;
      }
    }
    return res;
  }

  this.addMarker = function(markertype, lat, lng, text) {
    var icon = this._getMarkerIcon(markertype);
    var m = new GMarker(new GLatLng(lat,lng),
        {'icon':icon});
    this.map.addOverlay(m);
    this.markerList.push(m); 
    
   // m.bindInfoWindow(text);
    var id = this.markerList.length-1;
     m.bindInfoWindow(this.markerHtml(text,id));
    return id;
  }

  this.markerHtml = function(data,id){ 
    var st='<b>'+data.foundAs+'</b>,<br>'+data.zip+', '+data.municipality+'<br><br>';    
    st += '<a href="javascript:setRoutePointFrom(\''+data.pointY+'\',\''+data.pointX+'\')">';
    st += '<img src="'+svrUrl+'/images/start_hex.png" style="border:0px; margin-right:3px;" title="Διαδρομή από" alt="Διαδρομή από" /> &nbsp;<u>Διαδρομή Από</u></a> &nbsp;&nbsp;';
    st += '<a href="javascript:setRoutePointTo(\''+data.pointY+'\',\''+data.pointX+'\')">';
    st += '<img src="'+svrUrl+'/images/stop_hex.png" style="border:0px; margin-right:3px;" title="Διαδρομή έως" alt="Διαδρομή έως" />&nbsp;<u>Διαδρομή Προς</u></a>&nbsp;&nbsp;';
    st += '<a href="javascript:removeAddressMark('+id+')">';
    st += '<img src="'+svrUrl+'/images/delete_hex.png" style="border:0px; margin-right:3px;" title="ΔΙαγραφή" alt="Διαγραφή" />&nbsp;<u>Διαγραφή Σημείου</u></a>&nbsp;&nbsp;';
    return st;   
  }

  this.removeMarker = function(id) {    
    if (id>=this.markerList.length) return false;    
    var m = this.markerList[id];
    if (m==null) return false;
    this.map.removeOverlay(m);
    this.markerList[id] = null;
    return true;
  }

  this.getDisplayedLayers = function() {
    return this.poiman.getDisplayedLayersArray();
  }

  this.showLayers = function(layerids) {
    var b = this.map.getBounds();
    this.poiman.getPOIs(layerids,
            {'southwest':{'lat':b.getSouthWest().lat(), 'lng':b.getSouthWest().lng()},
             'northeast':{'lat':b.getNorthEast().lat(), 'lng':b.getNorthEast().lng()}});
  }

  this.removeLayers = function(layerids) {    
    this.poiman.removePOIsByLayer(layerids);
  }

  this.getLayers = function(cback) {
    RemoteAjax.call({
      'url': this.serverURL+'/poicategories.jsp',
      'success': function(data) {
        cback(data);
      }
    });
  }
    
  this.setLayerImage = function(layerid,img) {
    var m = new GIcon();
    m.shadow = this.imageURL+'/markers/shadow50.png';
    m.iconSize = new GSize(26, 40);
    m.shadowSize = new GSize(37, 34);
    m.iconAnchor = new GPoint(12, 39);
    m.infoWindowAnchor = new GPoint(13, 2);
    m.infoShadowAnchor = new GPoint(18, 35);
    m.image = this.imageURL+'/markers/Scaled_'+img+'.png';
    this.poiman.setLayerIcon(layerid, m);
  }

  this.mapUpdated = function() {
      if (this.mapUpdateTimer!=null) clearTimeout(this.mapUpdateTimer);
      this.mapUpdateTimer = setTimeout('MobicsGeo.instance['+this.id+'].mapUpdated1();',this.MAP_UPDATE_INTERVAL);
  }
  

  this.mapUpdated1 = function() {
    var n_mapSnapshotZoom = this.map.getZoom();
    var n_mapSnapshotBounds = this.map.getBounds();
    if ((n_mapSnapshotZoom==this.mapSnapshotZoom)&&
        (n_mapSnapshotBounds.getSouthWest().lng()==this.mapSnapshotBounds.getSouthWest().lng())&&
        (n_mapSnapshotBounds.getSouthWest().lat()==this.mapSnapshotBounds.getSouthWest().lat())&&
        (n_mapSnapshotBounds.getNorthEast().lng()==this.mapSnapshotBounds.getNorthEast().lng())&&
        (n_mapSnapshotBounds.getNorthEast().lat()==this.mapSnapshotBounds.getNorthEast().lat())) return;

    this.mapSnapshotZoom = n_mapSnapshotZoom;
    this.mapSnapshotBounds = n_mapSnapshotBounds;
    this.mapSnapshotTimer = null;
    this.poiman.mapUpdated();
    this.pharmacies.updatePharmacies();
  }

  this.setShowPharmacies = function(show,dur) {
    this.pharmacies.togglePharmaciesOnCall(show,dur);
  }

  this.setPharmacyIcon = function(img) {
    this.pharmacies.setIcon(this._getMarkerIcon(img));
  }
  
  this.route = function(pointfrom, pointto, infoelemid,opts) {
      if (this.routeentry) this.routeentry.remove();
      this.routeentry = new RoutingEntryNGI(this.map,this.serverURL,this.imageURL,
          this._getMarkerIcon('routefrom'),this._getMarkerIcon('routeto'),infoelemid,pointfrom,pointto,opts);
      this.routeentry.getNGIRoute();
  }
  
  
  GEvent.bind(this.map, 'move', this, this.mapUpdated);
  GEvent.bind(this.map, 'zoomend', this, this.mapUpdated);

}

MobicsGeo.instanceIdx = 0;
MobicsGeo.instance = {};
