// http://www.google.com/apis/maps/documentation/
// http://docs.jquery.com/

// Skapa ny karta
var map, mgrOptions, mgr;
// Egna kontroller
var VKZoomControl = function() {}
VKZoomControl.prototype = new GControl();
VKZoomControl.prototype.initialize = function() {
  var container = $('<div></div>').attr('id', 'mapcontrols');

  var returnButton = $('<span/>').addClass('return').attr('title', 'Till ursprungsvyn').bind('click', function() {
    map.returnToSavedPosition();
  });

  var panNorthButton = $('<span/>').addClass('pan-north').attr('title', 'Panorera norrut').bind('click', function() {
    map.panDirection(0, +1);
  });

  var panEastButton = $('<span/>').addClass('pan-east').attr('title', 'Panorera österut').bind('click', function() {
    map.panDirection(-1, 0);
  });

  var panSouthButton = $('<span/>').addClass('pan-south').attr('title', 'Panorera söderut').bind('click', function() {
    map.panDirection(0, -1);
  });

  var panWestButton = $('<span/>').addClass('pan-west').attr('title', 'Panorera västerut').bind('click', function() {
    map.panDirection(+1, 0);
  });

  var zoomInButton = $('<span/>').addClass('zoom-in').attr('title', 'Zooma in').bind('click', function() {
    map.zoomIn();
  });

  var zoomOutButton = $('<span/>').addClass('zoom-out').attr('title', 'Zooma ut').bind('click', function() {
    map.zoomOut();
  });

  $([
    returnButton,
    panNorthButton,
    panEastButton,
    panSouthButton,
    panWestButton,
    zoomInButton,
    zoomOutButton
  ]).appendTo(container);

  container.appendTo(map.getContainer());
  return container.get(0);
}

VKZoomControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(10, 35));
}

var VKTypeControl = function() {}
VKTypeControl.prototype = new GControl();
VKTypeControl.prototype.initialize = function() {
  var container = $('<div></div>').attr('id', 'maptype');
	var innerContainer = $('<div></div>').attr('class','innerContainer').appendTo(container);

  var mapButton = $('<span>Karta</span>').addClass('active').appendTo(innerContainer).bind('click', function() {
    $(this).addClass('active').siblings().removeClass('active');
    map.setMapType(G_NORMAL_MAP);
  });

  var satelliteButton = $('<span>Satellit</span>').appendTo(innerContainer).bind('click', function() {
    $(this).addClass('active').siblings().removeClass('active');
    map.setMapType(G_SATELLITE_MAP);
  });

  var hybridButton = $('<span>Hybrid</span>').appendTo(innerContainer).bind('click', function() {
    $(this).addClass('active').siblings().removeClass('active');
    map.setMapType(G_HYBRID_MAP);
  });

  var hits = $('<span class="hits"></span>').prependTo(container);

  container.appendTo(map.getContainer());
  return container.get(0);
}

VKTypeControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(0, 0));
}

// Eget infofönster
var VKInfoWindow = function(marker, data, width) {
  this.marker_ = marker;
  this.data_   = data;
  this.width_  = (width ? width + 'px' : 'auto');
}

var VKHoverWindow = function(marker) {
  this.marker_ = marker;  
}

// Använd GOverlay som grund
VKInfoWindow.prototype = new GOverlay();
VKInfoWindow.prototype.initialize = function(map) {
  // Skapa HTML för fönstret och skuggan
  this.map_ = map;
  var container = $('<div/>').addClass('vk_infowindow').css('display', 'none').appendTo(map.getPane(G_MAP_FLOAT_PANE));
  var shadowContainer = $('<div/>').addClass('vk_infowindow_bg').css('display', 'none').appendTo(map.getPane(G_MAP_FLOAT_SHADOW_PANE));
  this.container_ = container.get(0);
  this.shadowContainer_ = shadowContainer.get(0);

  // Storlek på fönstret
  this.contentWidth = 350;
  this.contentHeight = 300;

  // Innehålls-div:en
  var content = $('<div/>').addClass('content').appendTo(this.container_);

  // Stäng-knapp
  var closeButton = $('<div class="close"></div>').appendTo(content);

  // Namn/rubrik (this.data_.name bytt till '&nbsp;')
  $('<h4></h4>').html('&nbsp;').appendTo(content);

  // Blädderlänkar
  var pagination = $('<div>').addClass('pagination').appendTo(content);

  // Antal lokaler i denna byggnad
  var hitCount = this.data_.premises.length;

  // Använd rätt form på ordet :)
  var hitText = (hitCount == 1) ? ' ledig lokal' : ' lediga lokaler';
  var minArea = 10000, maxArea = 0;

  // ??
  $.each(this.data_.premises, function(i, p) {      
    if(p.minArea < minArea)
      minArea = p.minArea;
    if(p.maxArea > maxArea)
      maxArea = p.maxArea;
    if(p.minArea == p.maxArea)
      p.area = p.minArea
    else
      p.area = p.minArea + "-" + p.maxArea;
  });

  var spanArea = (maxArea > minArea) ? minArea + "-" + maxArea : maxArea;
  hitText = '<strong>' + hitCount + hitText + "</strong>, " + spanArea + " m²";

  // Spara location så den kan användas i loopen under
  var loc = this.data_.location
	
	var arr = this.data_.premises;
	
	function drawLinks(active){			
		pagination.empty();
		
		// Visa antalet
  	$('<p class="hits"></p>').html(hitText).appendTo(pagination);
		
		var diff;
		var bottom;
		var top;
		
		if (active + 2 > hitCount) {
			diff = hitCount - active;
			bottom = active - 5 + diff;
		}							
		else
			bottom = active - 3;
		if ( active - 4 < 0 )
		  top = 5;
		else
		  top = active + 2;	
		
		$.each(arr, function (i) {			
			i++;
			if (i > bottom && i <= top) {
				if (i == active) {
					$('<span></span>').text(i).addClass('active').appendTo(pagination);
				}
				else {
					$('<span></span>').text(i).appendTo(pagination).bind('click', function(){
						$(this).parent().siblings('.premises').hide().eq(i-1).show();
						active = i;
						drawLinks(active);
					})
				}
			}
		})
	}
	
  // Loopa igenom alla lokaler som fanns på detta ställe
  if(!realEstateMode)
  {
  $.each(this.data_.premises, function(i, p) {
    if(1 < hitCount) {			
      // Bläddra mellan lokalerna
			drawLinks(1);
      /*$('<span></span>').text(1+i).appendTo(pagination).bind('click', function() {
        $(this).addClass('active').siblings().removeClass('active').parent().siblings('.premises').hide().eq(i).show();
      });*/
    }

    // En sån här låda per lokal, att gömma/visa
    var premisesContainer = $('<div/>').addClass('premises').appendTo(content)

    // Bild och allt annat för lokalen
    $('<img/>').attr('src', p.image).appendTo(premisesContainer);
    $('<p/>').addClass('address').html(p.address).appendTo(premisesContainer);
    $('<p/>').html(loc).appendTo(premisesContainer);
    $('<p/>').html(p.type + ', ' + p.area + ' m&#xB2;').appendTo(premisesContainer);

    // Länk till lokalens sida
    var linkCaption;
    if(hitCount > 1)
      linkCaption = "&#xBB; Till markerad lokal";
    else
      linkCaption = "&#xBB; Till lokalen";
    p.link = $('<a></a>')
    	.attr('href', '/PageTemplates/Premise.aspx?PremiseId=' + p.id + '&epslanguage=SV')
    	.attr('rel', 'external')
    	.html(linkCaption)
    	.bind('click', function () {
    		window.open( $(this).attr('href'), '', 'resizable = yes, toolbar = 1, menubar = 1, location = no, status = 0, titlebar = 0, scrollbars = yes, width = 1000, height = 520, top = 50' );
    		return false;
    	});
    // $('<p>').addClass('more').append(p.link).appendTo(premisesContainer).bind('click', VKMap.showPremise);
    $('<p/>').addClass('more').append(p.link).appendTo(premisesContainer);
    $('<p/>').addClass('description').html(p.description).appendTo(premisesContainer);
  });

  // Göm alla lokaler, visa den första
  $('.premises', content).hide().eq(0).show();
  // Sätt .active på första blädderlänken
  $('.pagination span:first', content).addClass('active');
  }

  // Bakgrundsbilderna
  var bg = $('<div class="bg_top"></div><div class="bg_bottom"></div>').appendTo(this.container_);

  // Stäng-knapp
  var marker = this.marker_;
  closeButton.bind('click', function() {
    marker.closeVKInfoWindow();
  });

};

VKInfoWindow.prototype.remove = function() {
  // Ta bort containern och skuggan
  $(this.container_).add(this.shadowContainer_).remove();
}

VKInfoWindow.prototype.copy = function() {
  return new VKInfoWindow(this.marker_, this.data_, this.width_);
}

VKInfoWindow.prototype.redraw = function(force) {
  if (!force) return false;

  // Markörens pixelposition på kartan
  var pixelLocation = this.map_.fromLatLngToDivPixel(
    this.marker_.getPoint()
  );
		 
	
  // Placera fönstercontainern
  $(this.container_).css({
    position: 'absolute',
    left: (pixelLocation.x + 10) + 'px',
    top: (pixelLocation.y - 95 + 'px'),
    border: '0',
    display: 'block'
  });

  // Panorera om det behövs, så att fönstret ryms i kartan
  var mapNE = this.map_.fromLatLngToDivPixel(
    this.map_.getBounds().getNorthEast()
  );

  var mapSW = this.map_.fromLatLngToDivPixel(
    this.map_.getBounds().getSouthWest()
  );

  // Kolla om kartan behöver panoreras något
  var panX      = 0;
  var panTop    = 0;
  var panBottom = 0;

  if(this.container_.offsetTop < mapNE.y + 25) {
    // Fönstrets topp är utanför kartan
    panTop = mapNE.y - this.container_.offsetTop + 25;
  }
  if(this.container_.offsetLeft + this.contentWidth > mapNE.x) {
    // Fönstrets högra hörn är utanför kartan
    panX = (this.container_.offsetLeft + this.contentWidth) - mapNE.x;
  }
  if(this.container_.offsetTop + this.contentHeight > mapSW.y) {
    // Fönstrets botten är utanför kartan
    panBottom = mapSW.y - (this.container_.offsetTop + this.contentHeight);
  }
  if(panX != 0 || panTop != 0 || panBottom != 0) {
    // Panorera kartan
    panY = (panTop == 0) ? panBottom : panTop;
    this.map_.panBy(new GSize(-panX, panY));
  }
}

VKHoverWindow.prototype = new GOverlay();
VKHoverWindow.prototype.initialize = function(map) {
	this.map_ = map;
	var container = $('<div/>').addClass('vk_hoverwindow').addClass('right')
	  .css('display', 'none');
	  
	  
	if ($.browser.msie && $.browser.version < 7.0) {
		if (realEstateMode)
			container.css("filter", "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/map/map_re_bubble_right.png',sizingMethod='crop'");
		else
			container.css("filter", "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/map/map_bubble_right.png',sizingMethod='crop'");
	}
	container.appendTo(map.getPane(G_MAP_FLOAT_PANE));  
	this.container_ = container.get(0);
	
  this.contentWidth = 280;
  this.contentHeight = 296;
	
	/*var content = $('<div/>').addClass('content').appendTo(this.container_);*/
}

VKHoverWindow.prototype.remove = function() {
  // Ta bort containern
  $(this.container_).remove();
}

VKHoverWindow.prototype.copy = function() {
  return new VKInfoWindow(this.marker_, this.data_, this.width_);
}

VKHoverWindow.prototype.redraw = function(force) {
  if (!force) return false;

  // Markörens pixelposition på kartan
  var pixelLocation = this.map_.fromLatLngToDivPixel(
    this.marker_.getPoint()
  );
	
	// Positionera bubbla
	if(realEstateMode) {
		var horizontalAdjust = 20;
		var verticalAdjust = 48;
		$(this.container_).removeClass('right').addClass('re_right');
	} else {
		var horizontalAdjust = 0;
		var verticalAdjust = 48;
	}
	
  // Placera bubbla
  $(this.container_).css({
    position: 'absolute',
    left: (pixelLocation.x + horizontalAdjust) + 'px',
    top: (pixelLocation.y - verticalAdjust + 'px'),
    border: '0',
    display: 'block'		
  });

  // Ta fram kartgräns
  var mapNE = this.map_.fromLatLngToDivPixel(
    this.map_.getBounds().getNorthEast()
  );

  var mapSW = this.map_.fromLatLngToDivPixel(
    this.map_.getBounds().getSouthWest()
  );

  // Kolla om bubblans visning behöver ändras 
  var panX = 0;  
  	
  if(this.container_.offsetLeft+ this.contentWidth > mapNE.x) {
    // Fönstrets högra hörn är utanför kartan    	
		$(this.container_).css({
	    position: 'absolute',
	    left: (pixelLocation.x - 245) + 'px',
	    top: (pixelLocation.y - 48 + 'px'),
	    border: '0',
	    display: 'block'
  	}).removeClass('right').addClass('left');
		if (realEstateMode) {
			$(this.container_).removeClass('left').addClass('re_left');
		}
		// use some browser sniffing to fix ie6
		if ($.browser.msie && $.browser.version < 7.0) {
			this.container_.style['filter'] = null;
			if (realEstateMode)
				$(this.container_).css("filter", "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/map/map_re_bubble_left.png',sizingMethod='crop'");
			else
				$(this.container_).css("filter", "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/map/map_bubble_left.png',sizingMethod='crop'");
	  	}
  }   
}

// Nya metoder för GMarker
GMarker.prototype.VKInfoWindowInstance = null;
GMarker.prototype.openVKInfoWindow = function(marker, content, width) {
    
  if(this.VKInfoWindowInstance == null) {
    this.VKInfoWindowInstance = new VKInfoWindow(
      this,
      content,
      width
    );
    map.addOverlay(this.VKInfoWindowInstance);
  }
}
GMarker.prototype.closeVKInfoWindow = function() {
  if(this.VKInfoWindowInstance != null) {
    map.removeOverlay(this.VKInfoWindowInstance);
    this.VKInfoWindowInstance = null;
  }
}

GMarker.prototype.VKHoverWindowInstance = null;
GMarker.prototype.openVKHoverWindow = function(marker, content, width) {   
  if(this.VKHoverWindowInstance == null && this.VKInfoWindowInstance == null) {
    this.VKHoverWindowInstance = new VKHoverWindow(
      this,
      content,
      width
    );
    map.addOverlay(this.VKHoverWindowInstance);
  }
}
GMarker.prototype.closeVKHoverWindow = function() {
  if(this.VKHoverWindowInstance != null) {
    map.removeOverlay(this.VKHoverWindowInstance);
    this.VKHoverWindowInstance = null;
  }
}

// Rektangulärt område att använda sen
// var bounds = new GLatLngBounds(new GLatLng(59.332, 18.065), new GLatLng(59.333, 18.066));


// Kartans gränser
// var bounds = map.getBounds();
// var southWest = bounds.getSouthWest();
// var northEast = bounds.getNorthEast();
var temp;
var VKMap = {
  inited: false,
  init: function(data)
  {
    if(VKMap.inited)
      return;

    map = new GMap2($('#map_canvas').get(0));

    // Skapa geocoder för att kolla upp adresser osv
    // var geocoder = new GClientGeocoder();
    // geocoder.getLatLng('Sweden', function() {});

    // Utgångspunkt Göteborg, Lund, Malmö, Stockholm innerstad, Stockholm närförort, Uppsala
    /*var latVals  = [57.4244, 55.4231, 55.4226, 59.332, 59.2140, 59.5120];
    var longVals = [11.5813, 13.1145, 13.1151, 18.065, 18.0056, 17.3820];
    var zooms  = [14, 15, 15, 14, 13, 15];
    var index  = $("#search_premises select")[0].selectedIndex - 1;
    
    if(index == -1) //Ska inte hända
      index = 3;
    
    map.setCenter(new GLatLng(latVals[index], longVals[index]), 15);
    map.setZoom(zooms[index]);*/

    // Utgångspunkt som finns i JSON-svaret
    map.setCenter(new GLatLng(data.view[0], data.view[1]), data.view[2]);

    map.enableContinuousZoom();

    // Ikon för kluster
    /*var clusterIcon        = new GIcon();
    clusterIcon.image      = '/images/map/cluster.png';
    clusterIcon.shadow     = null;
    clusterIcon.iconSize   = new GSize(64, 48);
    clusterIcon.iconAnchor = new GPoint(32, 24);*/

    // Skapa ny Marker Manager
    /*mgrOptions = {
      borderPadding:      500,
      clusterMarkerIcon:  clusterIcon,
      clusterMarkerTitle: 'Klicka för att se alla %count fastigheter',
      fitMapMaxZoom: 9
    };

    mgr = new ClusterMarker(map, mgrOptions);*/
		
		// Skapa ny Marker Manager
    mgrOptions = { borderPadding: 50 };
    mgr = new MarkerManager(map, mgrOptions);
		
    // Sätt dit kontroller
    // map.addControl(new GLargeMapControl());
    map.addControl(new VKZoomControl());
    map.addControl(new VKTypeControl());
    
    GEvent.addListener(map, 'zoomend', function(oldLevel, newLevel) {
      // $('form').trigger('submit');
      mgr.refresh();
    });
    
    VKMap.inited = true;
  },
  
  updateResults: function(data) {
      if(data.locations.length < 1)
    {      
            $('#map_canvas').hide();
			$('.errorMessage').removeClass('displayNone');
			var type = realEstateMode ? "fastigheter" : "lokaler";
			$('.errorMessage').show();
			return;
    }
    
    
    VKMap.init(data); //Kollar om vi har initierat
    
    //
    $(document).trigger("mapResults");

    // Antal träffar
    var foundLocations = data.locations.length;
    var foundPremises  = 0;
    $.each(data.locations, function(i, l) {
      foundPremises += l.premises.length;
    });

    var extra = realEstateMode ? "" : foundPremises + " lokaler i ";
    $('#maptype .hits').html('Hittade ' + extra + foundLocations + ' fastigheter');

    VKMap.updateMap(data);
  },

  updateMap: function(data, noInfoPopup, onlyBig) {
    var bounds = map.getBounds();   

    var markers_s = [], markers_b = [];

    // Loopa genom träffarna
    $.each(data.locations, function(i, l) {
      var icon_s = VKMap.getIcon(l.premises.length, 'small');
      var icon_b = VKMap.getIcon(l.premises.length, 'big');
			
      var point  = new GLatLng(l.coordinates[0], l.coordinates[1]);
      
      bounds.extend(point);			
      
			if(noInfoPopup) {
				var marker_s = new GMarker(point, {icon: icon_s, clickable: false});
      	var marker_b = new GMarker(point, {icon: icon_b, clickable: false});	
			}	else {
				var marker_s = new GMarker(point, icon_s);
      	var marker_b = new GMarker(point, icon_b);
			}

      markers_s.push(marker_s);
      markers_b.push(marker_b);

      // Fixa infofönsterinnehållet
			if (!noInfoPopup) {
		  	GEvent.addListener(marker_s, 'click', function(){
		  		if (realEstateMode) {
		  			window.open( l.href, '', 'resizable = yes, toolbar = 1, menubar = 1, location = no, status = 0, titlebar = 0, scrollbars = yes, width = 1000, height = 620, top = 50' );
    				return false;
		  		} else {
		  			$('div.vk_infowindow div.close').trigger('click');
		  			this.openVKInfoWindow(marker_s, l, 299);
		  		}
		  	});
				GEvent.addListener(marker_b, 'click', function(){
					if(realEstateMode)
						window.open(l.href, '', 'resizable = yes, toolbar = 1, menubar = 1, location = no, status = 0, titlebar = 0, scrollbars = yes, width = 1000, height = 620, top = 50');
					else {
						$('div.vk_infowindow div.close').trigger('click');
		  			this.openVKInfoWindow(marker_b, l, 299);	
					}		  		
		  	});
				
				GEvent.addListener(marker_s, 'mouseover', function(){		  		
		  		this.openVKHoverWindow(marker_s, l, 299);		  		
		  	});
		  	
		  	GEvent.addListener(marker_s, 'mouseout', function(){		  						
		  		this.closeVKHoverWindow();
		  	});
		  }
						
    });
		
		// Rensa gamla resultat
    mgr.clearMarkers();	
		
    // Lägg till markers
    /*mgr.addMarkers(markers_s);
    mgr.addMarkers(markers_b);*/
		
		mgr.addMarkers(markers_s, 0, 15);
    mgr.addMarkers(markers_b, 16);

    mgr.refresh();

    map.savePosition();

    // Loopa genom träffarna
    /*
    $.each(data.clusters, function(i, c) {
      var icon   = VKMap.getIcon(1, 'cluster');
      var point  = new GLatLng(c.coordinates[0], c.coordinates[1]);
      var marker = new GMarker(point, { icon: icon, title: c.title || null });

      GEvent.addListener(marker, 'click', function() {
        map.setZoom(c.zoomTo || 13);
        map.panTo(point);
      });

      
    });
    */
			
		/*mgr.addMarker(marker, c.minZoom || 0, c.maxZoom || 11);*/	
			
    // Panorera kartan till center av alla resultat
    //map.panTo(markers_s[0].getLatLng());

    // Panorera kartan till positionen som finns i JSON-svaret
    map.panTo(new GLatLng(data.view[0], data.view[1]));
    map.setZoom(data.view[2]);

    map.savePosition();

    //map.panTo(bounds.getCenter());
  },

  getIcon: function(count, size) {
    // Count är antalet lokaler på en marker
    //count = (count > 9) ? 9 : count;

    // Zoomnivå
    var zoomlevel   = map.getZoom();
    var iconSize    = size || 'small';

    var icon        = new GIcon();
    //icon.image    = '/images/map/house-icon-' + iconSize + '-' + count + '.png';
    icon.image      = '/images/map/building-' + iconSize + '.png';
    icon.shadow     = null;
    icon.iconSize   = (iconSize == 'big') ? new GSize(62, 58)  : new GSize(32, 30);
    icon.iconAnchor = (iconSize == 'big') ? new GPoint(22, 32) : new GPoint(11, 21);

    return icon;
  },

  showPremise: function() {
    
    // var url = $(this).attr('href');
    var url = "premises_object_about.html";
    $('<div/>').attr('id', 'premises_overlay').load(url + ' #content').appendTo('body')
    .bind('click', VKMap.hidePremise);
    
    return false;
    
  },

  hidePremise: function() {
    $(this).remove();
  }
}


// Sök direkt när sidan visas
//$('#map input').get(0).checked = true;
//$('form').trigger('submit');

var realEstateMode;

// När DOM-trädet är redo
jQuery(function($) {

  realEstateMode =  $("#search_property").length > 0;

	//Verifiera att vi är på kartvyn
	if($('#map_canvas').length > 0)
	{
	  // Måste använda onsubmit pga andra script
	  $('form:last').get(0).onsubmit = function() {
	
		// Skicka som vanligt om listvyn är vald
		if( $('#list input').is(':checked') ) return true;
	
		// Visa kartan
		$('#map_canvas').css("position","static").show().nextAll().hide();
		
		//Kan vara fastighetssök
	
		$.ajax({
		  type: $(this).attr('method'),
		  url:  "/PageTemplates/UtilityPages/SearchPremises.aspx?epslanguage=SV",
		  data: $(this).serialize(),
		  dataType: 'json',
		  error: function() {
		    $('.errorMessage').html('<p>Ett oväntat fel har inträffat.</p>');
			
		  },
		  success: VKMap.updateResults
		});
	
		return false;
	  };
	
	  // Sök direkt om hashen är #search eller ifall område är valt
	  if(!$('#list input').is(':checked') && (window.location.hash == "#search" || $('select:first option:gt(0)').is(':selected') )) {
		$('form:last').get(0).onsubmit();
	  }
	}
});

// När fönstret stängs
jQuery(window).bind('unload', function() {
  // Frigör kartan
  GUnload();
});

function MarkerManager(map,opt_opts){var me=this;me.map_=map;me.mapZoom_=map.getZoom();me.projection_=map.getCurrentMapType().getProjection();opt_opts=opt_opts||{};me.tileSize_=MarkerManager.DEFAULT_TILE_SIZE_;var maxZoom=MarkerManager.DEFAULT_MAX_ZOOM_;if(opt_opts.maxZoom!=undefined){maxZoom=opt_opts.maxZoom;}
me.maxZoom_=maxZoom;me.trackMarkers_=opt_opts.trackMarkers;var padding;if(typeof opt_opts.borderPadding=="number"){padding=opt_opts.borderPadding;}else{padding=MarkerManager.DEFAULT_BORDER_PADDING_;}
me.swPadding_=new GSize(-padding,padding);me.nePadding_=new GSize(padding,-padding);me.borderPadding_=padding;me.gridWidth_=[];me.grid_=[];me.grid_[maxZoom]=[];me.numMarkers_=[];me.numMarkers_[maxZoom]=0;GEvent.bind(map,"moveend",me,me.onMapMoveEnd_);me.removeOverlay_=function(marker){map.removeOverlay(marker);me.shownMarkers_--;};me.addOverlay_=function(marker){map.addOverlay(marker);me.shownMarkers_++;};me.resetManager_();me.shownMarkers_=0;me.shownBounds_=me.getMapGridBounds_();};MarkerManager.DEFAULT_TILE_SIZE_=1024;MarkerManager.DEFAULT_MAX_ZOOM_=17;MarkerManager.DEFAULT_BORDER_PADDING_=100;MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE=256;MarkerManager.prototype.resetManager_=function(){var me=this;var mapWidth=MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE;for(var zoom=0;zoom<=me.maxZoom_;++zoom){me.grid_[zoom]=[];me.numMarkers_[zoom]=0;me.gridWidth_[zoom]=Math.ceil(mapWidth/me.tileSize_);mapWidth<<=1;}};MarkerManager.prototype.clearMarkers=function(){var me=this;me.processAll_(me.shownBounds_,me.removeOverlay_);me.resetManager_();};MarkerManager.prototype.getTilePoint_=function(latlng,zoom,padding){var pixelPoint=this.projection_.fromLatLngToPixel(latlng,zoom);return new GPoint(Math.floor((pixelPoint.x+padding.width)/this.tileSize_),Math.floor((pixelPoint.y+padding.height)/this.tileSize_));};MarkerManager.prototype.addMarkerBatch_=function(marker,minZoom,maxZoom){var mPoint=marker.getPoint();if(this.trackMarkers_){GEvent.bind(marker,"changed",this,this.onMarkerMoved_);}
var gridPoint=this.getTilePoint_(mPoint,maxZoom,GSize.ZERO);for(var zoom=maxZoom;zoom>=minZoom;zoom--){var cell=this.getGridCellCreate_(gridPoint.x,gridPoint.y,zoom);cell.push(marker);gridPoint.x=gridPoint.x>>1;gridPoint.y=gridPoint.y>>1;}};MarkerManager.prototype.isGridPointVisible_=function(point){var me=this;var vertical=me.shownBounds_.minY<=point.y&&point.y<=me.shownBounds_.maxY;var minX=me.shownBounds_.minX;var horizontal=minX<=point.x&&point.x<=me.shownBounds_.maxX;if(!horizontal&&minX<0){var width=me.gridWidth_[me.shownBounds_.z];horizontal=minX+width<=point.x&&point.x<=width-1;}
return vertical&&horizontal;}
MarkerManager.prototype.onMarkerMoved_=function(marker,oldPoint,newPoint){var me=this;var zoom=me.maxZoom_;var changed=false;var oldGrid=me.getTilePoint_(oldPoint,zoom,GSize.ZERO);var newGrid=me.getTilePoint_(newPoint,zoom,GSize.ZERO);while(zoom>=0&&(oldGrid.x!=newGrid.x||oldGrid.y!=newGrid.y)){var cell=me.getGridCellNoCreate_(oldGrid.x,oldGrid.y,zoom);if(cell){if(me.removeFromArray(cell,marker)){me.getGridCellCreate_(newGrid.x,newGrid.y,zoom).push(marker);}}
if(zoom==me.mapZoom_){if(me.isGridPointVisible_(oldGrid)){if(!me.isGridPointVisible_(newGrid)){me.removeOverlay_(marker);changed=true;}}else{if(me.isGridPointVisible_(newGrid)){me.addOverlay_(marker);changed=true;}}}
oldGrid.x=oldGrid.x>>1;oldGrid.y=oldGrid.y>>1;newGrid.x=newGrid.x>>1;newGrid.y=newGrid.y>>1;--zoom;}
if(changed){me.notifyListeners_();}};MarkerManager.prototype.removeMarker=function(marker){var me=this;var zoom=me.maxZoom_;var changed=false;var point=marker.getPoint();var grid=me.getTilePoint_(point,zoom,GSize.ZERO);while(zoom>=0){var cell=me.getGridCellNoCreate_(grid.x,grid.y,zoom);if(cell){me.removeFromArray(cell,marker);}
if(zoom==me.mapZoom_){if(me.isGridPointVisible_(grid)){me.removeOverlay_(marker);changed=true;}}
grid.x=grid.x>>1;grid.y=grid.y>>1;--zoom;}
if(changed){me.notifyListeners_();}};MarkerManager.prototype.addMarkers=function(markers,minZoom,opt_maxZoom){var maxZoom=this.getOptMaxZoom_(opt_maxZoom);for(var i=markers.length-1;i>=0;i--){this.addMarkerBatch_(markers[i],minZoom,maxZoom);}
this.numMarkers_[minZoom]+=markers.length;};MarkerManager.prototype.getOptMaxZoom_=function(opt_maxZoom){return opt_maxZoom!=undefined?opt_maxZoom:this.maxZoom_;}
MarkerManager.prototype.getMarkerCount=function(zoom){var total=0;for(var z=0;z<=zoom;z++){total+=this.numMarkers_[z];}
return total;};MarkerManager.prototype.addMarker=function(marker,minZoom,opt_maxZoom){var me=this;var maxZoom=this.getOptMaxZoom_(opt_maxZoom);me.addMarkerBatch_(marker,minZoom,maxZoom);var gridPoint=me.getTilePoint_(marker.getPoint(),me.mapZoom_,GSize.ZERO);if(me.isGridPointVisible_(gridPoint)&&minZoom<=me.shownBounds_.z&&me.shownBounds_.z<=maxZoom){me.addOverlay_(marker);me.notifyListeners_();}
this.numMarkers_[minZoom]++;};GBounds.prototype.containsPoint=function(point){var outer=this;return(outer.minX<=point.x&&outer.maxX>=point.x&&outer.minY<=point.y&&outer.maxY>=point.y);}
MarkerManager.prototype.getGridCellCreate_=function(x,y,z){var grid=this.grid_[z];if(x<0){x+=this.gridWidth_[z];}
var gridCol=grid[x];if(!gridCol){gridCol=grid[x]=[];return gridCol[y]=[];}
var gridCell=gridCol[y];if(!gridCell){return gridCol[y]=[];}
return gridCell;};MarkerManager.prototype.getGridCellNoCreate_=function(x,y,z){var grid=this.grid_[z];if(x<0){x+=this.gridWidth_[z];}
var gridCol=grid[x];return gridCol?gridCol[y]:undefined;};MarkerManager.prototype.getGridBounds_=function(bounds,zoom,swPadding,nePadding){zoom=Math.min(zoom,this.maxZoom_);var bl=bounds.getSouthWest();var tr=bounds.getNorthEast();var sw=this.getTilePoint_(bl,zoom,swPadding);var ne=this.getTilePoint_(tr,zoom,nePadding);var gw=this.gridWidth_[zoom];if(tr.lng()<bl.lng()||ne.x<sw.x){sw.x-=gw;}
if(ne.x-sw.x+1>=gw){sw.x=0;ne.x=gw-1;}
var gridBounds=new GBounds([sw,ne]);gridBounds.z=zoom;return gridBounds;};MarkerManager.prototype.getMapGridBounds_=function(){var me=this;return me.getGridBounds_(me.map_.getBounds(),me.mapZoom_,me.swPadding_,me.nePadding_);};MarkerManager.prototype.onMapMoveEnd_=function(){var me=this;me.objectSetTimeout_(this,this.updateMarkers_,0);};MarkerManager.prototype.objectSetTimeout_=function(object,command,milliseconds){return window.setTimeout(function(){command.call(object);},milliseconds);};MarkerManager.prototype.refresh=function(){var me=this;if(me.shownMarkers_>0){me.processAll_(me.shownBounds_,me.removeOverlay_);}
me.processAll_(me.shownBounds_,me.addOverlay_);me.notifyListeners_();};MarkerManager.prototype.updateMarkers_=function(){var me=this;me.mapZoom_=this.map_.getZoom();var newBounds=me.getMapGridBounds_();if(newBounds.equals(me.shownBounds_)&&newBounds.z==me.shownBounds_.z){return;}
if(newBounds.z!=me.shownBounds_.z){me.processAll_(me.shownBounds_,me.removeOverlay_);me.processAll_(newBounds,me.addOverlay_);}else{me.rectangleDiff_(me.shownBounds_,newBounds,me.removeCellMarkers_);me.rectangleDiff_(newBounds,me.shownBounds_,me.addCellMarkers_);}
me.shownBounds_=newBounds;me.notifyListeners_();};MarkerManager.prototype.notifyListeners_=function(){GEvent.trigger(this,"changed",this.shownBounds_,this.shownMarkers_);};MarkerManager.prototype.processAll_=function(bounds,callback){for(var x=bounds.minX;x<=bounds.maxX;x++){for(var y=bounds.minY;y<=bounds.maxY;y++){this.processCellMarkers_(x,y,bounds.z,callback);}}};MarkerManager.prototype.processCellMarkers_=function(x,y,z,callback){var cell=this.getGridCellNoCreate_(x,y,z);if(cell){for(var i=cell.length-1;i>=0;i--){callback(cell[i]);}}};MarkerManager.prototype.removeCellMarkers_=function(x,y,z){this.processCellMarkers_(x,y,z,this.removeOverlay_);};MarkerManager.prototype.addCellMarkers_=function(x,y,z){this.processCellMarkers_(x,y,z,this.addOverlay_);};MarkerManager.prototype.rectangleDiff_=function(bounds1,bounds2,callback){var me=this;me.rectangleDiffCoords(bounds1,bounds2,function(x,y){callback.apply(me,[x,y,bounds1.z]);});};MarkerManager.prototype.rectangleDiffCoords=function(bounds1,bounds2,callback){var minX1=bounds1.minX;var minY1=bounds1.minY;var maxX1=bounds1.maxX;var maxY1=bounds1.maxY;var minX2=bounds2.minX;var minY2=bounds2.minY;var maxX2=bounds2.maxX;var maxY2=bounds2.maxY;for(var x=minX1;x<=maxX1;x++){for(var y=minY1;y<=maxY1&&y<minY2;y++){callback(x,y);}
for(var y=Math.max(maxY2+1,minY1);y<=maxY1;y++){callback(x,y);}}
for(var y=Math.max(minY1,minY2);y<=Math.min(maxY1,maxY2);y++){for(var x=Math.min(maxX1+1,minX2)-1;x>=minX1;x--){callback(x,y);}
for(var x=Math.max(minX1,maxX2+1);x<=maxX1;x++){callback(x,y);}}};MarkerManager.prototype.removeFromArray=function(array,value,opt_notype){var shift=0;for(var i=0;i<array.length;++i){if(array[i]===value||(opt_notype&&array[i]==value)){array.splice(i--,1);shift++;}}
return shift;};

/*
	ClusterMarker Version 1.3.0
	
	A marker manager for the Google Maps API
	http://googlemapsapi.martinpearman.co.uk/clustermarker
	
	Copyright Martin Pearman 2008
	Last updated 5th March 2008

	This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

	You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
	
*/

/*function ClusterMarker($map,$options){this._map=$map;this._mapMarkers=[];this._iconBounds=[];this._clusterMarkers=[];this._eventListeners=[];if(typeof($options)==='undefined'){$options={};}this.borderPadding=($options.borderPadding)?$options.borderPadding:256;this.clusteringEnabled=($options.clusteringEnabled===false)?false:true;if($options.clusterMarkerClick){this.clusterMarkerClick=$options.clusterMarkerClick;}if($options.clusterMarkerIcon){this.clusterMarkerIcon=$options.clusterMarkerIcon;}else{this.clusterMarkerIcon=new GIcon();this.clusterMarkerIcon.image='http://maps.google.com/mapfiles/arrow.png';this.clusterMarkerIcon.iconSize=new GSize(39,34);this.clusterMarkerIcon.iconAnchor=new GPoint(9,31);this.clusterMarkerIcon.infoWindowAnchor=new GPoint(9,31);this.clusterMarkerIcon.shadow='http://www.google.com/intl/en_us/mapfiles/arrowshadow.png';this.clusterMarkerIcon.shadowSize=new GSize(39,34);}this.clusterMarkerTitle=($options.clusterMarkerTitle)?$options.clusterMarkerTitle:'Click to zoom in and see %count markers';if($options.fitMapMaxZoom){this.fitMapMaxZoom=$options.fitMapMaxZoom;}this.intersectPadding=($options.intersectPadding)?$options.intersectPadding:0;if($options.markers){this.addMarkers($options.markers);}GEvent.bind(this._map,'moveend',this,this._moveEnd);GEvent.bind(this._map,'zoomend',this,this._zoomEnd);GEvent.bind(this._map,'maptypechanged',this,this._mapTypeChanged);}ClusterMarker.prototype.addMarkers=function($markers){var i;if(!$markers[0]){var $numArray=[];for(i in $markers){$numArray.push($markers[i]);}$markers=$numArray;}for(i=$markers.length-1;i>=0;i--){$markers[i]._isVisible=false;$markers[i]._isActive=false;$markers[i]._makeVisible=false;}this._mapMarkers=this._mapMarkers.concat($markers);};ClusterMarker.prototype._clusterMarker=function($clusterGroupIndexes){function $newClusterMarker($location,$icon,$title){return new GMarker($location,{icon:$icon,title:$title});}var $clusterGroupBounds=new GLatLngBounds(),i,$clusterMarker,$clusteredMarkers=[],$marker,$this=this;for(i=$clusterGroupIndexes.length-1;i>=0;i--){$marker=this._mapMarkers[$clusterGroupIndexes[i]];$marker.index=$clusterGroupIndexes[i];$clusterGroupBounds.extend($marker.getLatLng());$clusteredMarkers.push($marker);}$clusterMarker=$newClusterMarker($clusterGroupBounds.getCenter(),this.clusterMarkerIcon,this.clusterMarkerTitle.replace(/%count/gi,$clusterGroupIndexes.length));$clusterMarker.clusterGroupBounds=$clusterGroupBounds;this._eventListeners.push(GEvent.addListener($clusterMarker,'click',function(){$this.clusterMarkerClick({clusterMarker:$clusterMarker,clusteredMarkers:$clusteredMarkers});}));return $clusterMarker;};ClusterMarker.prototype.clusterMarkerClick=function($args){this._map.setCenter($args.clusterMarker.getLatLng(),this._map.getBoundsZoomLevel($args.clusterMarker.clusterGroupBounds));};ClusterMarker.prototype._filterActiveMapMarkers=function(){var $borderPadding=this.borderPadding,$mapZoomLevel=this._map.getZoom(),$mapProjection=this._map.getCurrentMapType().getProjection(),$mapPointSw,$activeAreaPointSw,$activeAreaLatLngSw,$mapPointNe,$activeAreaPointNe,$activeAreaLatLngNe,$activeAreaBounds=this._map.getBounds(),i,$marker,$uncachedIconBoundsIndexes=[],$oldState;if($borderPadding){$mapPointSw=$mapProjection.fromLatLngToPixel($activeAreaBounds.getSouthWest(),$mapZoomLevel);$activeAreaPointSw=new GPoint($mapPointSw.x-$borderPadding,$mapPointSw.y+$borderPadding);$activeAreaLatLngSw=$mapProjection.fromPixelToLatLng($activeAreaPointSw,$mapZoomLevel);$mapPointNe=$mapProjection.fromLatLngToPixel($activeAreaBounds.getNorthEast(),$mapZoomLevel);$activeAreaPointNe=new GPoint($mapPointNe.x+$borderPadding,$mapPointNe.y-$borderPadding);$activeAreaLatLngNe=$mapProjection.fromPixelToLatLng($activeAreaPointNe,$mapZoomLevel);$activeAreaBounds.extend($activeAreaLatLngSw);$activeAreaBounds.extend($activeAreaLatLngNe);}this._activeMarkersChanged=false;if(typeof(this._iconBounds[$mapZoomLevel])==='undefined'){this._iconBounds[$mapZoomLevel]=[];this._activeMarkersChanged=true;for(i=this._mapMarkers.length-1;i>=0;i--){$marker=this._mapMarkers[i];$marker._isActive=$activeAreaBounds.containsLatLng($marker.getLatLng())?true:false;$marker._makeVisible=$marker._isActive;if($marker._isActive){$uncachedIconBoundsIndexes.push(i);}}}else{for(i=this._mapMarkers.length-1;i>=0;i--){$marker=this._mapMarkers[i];$oldState=$marker._isActive;$marker._isActive=$activeAreaBounds.containsLatLng($marker.getLatLng())?true:false;$marker._makeVisible=$marker._isActive;if(!this._activeMarkersChanged&&$oldState!==$marker._isActive){this._activeMarkersChanged=true;}if($marker._isActive&&typeof(this._iconBounds[$mapZoomLevel][i])==='undefined'){$uncachedIconBoundsIndexes.push(i);}}}return $uncachedIconBoundsIndexes;};ClusterMarker.prototype._filterIntersectingMapMarkers=function(){var $clusterGroup,i,j,$mapZoomLevel=this._map.getZoom();for(i=this._mapMarkers.length-1;i>0;i--){if(this._mapMarkers[i]._makeVisible){$clusterGroup=[];for(j=i-1;j>=0;j--){if(this._mapMarkers[j]._makeVisible&&this._iconBounds[$mapZoomLevel][i].intersects(this._iconBounds[$mapZoomLevel][j])){$clusterGroup.push(j);}}if($clusterGroup.length!==0){$clusterGroup.push(i);for(j=$clusterGroup.length-1;j>=0;j--){this._mapMarkers[$clusterGroup[j]]._makeVisible=false;}this._clusterMarkers.push(this._clusterMarker($clusterGroup));}}}};ClusterMarker.prototype.fitMapToMarkers=function(){var $markers=this._mapMarkers,$markersBounds=new GLatLngBounds(),i;for(i=$markers.length-1;i>=0;i--){$markersBounds.extend($markers[i].getLatLng());}var $fitMapToMarkersZoom=this._map.getBoundsZoomLevel($markersBounds);if(this.fitMapMaxZoom&&$fitMapToMarkersZoom>this.fitMapMaxZoom){$fitMapToMarkersZoom=this.fitMapMaxZoom;}this._map.setCenter($markersBounds.getCenter(),$fitMapToMarkersZoom);this.refresh();};ClusterMarker.prototype._mapTypeChanged=function(){this.refresh(true);};ClusterMarker.prototype._moveEnd=function(){if(!this._cancelMoveEnd){this.refresh();}else{this._cancelMoveEnd=false;}};ClusterMarker.prototype._preCacheIconBounds=function($indexes){var $mapProjection=this._map.getCurrentMapType().getProjection(),$mapZoomLevel=this._map.getZoom(),i,$marker,$iconSize,$iconAnchorPoint,$iconAnchorPointOffset,$iconBoundsPointSw,$iconBoundsPointNe,$iconBoundsLatLngSw,$iconBoundsLatLngNe,$intersectPadding=this.intersectPadding;for(i=$indexes.length-1;i>=0;i--){$marker=this._mapMarkers[$indexes[i]];$iconSize=$marker.getIcon().iconSize;$iconAnchorPoint=$mapProjection.fromLatLngToPixel($marker.getLatLng(),$mapZoomLevel);$iconAnchorPointOffset=$marker.getIcon().iconAnchor;$iconBoundsPointSw=new GPoint($iconAnchorPoint.x-$iconAnchorPointOffset.x-$intersectPadding,$iconAnchorPoint.y-$iconAnchorPointOffset.y+$iconSize.height+$intersectPadding);$iconBoundsPointNe=new GPoint($iconAnchorPoint.x-$iconAnchorPointOffset.x+$iconSize.width+$intersectPadding,$iconAnchorPoint.y-$iconAnchorPointOffset.y-$intersectPadding);$iconBoundsLatLngSw=$mapProjection.fromPixelToLatLng($iconBoundsPointSw,$mapZoomLevel);$iconBoundsLatLngNe=$mapProjection.fromPixelToLatLng($iconBoundsPointNe,$mapZoomLevel);this._iconBounds[$mapZoomLevel][$indexes[i]]=new GLatLngBounds($iconBoundsLatLngSw,$iconBoundsLatLngNe);}};ClusterMarker.prototype.refresh=function($forceFullRefresh){var i,$marker,$uncachedIconBoundsIndexes=this._filterActiveMapMarkers();if(this._activeMarkersChanged||$forceFullRefresh){this._removeClusterMarkers();if(this.clusteringEnabled&&this._map.getZoom()<this._map.getCurrentMapType().getMaximumResolution()){if($uncachedIconBoundsIndexes.length>0){this._preCacheIconBounds($uncachedIconBoundsIndexes);}this._filterIntersectingMapMarkers();}for(i=this._clusterMarkers.length-1;i>=0;i--){this._map.addOverlay(this._clusterMarkers[i]);}for(i=this._mapMarkers.length-1;i>=0;i--){$marker=this._mapMarkers[i];if(!$marker._isVisible&&$marker._makeVisible){this._map.addOverlay($marker);$marker._isVisible=true;}if($marker._isVisible&&!$marker._makeVisible){this._map.removeOverlay($marker);$marker._isVisible=false;}}}};ClusterMarker.prototype._removeClusterMarkers=function(){for(var i=this._clusterMarkers.length-1;i>=0;i--){this._map.removeOverlay(this._clusterMarkers[i]);}for(i=this._eventListeners.length-1;i>=0;i--){GEvent.removeListener(this._eventListeners[i]);}this._clusterMarkers=[];this._eventListeners=[];};ClusterMarker.prototype.removeMarkers=function(){for(var i=this._mapMarkers.length-1;i>=0;i--){if(this._mapMarkers[i]._isVisible){this._map.removeOverlay(this._mapMarkers[i]);}delete this._mapMarkers[i]._isVisible;delete this._mapMarkers[i]._isActive;delete this._mapMarkers[i]._makeVisible;}this._removeClusterMarkers();this._mapMarkers=[];this._iconBounds=[];};ClusterMarker.prototype.triggerClick=function($index){var $marker=this._mapMarkers[$index];if($marker._isVisible){GEvent.trigger($marker,'click');}else if($marker._isActive){this._map.setCenter($marker.getLatLng());this._map.zoomIn();this.triggerClick($index);}else{this._map.setCenter($marker.getLatLng());this.triggerClick($index);}};ClusterMarker.prototype._zoomEnd=function(){this._cancelMoveEnd=true;this.refresh(true);};*/