function ClusterManager() {
	this.clusters = {};
}
ClusterManager.prototype.setMap = function(map) {
	this.map = map;
	this.onMoveEndHandle = GEvent.addListener(map, "moveend", function() { this.onMoveEnd(); }.bind(this));
}
ClusterManager.prototype.clear = function() {
	for (var key in this.clusters)
		map.removeOverlay(this.clusters[key]);
	this.clusters = {};
}
ClusterManager.prototype.clearCounts = function() {
	for (var key in this.clusters)
		this.clusters[key].count = 0;
}

ClusterManager.prototype.options = {
	// width, height
};

ClusterManager.prototype.assignCluster = function(obj) {
	var cw = this.options.width;
	var ch = this.options.height;
	var cx = Math.floor(obj.px / cw);
	var cy = Math.floor(obj.py / ch);
	var key = 'c'+cx+'_'+cy;
	var c = this.clusters[key];
	if (! c) {
		// using projection coords in constructor
		c = new GCluster(cx * cw, cy * ch);
		c.count = 0;
		c.key = key;
		this.clusters[key] = c;
	}
	obj.cluster = c;
}

ClusterManager.prototype.onMoveEnd = function() {

	if (this.scheduleZoomIn) {
		delete this.scheduleZoomIn;

		//_clmgr.map = this.map;
		// setTimeout('_clmgr.map.zoomIn(); delete _clmgr.map', 200);

		this.map.zoomIn();
	}
}

ClusterManager.prototype.destroy = function() {
	this.clear();
	if (this.onMoveEndHandle)
		GEvent.removeListener(this.onMoveEndHandle);
}

ClusterManager.prototype.onZoom = function(clusterUid) {
	var c = this.clusters[clusterUid];
	var proj = G_NORMAL_MAP.getProjection();
	var centerX = c.px + Math.floor(c.options.width / 2);
	var centerY = c.py + Math.floor(c.options.height / 2);
	
	var zoom = this.map.getZoom();
	
	/* calculating difference with current center */
	var mapCenter = this.map.getCenter();
	var mc = proj.fromLatLngToPixel(mapCenter, zoom);
	var dx = centerX - mc.x;
	var dy = centerY - mc.y;
	var diff = Math.abs(dx) + Math.abs(dy);
	
	var coord = proj.fromPixelToLatLng(new GPoint(centerX, centerY), zoom);

	this.map.addOverlay(new GZoomer({
		w : this.options.width,
		h : this.options.height,
		coord : coord,
		duration : 300,
		steps : 7,
		fadeDuration: 2000,
		fadeSteps : 15,
		lineWidth : 6,
		correction : {x: -6, y: -5, w: 0, h: -1}
	}));

	if (diff < 4) {
		this.map.setCenter(coord);
		this.map.zoomIn();
	} else {
		this.scheduleZoomIn = true;
		map.panTo(coord);
	}
/*	
	this.map.setCenter(coord);
	this.map.zoomIn();
*/
}
_clmgr = {};

