wsgn.Map = {
  settings : {
    baseUrl: '',
    title : "Wir sind Golf Karte",    
    markerType: "flag",   
    targetContainer: "wsgnMap",    
    controls: ['GSmallMapControl'], //an array of GmapControls to be added http://code.google.com/apis/maps/documentation/reference.html#GControlImpl.GSmallMapControl 
    lat: null,
    lng: 0,
    zoom: 5,
    markCenter: false,
    hasControls: true,
    typeControl: true,    
    zoomControl: 'small',
    mapType: 'G_SATELLITE_MAP',
    clickable: true,
    draggable: false,        
    onClickFuncs : {
      'goToMarkerUrl': function(marker, point, params){
        var data = marker.data;
        if(data.url){
          document.location.href=data.url;
        }
      }
    },
    markers: []//an array of markers
  },
  
  filter: 'all',

  initialized: false,
  map : null,
  gCoder: null, 
  tooltip: null,

  //to prevent security wholes when passing func strings as init parameters, we limit the allowed strings to those funcitons availale in gmaps api 
  allowedControls: ['GSmallMapControl', 'GLargeMapControl', 'GSmallZoomControl', 'GScaleControl', 'GMapTypeControl', 'GHierarchicalMapTypeControl', 'GOverviewMapControl'],
  
  init : function(initObj){
    
    
    if(GBrowserIsCompatible()) {
      GUnload();
      
      //overwrite base settings with initObject
      if(typeof initObj.onClickFuncs != 'undefined'){
        wsgn.Map.settings.onClickFuncs = $.extend(wsgn.Map.settings.onClickFuncs, initObj.onClickFuncs);
        delete initObj.onClickFuncs;
      }
      wsgn.Map.settings = $.extend(wsgn.Map.settings, initObj);
      
      
      console.log(
        'init map with these settings:', 
        wsgn.Map.settings, 
        wsgn.Map.settings.markers.length
      );
      
      //first see, if markers or lat/lng is specified
      if(wsgn.Map.settings.markers.length === 0 && (wsgn.Map.settings.lat === null && wsgn.Map.settings.lng === null) ){
        alert('Weder Marker noch Koordinaten übergeben, konnte Map nicht laden');
      }

      //now set up the map
      try{
        wsgn.Map.map = new GMap2(document.getElementById(wsgn.Map.settings.targetContainer));
      }
      catch(e){
        console.error(e);
      }
      
      
      //setup map controls
      if(wsgn.Map.settings.controls.length > 0){
        this.addControls(wsgn.Map.settings.controls);
      }
      
       
      //markers have been specified (the preferred way to add markers)
      if(wsgn.Map.settings.markers.length > 0){
        this.createMarkers(wsgn.Map.settings.markers);
      }
      
      //center coordinates have been specified (e.g. if the map has no markers)
      else{
        wsgn.Map.map.setCenter(new GLatLng(wsgn.Map.lat, wsgn.Map.lng), wsgn.Map.zoom);                
        if(wsgn.Map.markCenter !== false){
          wsgn.Map.markLatLng(wsgn.Map.lat, wsgn.Map.lng);
        }
      }
      
      
      //create tooltip div
      wsgn.Map.tooltip = $('<div class="tooltip" style="visibility:hidden;" ></div>')[0];
      document.getElementById(wsgn.Map.settings.targetContainer).appendChild( wsgn.Map.tooltip);
      
      
      //register dom events
      this.registerEvents();
      
      this.initialized = true;
      wsgn.Map.map.setMapType(G_PHYSICAL_MAP);
      
      //set up on click listening
      if(wsgn.Map.clickable !== false){
        
        //loop across supplied click funcs
        $.each(wsgn.Map.settings.onClickFuncs, 
          function(func, params){
            GEvent.addListener(wsgn.Map.map, "click", 
              function(marker, point){
                if(!point){
                  if(marker){
                    point = marker.getPoint();
                  }
                  else{
                    point = new GLatLng();
                  }     
                }
                try{
                  console.log(func);
                  //wsgn.Map.apply(this, [marker, point, params]);
                  //func.apply(this, [marker, point, params]);
                  wsgn.Map.settings.onClickFuncs[func].apply("test", [marker, point, params]);
                }
                catch(e){
                  console.error('could not apply click func', e);
                }
                
                //tracking
                try{
                  wsgn.trackAjax('map/markerClicked');
                }
                catch(e){
                  console.warn('could track marker click');
                } 
              }
            );
          }
        );
        
      }       
    }
  },
  
  
  registerEvents: function(){
    $('.markerFilter').click(
      function(){
        var url = this.href;
        wsgn.Map.filter = this.rel;
        
        if(wsgn.Map.filter != 'all'){
          $('#showAllMarkers').show();
        }
        else{
          $('#showAllMarkers').hide();
        }
        console.log('filter is', wsgn.Map.filter);
        
        $.ajax({
          url: url,
          dataType: 'json',
          success: function(data){
            console.log('received', data);
            wsgn.Map.map.clearOverlays();
            if(data.markers.length > 0){
              wsgn.Map.createMarkers(data.markers);
            }
          },
          error: function(){
            alert('Leider ist ein Fehler aufgetretetn');
          }
        });
        return false;
      }
    );
  },
  
  /**
   * add controls to the map
   * @param {array} controls an array of control elements
   */
  addControls: function(controls){
    wsgn.Map.map.addControl(new GSmallMapControl());
    /*for(var i = 0; i < controls.length; i++){
      if(wsgn.Map.allowedControls.inArray(controls[i])){
        try{
          var func = eval(controls[i]);
          wsgn.Map.map.addControl(new func());
        }catch(e){
          console.warn('could not add control',e, controls[i]);
        }
      }
    }*/
  },
  
  //returns the current click coordinates to a text field
  getLocation : function(marker, point, params){
    if(!marker) {
      var lat = point.lat();
      var lng = point.lng();
      $(params.lngTextField).val(lng);
      $(params.latTextField).val(lat);
    }
  },
  
  
  /**
   * 
   * @param {GMarker} marker   
   */
  pointToAddress: function(point, successFunc, errorFunc){
    var successFunc = successFunc || null;
    var errorFunc = errorFunc || null;
    
    wsgn.Map.gCoder = new GClientGeocoder();
    wsgn.Map.gCoder.setBaseCountryCode('de');
    //var latLng = marker.getLatLng();
    var locations = wsgn.Map.gCoder.getLocations(
      point, 
      function(response){
        wsgn.Map.getLocations(point, response, successFunc, errorFunc);
      }
    );
  },
  
  

  /**
   * 
   * @param {Float} lat
   * @param {Float} lng
   * @param {Integer} zoom
   */
  setLocation : function(lat, lng, zoom){
     var newZooom = zoom || 8;
     var point = new GLatLng(lat, lng);
     wsgn.Map.map.setCenter(point, newZooom);
  },
  
  
  /**
   * create a set of markers(overlays) on the map based on an array of marker objects
   * @param {array} markers
   */
  createMarkers: function(markers){
    if (markers.length > 1) {
      wsgn.Map.map.setCenter(new GLatLng(0, 0), 0);
    }
    
    else{
      wsgn.Map.map.setCenter(
        new GLatLng(
          markers[0].lat, 
          markers[0].lng
        ),
        wsgn.Map.settings.zoom
      );
    }
        
    var bounds = new GLatLngBounds();
    var marker = null;
    var latLng = null;
    var icon = null;
    
    $.each(markers, function(num){
      marker = wsgn.Map.createMarker(this);
      bounds.extend(marker.getLatLng());
    });
    
    if(markers.length > 1){
      var zoom = wsgn.Map.map.getBoundsZoomLevel(bounds)-1;
      wsgn.Map.map.setZoom(zoom);
      wsgn.Map.map.setCenter(bounds.getCenter());
    }
    else{
      console.log('setting zoom to standard', wsgn.Map.settings.zoom);
      wsgn.Map.map.setZoom(parseInt(wsgn.Map.settings.zoom));
    }
  },
  
   // ====== This function displays the tooltip ======
      // it can be called from an icon mousover or a side_bar mouseover
  showTooltip: function(marker) {
    wsgn.Map.tooltip.innerHTML = marker.tooltip;
    var point = wsgn.Map.map.getCurrentMapType().getProjection().fromLatLngToPixel(wsgn.Map.map.getBounds().getSouthWest(),wsgn.Map.map.getZoom());
    var offset= wsgn.Map.map.getCurrentMapType().getProjection().fromLatLngToPixel(marker.getPoint(),wsgn.Map.map.getZoom());
    var anchor = marker.getIcon().iconAnchor;
    var width=marker.getIcon().iconSize.width;
    var pos = new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(offset.x - point.x - anchor.x + width,- offset.y + point.y +anchor.y)); 
    pos.apply(wsgn.Map.tooltip);    
    wsgn.Map.tooltip.style.visibility = "visible";
  },
  
  hideTooltip: function(){
    //$(wsgn.Map.tooltip).hide();
    wsgn.Map.tooltip.style.visibility="hidden";
  },
 

  /**
   * create a marker based on assed in properties
   * @param {Object} markerData
   */
  createMarker: function(markerData) {
    var latLng = new GLatLng(markerData.lat, markerData.lng);    
    var markerLabel = markerData.label || null;
    var markerColor = markerData.color || 'blue';
    
    var icon = wsgn.Map.getMarkerIcon(markerData.type, markerLabel, markerColor);
    
    if(markerData.url){            
      marker = new GMarker(latLng, {icon:icon});  
      marker.url = markerData.url;
    }
    else{
      marker = new GMarker(latLng, {icon:icon, clickable: false});            
    }
    
    marker.data = markerData;
    
    if(markerData.tooltip){
      marker.tooltip = markerData.tooltip;
    }
   
   wsgn.Map.map.addOverlay(marker);
   
   GEvent.addListener(marker, 'mouseover', function(){
      wsgn.Map.showTooltip(this);
    });
    
    GEvent.addListener(marker, 'mouseout', function(){
      wsgn.Map.hideTooltip();
    });
   
        
    return marker;
  },
  
  /**
   * a generic function that can be bound to a marker, if marker has property 'label' a label will appear on mouseover
   * 
   */
  showMarkerLabel: function(){
    var left, right, top, html, div;
    if(this.tooltip && this.tooltip.length > 0){
      left = parseInt(wsgn.Map.map.fromLatLngToDivPixel(this.getPoint()).x + 20, 10);
      top = parseInt(wsgn.Map.map.fromLatLngToDivPixel(this.getPoint()).y - 10, 10);
      left = parseInt(wsgn.Map.map.fromLatLngToDivPixel(this.getPoint()).x + 20, 10);
      top = parseInt(wsgn.Map.map.fromLatLngToDivPixel(this.getPoint()).y - 10, 10);
      if($('div#map_info').length === 0){
        html = '<div id="map_info" class="border" style="padding: 2px; background-color: #FDFDF8; display: none; position: absolute; z-index: 9999999999; left: 0px; top: 0px; padding: 3px;">0</div>';
        div = document.createElement("div");
            div.innerHTML = html;
        wsgn.Map.map.getPane(G_MAP_FLOAT_PANE).appendChild(div);             
      }
      $('div#map_info').html(this.tooltip).css('left', left).css('top', top).show();       
    }
  },
  
  /**
   * hides a markerlabel
   * @param {GMarker} marker
   */
  hideMarkerLabel: function(){
    $('#map_info').hide();
  },
  

  /** returns the icon of markers */
  getMarkerIcon : function(type, label, color){
    var icon;
    var labeledIcon = new GIcon(G_DEFAULT_ICON);
    var baseIcon = new GIcon(G_DEFAULT_ICON);    
        /*baseIcon.iconSize = new GSize(20, 20);    
        baseIcon.iconAnchor = new GPoint(10, 10);    
        baseIcon.infoWindowAnchor = new GPoint(25, 5);        
        baseIcon.shadow = "/images/icons/shadow_asset_icon.png";
        baseIcon.shadowSize = new GSize(31.0, 20.0);*/
    
    switch(type){
      default:
      case "labeledMarker":
        var color = color || 'blue';
        var label = label || 'A';
        icon = new GIcon(labeledIcon);
        icon.image = wsgn.Map.settings.baseUrl+"/images/markers/"+color+"_Marker"+label.toUpperCase()+".png";
      break;
      case "played":
        icon = new GIcon(baseIcon);
        icon.image = wsgn.Map.settings.baseUrl+"/images/markers/course_played.png";
      break;      
      case "favourite":
        icon = new GIcon(baseIcon);
        icon.image = wsgn.Map.settings.baseUrl+"/images/markers/course_favourite.png";        
      break;
      case "wantsToPlay":
        icon = new GIcon(baseIcon);
        icon.image = wsgn.Map.settings.baseUrl+"/images/markers/course_wants_to_play.png";
      break;
      case "homeclub":
        icon = new GIcon(baseIcon);
        icon.image = wsgn.Map.settings.baseUrl+"/images/markers/homeclub.png";
      break;                    
    }
    console.log('icon', icon, type);
    return icon;
  },

  /**
   * 
   * @param {gLatLng} point
   * @param {Array} params
   */
  setMarker : function(point, params){  
     wsgn.Map.map.addOverlay(new GMarker(point, wsgn.Map.getMarkerIcon(wsgn.Map.settings.markerType)));     
  },

  /** this function calls custom click functions */
  customClickFunc : function(marker, point, params){    
    console.log('apply custom click fnc!');
    params.func.apply("", [point, marker]);//apply the click funciton on the params.func funciton, eg. i  
  },

  /**
   * 
   * @param {GMarker} marker
   * @param {GLatLng} point
   * @param {Object} params
   */
  markCurrentPosition : function(marker, point, params){
    //remove 
    if(params){
      if(typeof params.removeOld != 'undefined'){
        wsgn.Map.map.clearOverlays();
      }  
    }
    
    wsgn.Map.lastPoint = point;
    wsgn.Map.lastMarker = marker;
    
    wsgn.Map.map.addOverlay(new GMarker(point, wsgn.Map.getMarkerIcon(wsgn.Map.settings.markerType)));
    //console.log("marker: "+wsgn.Map.getMarkerIcon());
    //display a list of close locations in the location fields
  },

  /**
   * 
   * @param {Float} lat
   * @param {Float} lng
   * @param {Boolean} centerView
   */ 
  markLatLng : function(lat, lng, centerView, zoomLevel){
    console.log(centerView);
    var setCenter = false | centerView;
    var point = new GLatLng(lat, lng);
    var marker = new GMarker(point, wsgn.Map.getMarkerIcon(wsgn.Map.settings.markerType));
    wsgn.Map.lastPoint = point;
    wsgn.Map.lastMarker = marker;
    wsgn.Map.map.clearOverlays();
    wsgn.Map.map.addOverlay(marker);
    if(setCenter){
      wsgn.Map.map.setCenter(point);
    }
    if(zoomLevel){
      wsgn.Map.map.setZoom(zoomLevel);
    }
  }
};

console.log('map', wsgn.Map);


//garbage collection
$(window).unload(
  function(){
    try{
      GUnload();//Google maps unload event
    }
    catch(e){}
  }
);
