/*
 * 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 doFitOnce=true;var projection=new Fluster2ProjectionOverlay(map);var me=this;var clusters=new Object();var markersLeft=new Object();this.debugEnabled=_debug;this.gridSize=60;this.markers=new Array();this.currentZoomLevel=-1;this.styles={0:{image:'http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m1.png',textColor:'#FFFFFF',width:53,height:52},10:{image:'http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m2.png',textColor:'#FFFFFF',width:56,height:55},20:{image:'http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/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(doFitOnce && clusters[zoom].length==1 && markerCount==clusters[zoom][0].getMarkerCount()){
	//alert(me.markers.length+ ' ' + clusters[me.currentZoomLevel][0].getMarkerCount() );
	dgMap2.map.fitBounds(clusters[zoom][0].getMarkerBounds());
    if(dgMap2.map.getZoom()>16){
        dgMap2.map.setZoom(16);
    }
	//alert(me.getNumClusters(zoom) );
	doFitOnce=false;
}


}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);

		google.maps.event.addListenerOnce(map, 'tilesloaded', function() {	
			createClusters();
		});
		window.setTimeout(createClusters,1000)

};
	this.getNumClusters=function(zoom){
		return clusters[zoom].length;
	}

}
/*
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 Fluster2Cluster(_fluster, _marker)
{	
	// Get properties from marker
	var markerPosition = _marker.getPosition();
	
	// Properties
	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;
	
	// Get properties from fluster
	var projection = _fluster.getProjection();
	var gridSize = _fluster.gridSize;
	
	// Calculate bounds
	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)
	);
	
	/**
	 * Adds a marker to the cluster.
	 */
	this.addMarker = function(_marker)
	{
		this.markers.push(_marker);
	};

	/**
	 * Shows either the only marker or a cluster marker instead.
	 */
	this.show = function()
	{
		// Show marker if there is only 1
		if(this.markers.length == 1)
		{
			this.markers[0].setMap(me.map);
		}
		else if(this.markers.length > 1)
		{
			// Hide all markers
			for(var i = 0; i < this.markers.length; i++)
			{
				this.markers[i].setMap(null);
			}
			
			// Create marker
			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);
				}
			}
			
			// Show marker
			this.marker.show();
		}
	};
	
	/**
	 * Hides the cluster
	 */
	this.hide = function()
	{
		if(this.marker != null)
		{
			this.marker.hide();
		}
	};
	
	/**
	 * Shows all markers included by this cluster (debugging only).
	 */
	this.debugShowMarkers = function()
	{
		for(var i = 0; i < me.markers.length; i++)
		{
			me.markers[i].setVisible(true);
		}
	};
	
	/**
	 * Hides all markers included by this cluster (debugging only).
	 */
	this.debugHideMarkers = function()
	{
		for(var i = 0; i < me.markers.length; i++)
		{
			me.markers[i].setVisible(false);
		}
	};
	
	/**
	 * Returns the number of markers in this cluster.
	 */
	this.getMarkerCount = function()
	{
		return this.markers.length;
	};
	
	/**
	 * Checks if the cluster bounds contains the given position.
	 */
	this.contains = function(_position)
	{
		return me.bounds.contains(_position);
	};
	
	/**
	 * Returns the central point of this cluster's bounds.
	 */
	this.getPosition = function()
	{
		return this.center;
	};

	/**
	 * Returns this cluster's bounds.
	 */
	this.getBounds = function()
	{
		return this.bounds;
	};

	/**
	 * Return the bounds calculated on the markers in this cluster.
	 */
	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.getMarkerBubbleTxt = function()
	{
		var ile = me.markers.length;
		var txt=dgMap2.map.getZoom()<13?'<h4 class="inBubble"><a class="zoomIn" onclick="dgMap2.zoomFluster()" href="javascript:void(0)">Zoom in</a> or go to property details:</h4>':'';
		txt += '<ul class="inBubble">';
		ile=ile>25?25:ile;
		
		while(ile--){
			txt += '<li><a href="/property/'+me.markers[ile].id+'/">'+me.markers[ile].title+'</a></li>';
		}
		txt += '</ul>'
		txt=me.markers.length>25?txt+'<h4 class="inBubble"><a class="zoomIn" onclick="dgMap2.zoomFluster()" href="javascript:void(0)">Zoom in</a></h4>':txt;
        return txt;
	};

	
	// Add the first marker
	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 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;
	
	// Assign style
	var styles = this.fluster.getStyles();
	for(var i in styles)
	{
		if(this.markerCount > i)
		{
			this.style = styles[i];
		}
		else
		{
			break;
		}
	}
	
	// Basics
	google.maps.OverlayView.call(this);
	this.setMap(this.map);
	
	// Draw
	this.draw();
};

Fluster2ClusterMarker.prototype = new google.maps.OverlayView();

Fluster2ClusterMarker.prototype.draw = function()
{
	if(this.div == null)
	{
		var me = this;
		
		// Create div
		this.div = document.createElement('div');
		
		// Set styles
		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;
		
		// Marker count
		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;
		
		// Cursor and onlick
		this.div.style.cursor = 'pointer';
		google.maps.event.addDomListener(this.div, 'click', function(e) {
            if (!e) var e = window.event;
            e.cancelBubble = true;
            if (e.stopPropagation) e.stopPropagation();
            
			if(me.markerCount<100){
				dgMap2.closeInfoWindow();
				dgMap2.openedInfoWindow = new google.maps.InfoWindow({
					content: me.cluster.getMarkerBubbleTxt(),
					position: me.position
				});

                dgMap2.openedInfoWindow.open( dgMap2.map );
			}else{
				me.map.fitBounds(me.cluster.getMarkerBounds());
			}
		
			//alert(me.cluster.getMarkerBubbleTxt());
            return false;
		});
		
		this.getPanes().overlayLayer.appendChild(this.div);
	}
	
	// Position
	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()
{
	// Hide div
	this.div.style.display = 'none';
};

Fluster2ClusterMarker.prototype.show = function()
{
	// Show div
	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(){};
