/*
 * @name MarkerManager
 * @version 1.1
 * @copyright (c) 2007 Google Inc.
 * @author Doug Ricket, others
 *
 * @fileoverview Marker manager is an interface between the map and the user,
 * designed to manage adding and removing many points when the viewport changes.
 * <br /><br />
 * <b>How it Works</b>:<br/> 
 * The MarkerManager places its markers onto a grid, similar to the map tiles.
 * When the user moves the viewport, it computes which grid cells have
 * entered or left the viewport, and shows or hides all the markers in those
 * cells.
 * (If the users scrolls the viewport beyond the markers that are loaded,
 * no markers will be visible until the <code>EVENT_moveend</code> 
 * triggers an update.)
 * In practical consequences, this allows 10,000 markers to be distributed over
 * a large area, and as long as only 100-200 are visible in any given viewport,
 * the user will see good performance corresponding to the 100 visible markers,
 * rather than poor performance corresponding to the total 10,000 markers.
 * Note that some code is optimized for speed over space,
 * with the goal of accommodating thousands of markers.
 */
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */
function MarkerManager(g,h){var e=this;
e.map_=g;e.mapZoom_=g.getZoom();e.projection_=g.getCurrentMapType().getProjection();h=h||{};e.tileSize_=MarkerManager.DEFAULT_TILE_SIZE_;var b=g.getMapTypes();var a=b[0].getMaximumResolution();
for(var c=0;c<b.length;c++){var d=b[c].getMaximumResolution();if(d>a){a=d;}}e.maxZoom_=h.maxZoom||a;e.trackMarkers_=h.trackMarkers;e.show_=h.show||true;var f;if(typeof h.borderPadding==="number"){f=h.borderPadding;
}else{f=MarkerManager.DEFAULT_BORDER_PADDING_;}e.swPadding_=new GSize(-f,f);e.nePadding_=new GSize(f,-f);e.borderPadding_=f;e.gridWidth_=[];e.grid_=[];e.grid_[e.maxZoom_]=[];
e.numMarkers_=[];e.numMarkers_[e.maxZoom_]=0;GEvent.bind(g,"moveend",e,e.onMapMoveEnd_);e.removeOverlay_=function(i){g.removeOverlay(i);e.shownMarkers_--;};e.addOverlay_=function(i){if(e.show_){g.addOverlay(i);
e.shownMarkers_++;}};e.resetManager_();e.shownMarkers_=0;e.shownBounds_=e.getMapGridBounds_();}MarkerManager.DEFAULT_TILE_SIZE_=1024;MarkerManager.DEFAULT_BORDER_PADDING_=100;
MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE=256;MarkerManager.prototype.resetManager_=function(){var c=this;var a=MarkerManager.MERCATOR_ZOOM_LEVEL_ZERO_RANGE;for(var b=0;
b<=c.maxZoom_;++b){c.grid_[b]=[];c.numMarkers_[b]=0;c.gridWidth_[b]=Math.ceil(a/c.tileSize_);a<<=1;}};MarkerManager.prototype.clearMarkers=function(){var a=this;
a.processAll_(a.shownBounds_,a.removeOverlay_);a.resetManager_();};MarkerManager.prototype.getTilePoint_=function(d,b,c){var a=this.projection_.fromLatLngToPixel(d,b);
return new GPoint(Math.floor((a.x+c.width)/this.tileSize_),Math.floor((a.y+c.height)/this.tileSize_));};MarkerManager.prototype.addMarkerBatch_=function(c,g,b){var f=c.getPoint();
c.MarkerManager_minZoom=g;if(this.trackMarkers_){GEvent.bind(c,"changed",this,this.onMarkerMoved_);}var d=this.getTilePoint_(f,b,GSize.ZERO);for(var e=b;e>=g;e--){var a=this.getGridCellCreate_(d.x,d.y,e);
a.push(c);d.x=d.x>>1;d.y=d.y>>1;}};MarkerManager.prototype.isGridPointVisible_=function(b){var f=this;var d=f.shownBounds_.minY<=b.y&&b.y<=f.shownBounds_.maxY;var a=f.shownBounds_.minX;
var c=a<=b.x&&b.x<=f.shownBounds_.maxX;if(!c&&a<0){var e=f.gridWidth_[f.shownBounds_.z];c=a+e<=b.x&&b.x<=e-1;}return d&&c;};MarkerManager.prototype.onMarkerMoved_=function(e,a,c){var g=this;
var i=g.maxZoom_;var d=false;var b=g.getTilePoint_(a,i,GSize.ZERO);var f=g.getTilePoint_(c,i,GSize.ZERO);while(i>=0&&(b.x!==f.x||b.y!==f.y)){var h=g.getGridCellNoCreate_(b.x,b.y,i);
if(h){if(g.removeFromArray_(h,e)){g.getGridCellCreate_(f.x,f.y,i).push(e);}}if(i===g.mapZoom_){if(g.isGridPointVisible_(b)){if(!g.isGridPointVisible_(f)){g.removeOverlay_(e);
d=true;}}else{if(g.isGridPointVisible_(f)){g.addOverlay_(e);d=true;}}}b.x=b.x>>1;b.y=b.y>>1;f.x=f.x>>1;f.y=f.y>>1;--i;}if(d){g.notifyListeners_();}};MarkerManager.prototype.removeMarker=function(c){var f=this;
var e=f.maxZoom_;var g=false;var b=c.getPoint();var d=f.getTilePoint_(b,e,GSize.ZERO);while(e>=0){var a=f.getGridCellNoCreate_(d.x,d.y,e);if(a){f.removeFromArray_(a,c);
}if(e===f.mapZoom_){if(f.isGridPointVisible_(d)){f.removeOverlay_(c);g=true;}}d.x=d.x>>1;d.y=d.y>>1;--e;}if(g){f.notifyListeners_();}f.numMarkers_[c.MarkerManager_minZoom]--;
};MarkerManager.prototype.addMarkers=function(d,e,c){var a=this.getOptMaxZoom_(c);for(var b=d.length-1;b>=0;b--){this.addMarkerBatch_(d[b],e,a);}this.numMarkers_[e]+=d.length;
};MarkerManager.prototype.getOptMaxZoom_=function(a){return a||this.maxZoom_;};MarkerManager.prototype.getMarkerCount=function(b){var a=0;for(var c=0;c<=b;c++){a+=this.numMarkers_[c];
}return a;};MarkerManager.prototype.getMarker=function(e,h,j){var f=this;var a=new GLatLng(e,h);var b=f.getTilePoint_(a,j,GSize.ZERO);var d=new GMarker(a);var g=f.getGridCellNoCreate_(b.x,b.y,j);
if(g!=undefined){for(var c=0;c<g.length;c++){if(e==g[c].getLatLng().lat()&&h==g[c].getLatLng().lng()){d=g[c];}}}return d;};MarkerManager.prototype.addMarker=function(b,f,d){var e=this;
var a=this.getOptMaxZoom_(d);e.addMarkerBatch_(b,f,a);var c=e.getTilePoint_(b.getPoint(),e.mapZoom_,GSize.ZERO);if(e.isGridPointVisible_(c)&&f<=e.shownBounds_.z&&e.shownBounds_.z<=a){e.addOverlay_(b);
e.notifyListeners_();}this.numMarkers_[f]++;};MarkerManager.prototype.getGridCellCreate_=function(a,f,e){var c=this.grid_[e];if(a<0){a+=this.gridWidth_[e];}var b=c[a];
if(!b){b=c[a]=[];return(b[f]=[]);}var d=b[f];if(!d){return(b[f]=[]);}return d;};MarkerManager.prototype.getGridCellNoCreate_=function(a,e,d){var c=this.grid_[d];
if(a<0){a+=this.gridWidth_[d];}var b=c[a];return b?b[e]:undefined;};MarkerManager.prototype.getGridBounds_=function(a,i,h,f){i=Math.min(i,this.maxZoom_);var b=a.getSouthWest();
var e=a.getNorthEast();var g=this.getTilePoint_(b,i,h);var d=this.getTilePoint_(e,i,f);var j=this.gridWidth_[i];if(e.lng()<b.lng()||d.x<g.x){g.x-=j;}if(d.x-g.x+1>=j){g.x=0;
d.x=j-1;}var c=new GBounds([g,d]);c.z=i;return c;};MarkerManager.prototype.getMapGridBounds_=function(){var a=this;return a.getGridBounds_(a.map_.getBounds(),a.mapZoom_,a.swPadding_,a.nePadding_);
};MarkerManager.prototype.onMapMoveEnd_=function(){var a=this;a.objectSetTimeout_(this,this.updateMarkers_,0);};MarkerManager.prototype.objectSetTimeout_=function(b,c,a){return window.setTimeout(function(){c.call(b);
},a);};MarkerManager.prototype.visible=function(){return this.show_?true:false;};MarkerManager.prototype.isHidden=function(){return !this.show_;};MarkerManager.prototype.show=function(){this.show_=true;
this.refresh();};MarkerManager.prototype.hide=function(){this.show_=false;this.refresh();};MarkerManager.prototype.toggle=function(){this.show_=!this.show_;this.refresh();
};MarkerManager.prototype.refresh=function(){var a=this;if(a.shownMarkers_>0){a.processAll_(a.shownBounds_,a.removeOverlay_);}if(a.show_){a.processAll_(a.shownBounds_,a.addOverlay_);
}a.notifyListeners_();};MarkerManager.prototype.updateMarkers_=function(){var a=this;a.mapZoom_=this.map_.getZoom();var b=a.getMapGridBounds_();if(b.equals(a.shownBounds_)&&b.z===a.shownBounds_.z){return;
}if(b.z!==a.shownBounds_.z){a.processAll_(a.shownBounds_,a.removeOverlay_);if(a.show_){a.processAll_(b,a.addOverlay_);}}else{a.rectangleDiff_(a.shownBounds_,b,a.removeCellMarkers_);
if(a.show_){a.rectangleDiff_(b,a.shownBounds_,a.addCellMarkers_);}}a.shownBounds_=b;a.notifyListeners_();};MarkerManager.prototype.notifyListeners_=function(){GEvent.trigger(this,"changed",this.shownBounds_,this.shownMarkers_);
};MarkerManager.prototype.processAll_=function(b,d){for(var a=b.minX;a<=b.maxX;a++){for(var c=b.minY;c<=b.maxY;c++){this.processCellMarkers_(a,c,b.z,d);}}};MarkerManager.prototype.processCellMarkers_=function(b,f,d,e){var a=this.getGridCellNoCreate_(b,f,d);
if(a){for(var c=a.length-1;c>=0;c--){e(a[c]);}}};MarkerManager.prototype.removeCellMarkers_=function(a,c,b){this.processCellMarkers_(a,c,b,this.removeOverlay_);};
MarkerManager.prototype.addCellMarkers_=function(a,c,b){this.processCellMarkers_(a,c,b,this.addOverlay_);};MarkerManager.prototype.rectangleDiff_=function(b,a,d){var c=this;
c.rectangleDiffCoords_(b,a,function(e,f){d.apply(c,[e,f,b.z]);});};MarkerManager.prototype.rectangleDiffCoords_=function(b,a,l){var f=b.minX;var m=b.minY;var h=b.maxX;
var d=b.maxY;var e=a.minX;var k=a.minY;var g=a.maxX;var c=a.maxY;var j,i;for(j=f;j<=h;j++){for(i=m;i<=d&&i<k;i++){l(j,i);}for(i=Math.max(c+1,m);i<=d;i++){l(j,i);
}}for(i=Math.max(m,k);i<=Math.min(d,c);i++){for(j=Math.min(h+1,e)-1;j>=f;j--){l(j,i);}for(j=Math.max(f,g+1);j<=h;j++){l(j,i);}}};MarkerManager.prototype.removeFromArray_=function(e,c,d){var a=0;
for(var b=0;b<e.length;++b){if(e[b]===c||(d&&e[b]===c)){e.splice(b--,1);a++;}}return a;};
