/**
 * Using global variables: basePath - for accessing images.
 *
 */
function clusterTile(markers) {
	clusterTile(markers, "*");
}

var mscClusterTileSize = 64
var mscClusterMinMarkersInCluster = 2;

var mscClusterShowMarkersLinskMaxZoomLevel = 13;
var mscClusterMinZoomLevel = -1; 

function clusterTile(markers, type) {

	var tileSize = mscClusterTileSize;
	var zoom = map.getZoom();
	var currentProjection = G_NORMAL_MAP.getProjection();
	
	var minMarkersInCluster = mscClusterMinMarkersInCluster; 

	//return clusterGridVisibleTiles(markers, type, tileSize, zoom, currentProjection, minMarkersInCluster);
	return clusterGridTiles(markers, type, tileSize, zoom, currentProjection, minMarkersInCluster);
}


function clusterGridTiles(markers, type, tileSize, zoom, currentProjection, minMarkersInCluster) {
	//log("clusterGridTiles:" + type + " #" + markers.length + " " + zoom);
	
	
	var tileClusters = new Array();
	var tileClustersIndex = new Array();

	for (var i = markers.length - 1; i >= 0; i--) {
		var point = markers[i].getLatLng();
		var tilePoint = currentProjection.fromLatLngToPixel(point, zoom);
		var tileCoordinate = new GPoint(Math.floor(tilePoint.x / tileSize), Math.floor(tilePoint.y / tileSize));
		
		var id = tileCoordinate.x + "_" + tileCoordinate.y;
		var index = tileClustersIndex.indexOf(id);
		if (index == -1) {
			tileClusters.push(new Array());
			tileClusters[tileClusters.length -1].push(markers[i]);
			tileClusters[tileClusters.length -1].x = tileCoordinate.x;
			tileClusters[tileClusters.length -1].y = tileCoordinate.y;
			tileClustersIndex.push(id);
		} else {
			tileClusters[index].push(markers[i]);
		}
	}
	
	//log("tileClusters: " + tileClusters.length);
	var clusterMarkers = [];
	for (var i = tileClusters.length - 1; i >= 0; i--) {
		var tc = tileClusters[i];
		//log(tc.x + " " + tc.y + " #" + tc.length);
	
		var bounds = getTileBounds(tc.x, tc.y, tileSize, zoom, currentProjection);
		var clusteredMarkers = clusterOneTile(tc, bounds, type, minMarkersInCluster);
		clusterMarkers = clusterMarkers.concat(clusteredMarkers);	
	}
	
	return clusterMarkers;
}



function clusterGridVisibleTiles(markers, type, tileSize, zoom, currentProjection, minMarkersInCluster) {
	log("clusterGridVisibleTiles:" + type + " #" + markers.length);
	
	
	var tilePointSW = currentProjection.fromLatLngToPixel(map.getBounds().getSouthWest(), zoom);
	var tilePointNE = currentProjection.fromLatLngToPixel(map.getBounds().getNorthEast(), zoom);
	var tileCoordinateSW = new GPoint(Math.floor(tilePointSW.x / tileSize), Math.floor(tilePointSW.y / tileSize));
	var tileCoordinateNE = new GPoint(Math.floor(tilePointNE.x / tileSize), Math.floor(tilePointNE.y / tileSize));

	var tileClusters = new Array();
	for (var i = tileCoordinateSW.x; i <= tileCoordinateNE.x; i++) {
		for (var j = tileCoordinateNE.y; j <= tileCoordinateSW.y; j++) {
			if (tileClusters[i] == undefined) {
				tileClusters[i] = new Array();
			}
			if (tileClusters[i][j] == undefined) {
				tileClusters[i][j] = new Array();
		
			}
		}
	}

	for (var i = 0; i < markers.length; i++) {
		var point = markers[i].getLatLng();
		var tilePoint = currentProjection.fromLatLngToPixel(point, zoom);
		var tileCoordinate = new GPoint(Math.floor(tilePoint.x / tileSize), Math.floor(tilePoint.y / tileSize));

		//log(tileCoordinate.x + " " + tileCoordinate.y + " " + "marker" + i);
    	if ((tileClusters[tileCoordinate.x] != undefined) && (tileClusters[tileCoordinate.x][tileCoordinate.y] != undefined))
			tileClusters[tileCoordinate.x][tileCoordinate.y].push(markers[i]);
	}
	
	
	var clusterMarkers = [];
	for (var i = tileCoordinateSW.x; i <= tileCoordinateNE.x; i++) {
		for (var j = tileCoordinateNE.y; j <= tileCoordinateSW.y; j++) {
			//log( i + " " + j + " " + tileClusters[i][j].length);
			
			var bounds = getTileBounds(i, j, tileSize, zoom, currentProjection);
			var clusteredMarkers = clusterOneTile(tileClusters[i][j], bounds, type, minMarkersInCluster);
			clusterMarkers = clusterMarkers.concat(clusteredMarkers);	
		}
	}
	return clusterMarkers;
	
}


var simpleTileCluster_groupMarkerClickable = true;

function getTileBounds(i, j, tileSize, zoom, currentProjection) {
	var minCoordinate = new GPoint(i * tileSize, j * tileSize);
	var minLatLng = currentProjection.fromPixelToLatLng(minCoordinate, zoom);
	var maxCoordinate = new GPoint(i * tileSize + tileSize, j * tileSize + tileSize);
	var maxLatLng = currentProjection.fromPixelToLatLng(maxCoordinate, zoom);
	var bounds = new GLatLngBounds(minLatLng, maxLatLng);
	return bounds;
}


/**
 * Custom function (uses custom marker object parameter mscShortTitle)
**/
function makeGroupMarkerDescription(tileClusters) {
		var clusterMarkerDesc = "";						
		for (var k = 0; k < tileClusters.length; k++) {
				clusterMarkerDesc += "<a href=\"javascript:mscClickMarker('" + tileClusters[k].mscIndex + "'); void(0);\">" + tileClusters[k].mscShortTitle + "</a><br/>";
		}
		return clusterMarkerDesc;
}

function clusterOneTile(tileClusters, bounds, type, minMarkersInCluster) {
	var clusterMarkers = [];

	if (tileClusters.length == 0) {
		//
	} else if (tileClusters.length < minMarkersInCluster) {
		for (var k = 0; k < tileClusters.length; k++) {
			clusterMarkers.push(tileClusters[k]);
		}
	} else {
		var clusterBounds = new GLatLngBounds(tileClusters[0].getPoint(), tileClusters[0].getPoint());

		for (var k = 0; k < tileClusters.length; k++) {
			var pnt = tileClusters[k].getPoint();
			clusterBounds.extend(pnt);
		}
						
		//var title_ = "#" + tileClusters.length;
		var title_;
		
		var tmpTitle = getClusterGroupMarkerTitle(type);
		if (tmpTitle) {
			title_ = tmpTitle.replace(/#cnt/, "" + tileClusters.length);
		}
						
		//var customIcon = getClusterMarkerIcon(type, tileClusters[i][j].length);
		//var customIcon = createSimpleClusterMarkerIcon();
		var customIcon = getClusterGroupMarkerIcon(type);

		if (title_)						
			markerOptions = {icon:customIcon, title:title_};
		else
			markerOptions = {icon:customIcon};
		//var marker = new GMarker(bounds.getCenter(), markerOptions);
		var marker = new GMarker(clusterBounds.getCenter(), markerOptions);
				

		var clusterMarkerDesc = makeGroupMarkerDescription(tileClusters);					
		
		if (simpleTileCluster_groupMarkerClickable) {
			GEvent.addListener(marker,"click", function() {
				
				if (map.getZoom() >= mscClusterShowMarkersLinskMaxZoomLevel)  {
				//clusterBounds.getCenter()
					marker.openInfoWindow(clusterMarkerDesc);
				} else {
					var zl = map.getBoundsZoomLevel(clusterBounds);
					if ((zl <= mscClusterMinZoomLevel) && (mscClusterMinZoomLevel != -1)) {
						zl = mscClusterMinZoomLevel;
					}
					map.setCenter(clusterBounds.getCenter(), zl);
				}
				
				
			 });
		}

		clusterMarkers.push(marker);
	}
			
	return clusterMarkers;
}

function createSimpleClusterMarkerIcon() {
	var customIcon = new GIcon(G_DEFAULT_ICON);
    return customIcon;
}

var mscGroupDefaultIcon = createSimpleClusterMarkerIcon();
var mscGroupIcons;
var mscGroupTitle;

function getClusterGroupMarkerIcon(type) {
	if (mscGroupIcons) {
		for (var k = 0; k < mscGroupIcons.length; k++) {
			if (mscGroupIcons[k].type == type) {
				return mscGroupIcons[k].groupIcon;
			}
			
		}
	}
	return mscGroupDefaultIcon;
}
function getClusterGroupMarkerTitle(type) {
	var rez;
	if (mscGroupIcons) {
		for (var k = 0; k < mscGroupIcons.length; k++) {
			if (mscGroupIcons[k].type == type) {
				rez =  mscGroupIcons[k].title;
			}
			
		}
	}
	return rez;
}

	
function getClusterMarkerIcon(type, size) {
	var markerType = "largeTDGreenIcons";
	if (type == "0") {
		markerType = "largeTDYellowIcons";
	}
	if (type == "1") {
		markerType = "largeTDBlueIcons";
	}
	if (type == "2") {
		markerType = "largeTDRedIcons";
	}
						
	var url = basePath + "/g" + "/markerIcons/" + markerType + "/blank.png";
	if (size < 99) {
		url = basePath + "/g" + "/markerIcons/" + markerType + "/marker" + size + ".png";
	}
	var customIcon = new GIcon(G_DEFAULT_ICON);
	customIcon.image = url;
	return customIcon;				
}















function tileinfo() {
	/*
		  	document.getElementById("tileinfolog").innerHTML = "bounds: " + map.getBounds()
		  	+"</br>" + tileInfoAtPoint(map.getBounds().getSouthWest())
		  	+"</br>" + tileInfoAtPoint(map.getBounds().getNorthEast());
		  	*/
		  	//tileInfoAtMap();
	clusterTile(markers);
}
function tileInfoAtMap() {
	var currentProjection = G_NORMAL_MAP.getProjection();
	var tilePointSW = currentProjection.fromLatLngToPixel(map.getBounds().getSouthWest(), map.getZoom());
	var tilePointNE = currentProjection.fromLatLngToPixel(map.getBounds().getNorthEast(), map.getZoom());
	var tileCoordinateSW = new GPoint(Math.floor(tilePointSW.x / 256), Math.floor(tilePointSW.y / 256));
	var tileCoordinateNE = new GPoint(Math.floor(tilePointNE.x / 256), Math.floor(tilePointNE.y / 256));

		  //document.getElementById("tileinfolog").innerHTML = tileCoordinateSW.x + " " + tileCoordinateSW.y + "<br/>" + tileCoordinateNE.x + " " + tileCoordinateNE.y + "<br/>";
	for (var i = tileCoordinateSW.x; i <= tileCoordinateNE.x; i++) {
		for (var j = tileCoordinateNE.y; j <= tileCoordinateSW.y; j++) {
				  //document.getElementById("tileinfolog").innerHTML += i + " " + j;
			showTile(i, j);
		}
	}
}

function showTile(x, y) {
	var currentProjection = G_NORMAL_MAP.getProjection();
	var minCoordinate = new GPoint(x * 256, y * 256);
	var minLatLng = currentProjection.fromPixelToLatLng(minCoordinate, map.getZoom());
	var maxCoordinate = new GPoint(x * 256 + 256, y * 256 + 256);
	var maxLatLng = currentProjection.fromPixelToLatLng(maxCoordinate, map.getZoom());
	var townBorders = new Rectangle(new GLatLngBounds(minLatLng, maxLatLng), 1, "#00FF00");
	map.addOverlay(townBorders);
}
function tileInfoAtPoint(latlng) {
	var currentProjection = G_NORMAL_MAP.getProjection();
	var tilePoint = currentProjection.fromLatLngToPixel(latlng, map.getZoom());
	var tileCoordinate = new GPoint();
	tileCoordinate.x = Math.floor(tilePoint.x / 256);
	tileCoordinate.y = Math.floor(tilePoint.y / 256);
	var minCoordinate = new GPoint(tileCoordinate.x * 256, tileCoordinate.y * 256);
	var minLatLng = currentProjection.fromPixelToLatLng(minCoordinate, map.getZoom());
	var maxCoordinate = new GPoint(tileCoordinate.x * 256 + 256, tileCoordinate.y * 256 + 256);
	var maxLatLng = currentProjection.fromPixelToLatLng(maxCoordinate, map.getZoom());
	var townBorders = new Rectangle(new GLatLngBounds(minLatLng, maxLatLng), 2, "#00FF00");
	map.addOverlay(townBorders);
	var myHtml = "Latitude: " + latlng.lat() + "<br/>Longitude: " + latlng.lng() + "<br/>The Tile Coordinate is:<br/> x: " + tileCoordinate.x + "<br/> y: " + tileCoordinate.y + "<br/> at zoom level " + map.getZoom() + "<br/> min: " + minLatLng + "<br/> max: " + maxLatLng;
	return myHtml;
}

