
if (typeof freewave == 'undefined') {
   var freewave = {};
}

$(window).unload(function() {
   GUnload();
});

freewave.GoogleMap = { 

   containerId: null,
   map: null,

   active: null,
   initLat: null,
   initLng: null,

   icon: null,
   iconTrans: null,
   iconCluster: null,

   locations: null,
   oldBound: null,

   init: function(id, active, initLat, initLng) {
      this.containerId = id;
      this.active = active;
      this.initLat = initLat;
      this.initLng = initLng;

      this.icon = new GIcon({
         image: 'http://static.freewave.at/map/freewave_pin_new.png',
         iconSize: new GSize(29, 39),
         shadow: 'http://static.freewave.at/map/freewave_pin_shadow.png', 
         shadowSize: new GSize(44, 42),
         iconAnchor: new GPoint(21, 38),
         infoWindowAnchor: new GPoint(22, 22)
      });

      this.iconTrans = new GIcon({
         image: 'http://static.freewave.at/map/freewave_pin_new_trans.png',
         iconSize: new GSize(29, 39),
         shadow: 'http://static.freewave.at/map/freewave_pin_shadow_trans.png', 
         shadowSize: new GSize(44, 42),
         iconAnchor: new GPoint(21, 38),
         infoWindowAnchor: new GPoint(22, 22)
      });
      
      this.iconCluster = new GIcon({
         image: 'http://static.freewave.at/map/freewave_pin_cluster.png',
         iconSize: new GSize(35, 52),
         iconAnchor: new GPoint(17, 30),
         infoWindowAnchor: new GPoint(17, 30),
      });

      this.iconPosition = new GIcon({
         image: 'http://static.freewave.at/map/freewave_pin_position.png',
         iconSize: new GSize(31, 41),
         iconAnchor: new GPoint(12, 33),
         shadow: 'http://static.freewave.at/map/freewave_pin_position_shadow.png', 
         shadowSize: new GSize(41, 41),
      });
      
      this.map = new GMap2(document.getElementById(id), {
         backgroundColor: '#ffffff'
      });
      
      if (this.active != null) {
         this.map.setCenter(new GLatLng(this.initLat, this.initLng), 16);
      } else {
         this.map.setCenter(new GLatLng(47.50, 13.33), 7);
         this.map.addControl(new GMenuMapTypeControl()); 
         this.map.addControl(new GScaleControl()); 
      }
        
      this.map.addControl(new GLargeMapControl3D()); 
      //this.map.addControl(new GSmallMapControl());
      this.map.addControl(new GOverviewMapControl());
      
      if (navigator.geolocation)
         this.map.addControl(new freewave.GoogleMap.GeoPosControl());

      GEvent.addListener(this.map, 'moveend', function(me) {
         return function() {
            if (me.oldBounds && !me.oldBounds.containsBounds(me.map.getBounds())) {
               me.loadLocations();
            } 
         };
      }(this));
      

     GEvent.addListener(this.map, 'zoomend', function(oldLevel, newLevel) {
         freewave.GoogleMap.loadLocations();
      });

      this.loadLocations();
   },

   loadLocations: function() {
      this.map.clearOverlays();

      $('#google-map-info').hide();
      $('#loading-marker').show();
      
      this.locations = [];
      
      var projection = this.map.getCurrentMapType().getProjection();
      var zoom = this.map.getZoom();
      
      var bounds = this.map.getBounds();
      var padding = 150;
      
      var sw = bounds.getSouthWest();
      var ne = bounds.getNorthEast();
      
      var swPixel = projection.fromLatLngToPixel(sw, zoom);
      var nePixel = projection.fromLatLngToPixel(ne, zoom);
      
      swPixel.x -= padding;
      swPixel.y += padding;
      
      nePixel.x += padding;
      nePixel.y -= padding;
      
      var newSW = projection.fromPixelToLatLng(swPixel, zoom);
      var newNE = projection.fromPixelToLatLng(nePixel, zoom);

      this.oldBounds = new GLatLngBounds(newSW, newNE);

      var lat1 = newSW.lat();
      var lng1 = newSW.lng();
      var lat2 = newNE.lat();
      var lng2 = newNE.lng();

      $.ajax({
         //async: false,
         url: '/hotspots/locations.json',
         dataType: 'json',
         
         complete: function() {
            $('#loading-marker').hide();
         },
         
         data: {
            lat1: lat1,
            lng1: lng1,
            lat2: lat2,
            lng2: lng2,
            zoom: this.map.getZoom(),
            lang: fw_lang
         },
         
         success: function(data) {
            freewave.GoogleMap.locations = data;
            freewave.GoogleMap.drawMarkers();
         }
      });
   },
   
   drawMarkers: function() {
      var zoom = this.map.getZoom();
      this.map.clearOverlays();

      if (this.map.fw_geoloc_active && this.map.fw_geoloc_marker)
         this.map.addOverlay(this.map.fw_geoloc_marker);

      if (zoom < 16 && this.active == null) {
         var clusteredOrLocations = freewave.GoogleMap.ClusterMaker.cluster(this.locations, 50, zoom);
      } else {
         var clusteredOrLocations = this.locations;
      }

      for (var i = 0; i < clusteredOrLocations.length; i++) {
         
         var clusterOrLocation = clusteredOrLocations[i];
         if (clusterOrLocation.length == undefined) {
            
            // Location
            var location = clusterOrLocation;
            
            var marker = new GMarker(new GLatLng(location.latitude, location.longitude), {
               icon: (this.active && this.active != location.uid) ? freewave.GoogleMap.iconTrans : freewave.GoogleMap.icon
            });
            
            marker.uid = location.uid;

            GEvent.addListener(marker, 'click', function(url) {
               return function() {
                  if (url) window.location.href = url;
                };
            }(location.url));

            GEvent.addListener(marker, 'mouseover', function(content, map, active) {
               return function() {

                  if (active && this.nas_id != active)
                     this.setImage('http://static.freewave.at/map/freewave_pin_new.png');
                  
                  var i = $('#google-map-info');
                  i.find('div').html(content);
                  var pos = map.fromLatLngToContainerPixel(this.getLatLng());
                  var gmap = $('#google-map').position();
                  
                  var x = Math.round(pos.x - i.width() / 2) + gmap.left + 1;
                  if (x < gmap.left) {
                     x = gmap.left + 2;
                     
                     var bx = -294 - (x - pos.x);
                     if (bx < -282) bx = -282;
                     //window.status = bx;
                     i.css({'background-position': bx + 'px bottom'});
                  } else {
                     i.css({'background-position': '50% bottom'});
                  }
                  var y = pos.y - 50 - i.height() + gmap.top;
                  if (y < gmap.top - i.height())
                     y = gmap.top - i.height() - 15;
                  
                  i.css({left: x+'px', top: y+'px'})
                  i.show();
                  
               };
            }('<img src="' + location.logoSmall + '" />' +
               '<h4>' + location.name + '</h4>' +
               '<p>' + location.street1 + (location.street2 ? ', ' + location.street2 : '') + '<br />' +
               location.postalCode + ' ' + location.city + '</p>', freewave.GoogleMap.map, this.active));

            GEvent.addListener(marker, 'mouseout', function(active) {
               return function() {
                  if (active && this.uid != active)
                     this.setImage('http://static.freewave.at/map/freewave_pin_new_trans.png');
                  $('#google-map-info').hide();
               }
            }(this.active));

            this.map.addOverlay(marker);
            
            if (location.uid == this.active) {
               var selectionMarker = new freewave.GoogleMap.Selection(marker);
               this.map.addOverlay(selectionMarker);
            }

         } else {
            // Cluster
            var cluster = clusterOrLocation;
         
            var lat = 0;
            var lng = 0;
            var radius = 0;
            var bounds = new GLatLngBounds();
             
            // Mittelpunkt aller im Cluster befindlichen Marker berechnen
            for (var j = 0; j < cluster.length; j++) {
               var location = cluster[j];
               lat += Number(location.latitude);
               lng += Number(location.longitude);
               bounds.extend(new GLatLng(location.latitude, location.longitude));
            }
         
            lat = lat / cluster.length;
            lng = lng / cluster.length;
            
            // Radius bestimmen
            for (var j = 0; j < cluster.length; j++) {
               var location = cluster[j];
               var dist = freewave.GoogleMap.ClusterMaker.pixelDistance(lat, lng, location.latitude, location.longitude, zoom); 
               if (dist > radius)
                  radius = dist;
            }
         
            if (radius < 25) radius = 25;
             
            var marker = new LabeledMarker(new GLatLng(lat, lng), {
               icon: this.iconCluster,
               labelClass: 'label',
               labelOffset: new GSize(-15, 8),
               labelText: cluster.length,
            });
            
            marker.centerBounds = bounds;

            GEvent.addListener(marker, 'click', function(map) {
               return function() {
                  var zoom = map.getBoundsZoomLevel(this.centerBounds);
                  if (zoom > 16) zoom = 16;
                  
                  map.setCenter(this.centerBounds.getCenter(), zoom);
               }
            }(this.map));            

            switch (fw_lang) {
               default:
               case 'de':
                  var clusterContent = '<img src="/wp-content/themes/freewave/images/map_cluster.png" />' + 
                                       '<h4>' + cluster.length + ' Hotspots</h4>' +
                                       '<p>Für Zoom in diesen Bereich klicken.</p>';
                  break;
               case 'en':
                  var clusterContent = '<img src="/wp-content/themes/freewave/images/map_cluster.png" />' + 
                                       '<h4>' + cluster.length + ' hotspots</h4>' +
                                       '<p>Click to zoom into this area.</p>';
                  break;
            }
            
            

            GEvent.addListener(marker, 'mouseover', function(content, map) {
               return function() {
                  var i = $('#google-map-info');
                  i.find('div').html(content);
                  var pos = map.fromLatLngToContainerPixel(this.getLatLng());
                  var gmap = $('#google-map').position();
                  
                  var x = Math.round(pos.x - i.width() / 2) + gmap.left + 1;
                  if (x < gmap.left) {
                     x = gmap.left + 2;
                     
                     var bx = -294 - (x - pos.x);
                     if (bx < -282) bx = -282;
                     //window.status = bx;
                     i.css({'background-position': bx + 'px bottom'});
                  } else {
                     i.css({'background-position': '50% bottom'});
                  }
                  var y = pos.y - 50 - i.height() + gmap.top;
                  if (y < gmap.top - i.height())
                     y = gmap.top - i.height() - 15;
                  
                  i.css({left: x+'px', top: y+'px'})
                  i.show();
                  
               };
            }(clusterContent, this.map));

            GEvent.addListener(marker, 'mouseout', function() {
               $('#google-map-info').hide();
            });
            
            var Radius = new freewave.GoogleMap.Radius(lat, lng, radius);

            this.map.addOverlay(Radius);
            this.map.addOverlay(marker);
         }
      }
   }
   
/*   
   
   function EOffset(point,easting,northing) {
	  var latConv = point.distanceFrom(new GLatLng(point.lat()+0.1,point.lng()))*10;
 	 var lngConv = point.distanceFrom(new GLatLng(point.lat(),point.lng()+0.1))*10;
        return new GLatLng(point.lat()+northing/latConv,point.lng()+easting/lngConv)      
      }
*/
};

/**
 *
 *
 */
freewave.GoogleMap.Selection = function(marker) {
   this.marker = marker;
   this.map = null;
   this.container = null;
}

freewave.GoogleMap.Selection.prototype = new GOverlay();

freewave.GoogleMap.Selection.prototype.initialize = function (map) {
   this.container = document.createElement('div');
   this.container.style.position = 'absolute';
   this.container.style.width = '25px';
   this.container.style.height = '26px';
   this.container.innerHTML = '<img src="/wp-content/themes/freewave/images/selected.gif" alt="Selected Hotspot" />';
   this.map = map;   
   this.clickable = false;
   
   map.getPane(G_MAP_FLOAT_SHADOW_PANE).appendChild(this.container);
}

freewave.GoogleMap.Selection.prototype.remove = function(){
	this.container.parentNode.removeChild(this.container);
}

freewave.GoogleMap.Selection.prototype.show = function() {
   this.container.style.display = 'block';
}

freewave.GoogleMap.Selection.prototype.hide = function() {
   this.container.style.display = 'none';
}

freewave.GoogleMap.Selection.prototype.redraw = function(force) {
   if (!force) return;
   
   var markerPos = this.map.fromLatLngToDivPixel(this.marker.getLatLng());
   var iconHeight = this.marker.getIcon().iconSize.height;
	
	var x = Math.round(markerPos.x - $(this.container).width() / 2) - 1;
	var y = Math.round(markerPos.y - this.marker.getIcon().iconAnchor.y - $(this.container).height() / 2) + 5;
 
//   var point = this.map.fromLatLngToDivPixel(latLng);
   this.container.style.left = x + 'px';
   this.container.style.top  = y + 'px';
}


/**
 *
 *
 */
freewave.GoogleMap.Radius = function(lat, lng, radius) {
   this.lat = lat,
   this.lng = lng,
   this.radius = radius;
   this.map = null;
   this.image = null;
}

freewave.GoogleMap.Radius.prototype = new GOverlay();

freewave.GoogleMap.Radius.prototype.initialize = function (map) {
   this.image = document.createElement('img');
   this.image.style.position = 'absolute';
   this.image.style.opacity = '0.7';
   this.image.setAttribute('src', '/wp-content/themes/freewave/images/cluster4.png');
   this.map = map;   
   this.clickable = false;
   map.getPane(G_MAP_MARKER_SHADOW_PANE).appendChild(this.image);
}

freewave.GoogleMap.Radius.prototype.remove = function(){
	this.image.parentNode.removeChild(this.image);
}

freewave.GoogleMap.Radius.prototype.show = function() {
   this.image.style.display = 'block';
}

freewave.GoogleMap.Radius.prototype.hide = function() {
   this.image.style.display = 'none';
}

freewave.GoogleMap.Radius.prototype.redraw = function(force) {
   if (!force) return;
   
   var position = this.map.fromLatLngToDivPixel(new GLatLng(this.lat, this.lng));

   this.image.style.left = (position.x - this.radius) + 'px';
   this.image.style.top  = (position.y - this.radius) + 'px';
   this.image.style.width = this.image.style.height = (this.radius * 2) + 'px';
}


/**
 *
 *
 */
freewave.GoogleMap.GeoPosControl = function() {
   this.container = null;
   this.map = null;
}

freewave.GoogleMap.GeoPosControl.prototype = new GControl();

freewave.GoogleMap.GeoPosControl.prototype.initialize = function(map) {
   this.map = map;
   this.container = document.createElement('div');
   this.container.setAttribute('id', 'geoloc-control');
   this.container.setAttribute('class', 'geoloc-control');
   this.container.innerHTML = '<img src="/wp-content/themes/freewave/images/geoloc_control_loading.gif" alt="Loading GeoLocation..." style="display: none;">';

   GEvent.addDomListener(this.container, 'click', function() {
      $('#geoloc-control img').show();
      if (!map.fw_geoloc_active) {
         navigator.geolocation.getCurrentPosition(
            function(position, timestamp) {  
               $('#geoloc-control img').hide();
               $('#geoloc-control').css('background-position', '-28px 0');
               map.fw_geoloc_active = true;
               
               if (map.fw_geoloc_marker)
                  map.removeOverlay(map.fw_geoloc_marker);
               
               map.fw_geoloc_marker = new GMarker(new GLatLng(position.coords.latitude, position.coords.longitude), {
                  icon: freewave.GoogleMap.iconPosition
               });
               
               switch (fw_lang) {
                  default:
                  case 'de':
                     var positionContent = '<img src="http://static.freewave.at/map/freewave_pin_position.png" alt="Location" />' +
                                           '<h4>Ihre Position</h4>' +
                                           '<p>Accuracy : ' + (position.coords.accuracy > 1000 ? Math.round(position.coords.accuracy/1000) + " Kilometer" : position.coords.accuracy + " Meter" ) + '</p>';
                     break;
                  case 'en':
                     var positionContent = '<img src="http://static.freewave.at/map/freewave_pin_position.png" alt="Location" />' +
                                           '<h4>Your location</h4>' +
                                           '<p>Accuracy: ' + (position.coords.accuracy > 1000 ? Math.round(position.coords.accuracy/1000) + " kilometers" : position.coords.accuracy + " meters" ) + '</p>';
                     break;
               }
               
               
               GEvent.addListener(map.fw_geoloc_marker, 'mouseover', function(content, map) {
                  return function() {
                     var i = $('#google-map-info');
                     i.find('div').html(content);
                     var pos = map.fromLatLngToContainerPixel(this.getLatLng());
                     var gmap = $('#google-map').position();
                     
                     var x = Math.round(pos.x - i.width() / 2) + gmap.left + 1;
                     if (x < gmap.left) {
                        x = gmap.left + 2;
                        
                        var bx = -294 - (x - pos.x);
                        if (bx < -282) bx = -282;
                        //window.status = bx;
                        i.css({'background-position': bx + 'px bottom'});
                     } else {
                        i.css({'background-position': '50% bottom'});
                     }
                     var y = pos.y - 50 - i.height() + gmap.top;
                     if (y < gmap.top - i.height())
                        y = gmap.top - i.height() - 15;
                     
                     i.css({left: x+'px', top: y+'px'})
                     i.show();
                     
                  };
               }(positionContent, map));

               GEvent.addListener(map.fw_geoloc_marker, 'mouseout', function() {
                  $('#google-map-info').hide();
               });

               GEvent.addListener(map.fw_geoloc_marker, 'click', function(map) {
                  return function() {
                     map.setCenter(this.getLatLng(), 12);
                  }
               }(map));            

               map.addOverlay(map.fw_geoloc_marker);
               map.panTo(new GLatLng(position.coords.latitude, position.coords.longitude));
               GEvent.trigger(map, 'dragend'); 
            },

            function(error) {
               $('#geoloc-control img').hide();
               alert("Error");
               map.fw_geoloc_active.active = false;
            },

            {
               maximumAge:900000
            });
      } else {
         $('#geoloc-control img').hide();
         $('#geoloc-control').css('background-position', '-0 0');
         map.removeOverlay(map.fw_geoloc_marker);
         map.fw_geoloc_active = false;
      }
   });

   this.map.getContainer().appendChild(this.container);
   return this.container;
}

freewave.GoogleMap.GeoPosControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(71, 22));
}


/**
 *
 *
 */
freewave.GoogleMap.ClusterMaker = {
   offset: 268435456,
   radius: 85445659.4471, // offset / Math.PI
  
   lngToX: function(lng) {
      return Math.round(this.offset + this.radius * lng * Math.PI / 180);        
   },
  
   latToY: function(lat) {
      return Math.round(this.offset - this.radius * Math.log((1 + Math.sin(lat * Math.PI / 180)) / (1 - Math.sin(lat * Math.PI / 180))) / 2);
   },

   pixelDistance: function(lat1, lng1, lat2, lng2, zoom) {
      var x1 = this.lngToX(Number(lng1));
      var y1 = this.latToY(Number(lat1));

      var x2 = this.lngToX(Number(lng2));
      var y2 = this.latToY(Number(lat2));

      return Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2)) >> (21 - zoom);
   },
  
   cluster: function(locations, distance, zoom) {
      if (locations == null) return null;
      
      // Check for density
      for (var i = 0; i < locations.length; i++) {
         
         var location = locations[i];
         location.near = 0;
         
         for (var j = 0; j < locations.length; j++) {
            if (i == j) continue;
            var target = locations[j]; 
                       
            var pixels = this.pixelDistance(location.latitude, location.longitude, target.latitude, target.longitude, zoom);
            if (pixels <= distance) {
               location.near++;
            }
         }
      }

      locations.sort(function(l1 ,l2) {
         return l2.near - l1.near;
      });

      var clustered = [];

      while (locations.length > 0) {
         var location  = locations.shift();

         var cluster = [];
         
         for (var i = 0; i < locations.length; i++) {
            var target = locations[i];
            
            var pixels = this.pixelDistance(location.latitude, location.longitude, target.latitude, target.longitude, zoom);

            if (pixels <= distance) {
               cluster.push(target);
               locations.splice(i, 1);
               i--;
            }
         }
         
         // Original:
         if (cluster.length > 0) {
            cluster.push(location);
            clustered.push(cluster);
         } else {
            clustered.push(location);
         }
      }

      return clustered;
   }   
};

