/*
 * Fluster2 0.1.1
 * Copyright (C) 2009 Fusonic GmbH
 *
 * This file is part of Fluster2.
 *
 * Fluster2 is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Fluster2 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

function Fluster2(_map,_debug){
var map=_map;
var projection=new 
Fluster2ProjectionOverlay(map);
var me=this;
var clusters=new Object();
var markersLeft=new Object();
this.debugEnabled=_debug;
this.gridSize=31;
this.markers=new Array();
this.currentZoomLevel=-1;
this.styles={
0:{image:'images/m1.png',textColor:'#FFFFFF',width:53,height:52},
10:{image:'images/m2.png',textColor:'#FFFFFF',width:56,height:55},
20:{image:'images/m3.png',textColor:'#FFFFFF',width:66,height:65}};
var zoomChangedTimeout=null;
function createClusters(){
var zoom=map.getZoom();
if(clusters[zoom]){
me.debug('Clusters for zoom level '+zoom+' already initialized.')
}
else{
var clustersThisZoomLevel=new Array();
var clusterCount=0;
var markerCount=me.markers.length;
for(var i=0;i<markerCount;i++){
var marker=me.markers[i];
var markerPosition=marker.getPosition();
var done=false;
for(var j=clusterCount-1;j>=0;j--){
	var cluster=clustersThisZoomLevel[j];
	if(cluster.contains(markerPosition)){
		cluster.addMarker(marker);done=true;break}
		}
	if(!done){
	var cluster=new Fluster2Cluster(me,marker);
	clustersThisZoomLevel.push(cluster);
	clusterCount++}}
clusters[zoom]=clustersThisZoomLevel;
me.debug('Initialized '+clusters[zoom].length+' clusters for zoom level '+zoom+'.')}
if(clusters[me.currentZoomLevel]){
for(var i=0;i<clusters[me.currentZoomLevel].length;i++){
clusters[me.currentZoomLevel][i].hide()}}
me.currentZoomLevel=zoom;
showClustersInBounds()}
function showClustersInBounds(){
var mapBounds=map.getBounds();
for(var i=0;i<clusters[me.currentZoomLevel].length;i++){
var cluster=clusters[me.currentZoomLevel][i];
if(mapBounds.contains(cluster.getPosition())){cluster.show()}}}
this.zoomChanged=function(){
window.clearInterval(zoomChangedTimeout);
zoomChangedTimeout=window.setTimeout(createClusters,500)};
this.getMap=function(){return map};
this.getProjection=function(){
return projection.getP()};
this.debug=function(message){
if(me.debugEnabled){console.log('Fluster2: '+message)}};
this.addMarker=function(_marker){me.markers.push(_marker)};
this.getStyles=function(){return me.styles};
this.initialize=function(){google.maps.event.addListener(map,'zoom_changed',this.zoomChanged);
google.maps.event.addListener(map,'dragend',showClustersInBounds);
window.setTimeout(createClusters,1000)}}

function Fluster2Cluster(_fluster,_marker){
var markerPosition=_marker.getPosition();
this.fluster=_fluster;this.markers=[];
this.bounds=null;
this.marker=null;
this.lngSum=0;
this.latSum=0;
this.center=markerPosition;
this.map=this.fluster.getMap();
var me=this;
var projection=_fluster.getProjection();
var gridSize=_fluster.gridSize;
var position=projection.fromLatLngToDivPixel(markerPosition);
var positionSW=new google.maps.Point(position.x-gridSize,position.y+gridSize);
var positionNE=new google.maps.Point(position.x+gridSize,position.y-gridSize);
this.bounds=new google.maps.LatLngBounds(projection.fromDivPixelToLatLng(positionSW),projection.fromDivPixelToLatLng(positionNE));
this.addMarker=function(_marker){this.markers.push(_marker)};
this.show=function(){
if(this.markers.length==1){
this.markers[0].setMap(me.map)
}
else if(this.markers.length>1){
for(var i=0;i<this.markers.length;i++){
this.markers[i].setMap(null)}
if(this.marker==null){this.marker=new Fluster2ClusterMarker(this.fluster,this);
if(this.fluster.debugEnabled){
google.maps.event.addListener(this.marker,'mouseover',me.debugShowMarkers);
google.maps.event.addListener(this.marker,'mouseout',me.debugHideMarkers)}}
this.marker.show()}};
this.hide=function(){
if(this.marker!=null){this.marker.hide()}};
this.debugShowMarkers=function(){
for(var i=0;i<me.markers.length;i++){me.markers[i].setVisible(true)}};
this.debugHideMarkers=function(){
for(var i=0;i<me.markers.length;i++){me.markers[i].setVisible(false)}};
this.getMarkerCount=function(){return this.markers.length};
this.contains=function(_position){return me.bounds.contains(_position)};
this.getPosition=function(){return this.center};
this.getBounds=function(){return this.bounds};
this.getMarkerBounds=function(){
var bounds=new google.maps.LatLngBounds(me.markers[0].getPosition(),me.markers[0].getPosition());
for(var i=1;i<me.markers.length;i++){bounds.extend(me.markers[i].getPosition())}
return bounds};
this.addMarker(_marker)}

function Fluster2ClusterMarker(_fluster,_cluster){
this.fluster=_fluster;
this.cluster=_cluster;
this.position=this.cluster.getPosition();
this.markerCount=this.cluster.getMarkerCount();
this.map=this.fluster.getMap();
this.style=null;
this.div=null;
var styles=this.fluster.getStyles();
for(var i in styles){
if(this.markerCount>i){
this.style=styles[i]}else{break}}google.maps.OverlayView.call(this);
this.setMap(this.map);
this.draw()};
Fluster2ClusterMarker.prototype=new google.maps.OverlayView();
Fluster2ClusterMarker.prototype.draw=function(){
if(this.div==null){var me=this;
this.div=document.createElement('div');
this.div.style.position='absolute';
this.div.style.width=this.style.width+'px';
this.div.style.height=this.style.height+'px';
this.div.style.lineHeight=this.style.height+'px';
this.div.style.background='transparent url("'+this.style.image+'") 50% 50% no-repeat';
this.div.style.color=this.style.textColor;
this.div.style.textAlign='center';
this.div.style.fontFamily='Arial, Helvetica';
this.div.style.fontSize='11px';
this.div.style.fontWeight='bold';
this.div.innerHTML=this.markerCount;
this.div.style.cursor='pointer';
google.maps.event.addDomListener(this.div,'click',function(){
me.map.fitBounds(me.cluster.getMarkerBounds())});
this.getPanes().overlayLayer.appendChild(this.div)}
var position=this.getProjection().fromLatLngToDivPixel(this.position);
this.div.style.left=(position.x-parseInt(this.style.width/2))+'px';
this.div.style.top=(position.y-parseInt(this.style.height/2))+'px'};
Fluster2ClusterMarker.prototype.hide=function(){
this.div.style.display='none'};
Fluster2ClusterMarker.prototype.show=function(){
this.div.style.display='block'};


function Fluster2ProjectionOverlay(map){
google.maps.OverlayView.call(this);
this.setMap(map);
this.getP=function(){
return this.getProjection()}}
Fluster2ProjectionOverlay.prototype=new google.maps.OverlayView();
Fluster2ProjectionOverlay.prototype.draw=function(){};
