/*

Plugin name: UGMOClientClusterer 0.1
For Ugmo version: 3.0

Description:
Clusters the markers retrieved from the server
*/

(function(undefined){
    if(typeof UGMO == "undefined"){
        throw("UGMO is required for UGMOClientClusterer");
    }
    
    UGMO.prototype.UGMOClientClusterer = {};
    
    UGMO.prototype.UGMOClientClusterer.settings = {
	    //decide the grid size
        gridSize: 10
    };
    
    UGMO.prototype.enableMarkerClustering = function(){
        var ugmo_ = this;
        var listener = null;
        var originalIcons;
        var originalMarkers;
        
        //override the draw function to first cluster the markers
        var oldDrawMarkers = this.drawMarkers;
        this.drawMarkers = function(jsondata, zoomToExtend){
            
            if(zoomToExtend && jsondata.markers.length){
                //get the bounds from the markers
                var markerBounds = new google.maps.LatLngBounds();
                
                for(i in jsondata.markers){
                    markerBounds.extend(new google.maps.LatLng(jsondata.markers[i].lat, jsondata.markers[i].lon));
                }
                ugmo_.map.fitBounds(markerBounds);
            }

            //get the bounds from the map
            var mapBounds = ugmo_.map.getBounds();
            
        
            //cluster markers here
            var size = mapBounds.toSpan();
            
            //define grid in which to search
            var gridSize = ugmo_.UGMOClientClusterer.settings.gridSize;
            var gridCellSizeLat = size.lat()/gridSize;
            var gridCellSizeLon = size.lng()/gridSize;
            var gridCells = {};
                      
            var marker;
            //loop through the markers and assign each one to a grid cell
            for(i=0; i<jsondata.markers.length; i++){
                marker = jsondata.markers[i];
                var latlng = new google.maps.LatLng(marker.lat, marker.lon);
                
                //find grid cell it is in:
                var testBounds = new google.maps.LatLngBounds(mapBounds.getSouthWest(), latlng);
                var testSize = testBounds.toSpan();
                var x = Math.ceil(testSize.lat()/gridCellSizeLat);
                var y = Math.ceil(testSize.lng()/gridCellSizeLon);
                var cell = ''+x+'_'+y+'';
                
                if( typeof gridCells[cell] == 'undefined' ){
                    gridCells[cell] = {
                        markers:[],
                        length:0
                    };
                }
                
                gridCells[cell].length++;
                gridCells[cell].markers.push(i);
            }
            
            //safe all the original markers before really clustering them. We need them to recluster when the map changes and no new markers are fetch automatically
            originalMarkers = [];
            for(i in jsondata.markers){
                originalMarkers.push(jsondata.markers[i]);
            }
            originalIcons = [];
            for(i in jsondata.icons){
                originalIcons.push(jsondata.icons[i]);
            }
            
            //Now cluster them
            var clusters = [];
            for(cell in gridCells){
                //only clusterize when more than 1 markers
                if(gridCells[cell].length > 1){
                    var cellBound = new google.maps.LatLngBounds();
                    var markersInCluster = [];
                    for(i in gridCells[cell].markers){
                        cellBound.extend(new google.maps.LatLng(jsondata.markers[gridCells[cell].markers[i]].lat, jsondata.markers[gridCells[cell].markers[i]].lon));
                        //remove this marker from jsondata.markers
                        markersInCluster.push(jsondata.markers[gridCells[cell].markers[i]]);
                        delete(jsondata.markers[gridCells[cell].markers[i]]);
                    }
                    
                    //create a marker from this cluster
                    var clusterMarker = {
                        'id': 'cluster'+cell,
                        'lat': cellBound.getCenter().lat(),
                        'lon': cellBound.getCenter().lng(),
                        'markers': markersInCluster
                    };
                    clusters.push(clusterMarker);
                }
            }
            
            //loop through jsondata.markers and fix array
            var newMarkers = [];
            for(i in jsondata.markers){
                newMarkers.push(jsondata.markers[i]);
            }
            
            //if no new markers are to be fetched from the server, redraw with the original markers
            if(!ugmo_.settings.getOnlyMarkersWithinBounds && !listener){
                listener = google.maps.event.addListener(ugmo_.map, "zoom_changed", function(){
                    //remove this eventlistener again
                    //google.maps.event.removeListener(listener);
                    ugmo_.drawMarkers({markers: originalMarkers, icons: jsondata.icons}, false);
                });
            }
            
            //change the jsondata to act as if this all was done on the server.
            jsondata.markers = newMarkers; 
            jsondata.clusters = clusters;
            //call the original drawMarkers function
            oldDrawMarkers.apply(ugmo_, [jsondata, false]);
        }
    };
    
}());
