
var g_map = null;
var g_manager = null;
var g_condoIcon;
var g_highlighted = -1; // Highlighted marker id
var g_tempHighlighted = -1;
var g_highlightedBuilding = -1; // The building id highlighted

var g_zoomLevels = [14, 13, 12, 10, 8];
var g_zoomClusterSizes = [0.0, 0.0045, 0.0065, 0.0175, 0.0900];

var g_markers = new Array();
var g_locationToMarkerId = {};
var g_buildingIdToMarkerId = new Array(g_zoomClusterSizes.length); 
var g_markerIdToBuildingId = {};
var g_urlToBuildingId = {};

var g_tempZoomToMarker = {};
var g_tempBuildingIdToUrl = {};
var g_buildingIdToBuilding = {};
var g_reservedMarkers = 0;
var g_oldZoom;
var g_initialized = false;
var g_timeout = 0;

function initializeMap(lat, lon)
{
	if (GBrowserIsCompatible()) {
		g_map = new GMap2(document.getElementById("map_canvas"));
		//g_map.addControl(new GSmallMapControl());
		g_map.addControl(new GLargeMapControl());
		g_map.addControl(new GMapTypeControl());
		g_map.addControl(new GScaleControl());
//		g_map.enableScrollWheelZoom();
		g_map.setCenter(new GLatLng(lat, lon), 12);
		g_manager = new MarkerManager(g_map);
		GEvent.addListener(g_manager, "changed", markerChange);
		g_initialized = true;

	} else {
		// Something went wrong. Display error code and error message.
		alert("Error: This browser is not compatible with google maps.");
	}

}

// returns true if the marker with markerId
// represents more than 1 building
function isGroupedMarker(markerId)
{
	return (g_markerIdToBuildingId[markerId].length > 1);
}

function getUrlId(url)
{
	if (url in g_urlToBuildingId)
		return g_urlToBuildingId[url]
	else
		return -1;
}

function clearMap()
{
	g_map.clearOverlays();
	g_markers = new Array();
	g_locationToMarkerId = {};
	g_buildingIdToMarkerId = new Array(g_zoomClusterSizes.length); 
	g_markerIdToBuildingId = {};
	g_urlToBuildingId = {};

	g_manager.clearMarkers();

	g_highlightedBuilding = -1;

	// remove info window doms
	$(".marker_info_window").remove();
}

/**
 * Translates any zoom level supported by gmaps
 * into a zoom level used in this app.
 *
 * params:
 * ?gmapZoom - The gmap zoom level.
 * If this is empty the present zoom level of the map is used.
 */
function gmapZoomTranslation(gmapZoom)
{
	if (gmapZoom === undefined)
		gmapZoom = g_map.getZoom();

	for (var i = 0; i < g_zoomLevels.length; i++) {
		if (gmapZoom >= g_zoomLevels[i])
			return i;
	}

	return (g_zoomLevels.length - 1);
}

function buildingToMarker(buildingId)
{
	zoom = gmapZoomTranslation();

	if (g_buildingIdToMarkerId[zoom][buildingId] === undefined) {
		alert("Cannot find markerId for building " + buildingId);
		return;
	}

	return g_buildingIdToMarkerId[zoom][buildingId]
}

function getInfoWindowDOMId(markerId)
{
	return 'marker_' + markerId;
}

function buildCondoIcon()
{
	if (g_condoIcon)
		return;

    g_condoIcon = new GIcon();
    g_condoIcon.image = "http://toronto.condocatch.com/static/img/map_icons/highrise.png";
    g_condoIcon.iconSize = new GSize(35, 35);
    g_condoIcon.shadowSize = new GSize(35, 35);
    g_condoIcon.iconAnchor = new GPoint(15, 30);
	g_condoIcon.infoWindowAnchor = new GPoint(10, 5);
}

function coordinateKey(zoom, coordinate)
{
	var gridWidth = g_zoomClusterSizes[zoom];
	if (gridWidth == 0) {
		return coordinate;
	} else {

		// Bucket the coordinate into a grid
		var grid = parseFloat((coordinate / gridWidth).toFixed(0));

		// Center the item in the grid
		//var flatCoord = (grid + 0.0) * gridWidth;

		return grid * gridWidth;
	}
}

function locationKey(zoom, lat, lon)
{

	return "" + zoom + "," + coordinateKey(zoom, lat) + "," + coordinateKey(zoom, lon);
}

function getCondoMarkers(lat, lon)
{
	// Create a marker for each zoom level
	var markers = new Array(g_zoomClusterSizes.length);

	for (var z = 0; z < g_zoomClusterSizes.length; z++) {
		markers[z] = getCondoMarker(z, lat, lon);
	}

	return markers;
}

function getCondoMarker(zoom, lat, lon)
{
	// If marker already exists at (lat,lon)
	var key = locationKey(zoom, lat, lon);
	var markerId = g_locationToMarkerId[key]
	var marker;

	if (markerId) {
		marker = g_markers[markerId];
	} else {
		// build marker
		marker = reserveCondoMarker(coordinateKey(zoom, lat), coordinateKey(zoom, lon));
		g_markers[marker.markerId] = marker;

		// 	map (lat, lon) to marker
		g_locationToMarkerId[key] = marker.markerId;
	}

	return marker;
}

function reserveCondoMarker(latitude, longitude)
{
	marker = new Object();
	marker.latitude = latitude;
	marker.longitude = longitude;
	marker.markerId = g_markers.length + g_reservedMarkers;
	g_reservedMarkers = g_reservedMarkers + 1;

	return marker;
}

function buildCondoMarker(latitude, longitude, markerId, icon)
{
    markerOptions = {icon: icon,
		     		clickable:true,
		     		draggable:false};

    var point = new GLatLng(latitude, longitude);
    marker = new GMarker(point, markerOptions);
	marker.markerId = markerId;
	g_markers[markerId] = marker;

	var highlightCallback = function(id, m) {
		return function() {
			tempHighlightMarker(id);
		}
	}(markerId, marker);

	GEvent.addListener(marker, "mouseover", highlightCallback);
	GEvent.addListener(marker, "mouseout", tempUnhighlightBuilding);

    return marker;
}


function addCondoLocation(buildingId, url, title, price, occupancy, lat, lon, icon, updateMap)
{
	// Don't do anything if the location already exists
	// (check zoom level 0)
	if (0 in g_buildingIdToMarkerId &&
        buildingId in g_buildingIdToMarkerId[0])
		return;

	// get marker for building
	var markers = getCondoMarkers(lat, lon);
	
	// deal with mappings
	//
	// map url to buildingId
	g_urlToBuildingId[url] = buildingId;

	// map buildingId to markerId
	for (var z = 0; z < markers.length; z++) {
		var markerId = markers[z].markerId;

		// map markerId to buildingId
		if (g_markerIdToBuildingId[markerId] === undefined)
			g_markerIdToBuildingId[markerId] = new Array();

		g_markerIdToBuildingId[markerId].push(buildingId);

		if (g_buildingIdToMarkerId[z] === undefined)
			g_buildingIdToMarkerId[z] = {};
			
		g_buildingIdToMarkerId[z][buildingId] = markerId;

		if (g_tempZoomToMarker[z] === undefined)
			g_tempZoomToMarker[z] = new Array();

		g_tempZoomToMarker[z].push(markers[z]);

	}

	g_tempBuildingIdToUrl[buildingId] = url;
	g_buildingIdToBuilding[buildingId] = {
		"title": title,
		"price": price,
		"icon": icon,
		"occupancy": occupancy
	};
}

function updateMap()
{
	for (z in g_tempZoomToMarker) {
		var minZoom = g_zoomLevels[z];
		var maxZoom = null;

		if (z != 0)
			maxZoom = g_zoomLevels[z - 1] - 1;

		// Transform temporary markers into actual markers
		var markers = new Array();
		for (m in g_tempZoomToMarker[z]) {
			var tempMarker = g_tempZoomToMarker[z][m];
			var icon = new GIcon(g_condoIcon, markerIcon(tempMarker.markerId, false));

//	var newIcon = GIcon(icon);
//	var newImage = markerIcon(markerId, false);

			markers.push(buildCondoMarker(tempMarker.latitude, tempMarker.longitude, tempMarker.markerId, icon));
		}

		g_manager.addMarkers(markers, minZoom, maxZoom);
	}

	for (markerId in g_markers) {
		var marker = g_markers[markerId];
		var clickCB = function(m,mId) {
			return function() {
				m.openInfoWindowHtml(markerHtml(mId));
			}
			}(marker, markerId);

		var hoverShowInfo = function(cb,mId) {
			return function() {
				if (g_tempHighlighted == mId) {
					cb();
				}
			}
			}(clickCB, markerId);

		var hoverCB = function(m,mId,cb) {
			return function() {
				clearTimeout(g_timeout);
				g_timeout = setTimeout(cb,700);
			}
			}(marker, markerId, hoverShowInfo);

//		marker.bindInfoWindowHtml(markerHtml(markerId));
		GEvent.addListener(marker, "mouseover", hoverCB);
		GEvent.addListener(marker, "click", clickCB);
	}


	g_manager.refresh();
	g_tempZoomToMarker = {};
	g_reservedMarkers = 0;
}

function markerHtml(markerId)
{
	//var mouseOutStyle = "color:#ff9933";
	var mouseOutStyle = "color:#000000";
	var mouseOverStyle = "color:#ff3333; cursor: pointer;";
	var divId = getInfoWindowDOMId(markerId);

	// Create a div to hold the html
	var html = "<div class='marker_info_window'>";
//	html += "<ul style='padding: 0px; margin: 0px;'>";

	var first = true;
	for (b in g_markerIdToBuildingId[markerId]) {
			var buildingId = g_markerIdToBuildingId[markerId][b];
			var url = g_tempBuildingIdToUrl[buildingId];
			var title = g_buildingIdToBuilding[buildingId].title;
			var price = g_buildingIdToBuilding[buildingId].price;
			var occupancy = g_buildingIdToBuilding[buildingId].occupancy;

			var clickFunction = 'pageTracker._trackEvent("buildings", "map select", "' + title + '"); $.historyLoad("details' + url + '");';

			if (first)
				first = false;
			else {
				html += "<hr />"
			}

			html += "<div style='" + mouseOutStyle + "' " +
					"onClick='" + clickFunction + "' " +
					"onMouseOver='$(this).attr(\"style\", \"" + mouseOverStyle + "\");' " +
					"onMouseOut='$(this).attr(\"style\", \"" + mouseOutStyle + "\");' " +
					">"; 
			html += "<h2>" + title + "</h2>";
			html += "Price: " + price;
			html += "<br />Occupancy: " + occupancy;
			html += "</div>";
	}
//	html += "</ul>"
	html +=	"</div>"

	return html;
}

function centerMap(lat, lon)
{
	g_map.panTo(new GLatLng(lat, lon, 13));
}

function highlightMarker(markerId)
{
	unhighlightMarker()
	if (markerId in g_markers) {
		var img = markerIcon(markerId, true)
		g_markers[markerId].setImage(img);
		g_highlighted = markerId;
	} else {                     
		alert("can't find " + id + " to highlight");
	}                            
}

function unhighlightMarker()
{
	if (g_highlighted in g_markers) {
		var img = markerIcon(g_highlighted, false)
		g_markers[g_highlighted].setImage(img);
		g_highlighted = -1;
	}
}

function tempHighlightMarker(markerId)
{
	tempUnhighlightBuilding();
	if (markerId in g_markers) {
		// Only highlight if icon is visible
		if (g_map.getBounds().containsLatLng(g_markers[markerId].getLatLng())) {
			var img = markerIcon(markerId, true)
			g_markers[markerId].setImage(img);
			g_tempHighlighted = markerId;
		}
	} else {
		alert("can't find " + markerId + " in: " + g_markers);
	}
}

function tempHighlightBuilding(buildingId)
{
	if (!g_initialized)
		return;

	markerId = buildingToMarker(buildingId);
	if (markerId === undefined) {
		//alert("can't find " + id);
		return;
	} else {
		tempHighlightMarker(markerId);
	}
}

function tempUnhighlightBuilding()
{
	if (g_tempHighlighted == -1)
		return;

	if ((g_tempHighlighted != g_highlighted) && (g_tempHighlighted in g_markers)) {
		// Only highlight if icon is visible
		if (g_map.getBounds().containsLatLng(g_markers[g_tempHighlighted].getLatLng())) {
			var img = markerIcon(g_tempHighlighted, false)
			g_markers[g_tempHighlighted ].setImage(img);
		}
		g_tempHighlighted = -1;
	}
}

function markerIcon (markerId, highlight) {
	var img = "http://toronto.condocatch.com/static/img/map_icons/"
	if (isGroupedMarker(markerId))
		img += "multiplex";
	else {
		var buildingId = g_markerIdToBuildingId[markerId][0]
		switch (g_buildingIdToBuilding[buildingId].icon) {
			case "0": img += "highrise"; break;
			case "1": img += "highrise"; break;
			case "2": img += "lowrise"; break;
			case "3": img += "lofts"; break;
			case "4": img += "townhouses"; break;
		}
	}

	if (highlight) {
		img += "_red.png";
	} else {
		img += ".png";
	}
	return img;
}

function waitUntilVisible(latLng)
{
	if (g_map.getBounds().containsLatLng(latLng)) {
		return
	} else {
		alert('not visible');
//		setTimeout('waitUntilVisible(' + latLng + ')', 200);
	}
}

function selectBuilding(buildingId)
{
	g_highlightedBuilding = buildingId;
	markerId = buildingToMarker(buildingId);
	var visible = g_map.getBounds().containsLatLng(g_markers[markerId].getLatLng());
	centerMap(g_markers[markerId].getLatLng().lat(), g_markers[markerId].getLatLng().lng());

	if (visible) {
		tempUnhighlightBuilding();
		highlightMarker(markerId);
	} else {
		// Wait for marker to become visible
		setTimeout('tempUnhighlightBuilding(); highlightMarker(' + markerId + ');', 1000);
	}
}

// Make sure the highlighted building persists
function markerChange(bounds, markerCount)
{
	// check if zoom changed
	if (g_oldZoom != g_map.getZoom()) {
		g_highlighted = -1;
		g_tempHighlighted = -1;
		
		if (g_highlightedBuilding != -1) {
			markerId = buildingToMarker(g_highlightedBuilding);
			highlightMarker(markerId);
		}

		g_oldZoom = g_map.getZoom();
	}
}

