/* ---------------------------------------------------------------------------
Copyright:
	Davis Instruments, (c) 2010

Code by:
	Author:  Andy Schmidt
	Created: 01/15/2010

Notes:
	Best viewed with TAB-Size = 4

ToDo:
	Todo items are marked with a $$$ comment

Revisions:

--------------------------------------------------------------------------- */

//--------------------------------------
// Global variables
//--------------------------------------
var oDebugDiv		= null;
var oMapDiv			= null;
var oMapInfoDiv		= null;
var oGMap			= null;
var oMapCenter		= null;
var oMapBounds		= null;
var oMapSW			= null;
var oMapNE			= null;
var oStatusWindow	= null;
var sMapDomain		= "";

var iMapWidth		= 760;
var iMapHeight		= 480;
var iMapZoom		= 1;			// Default Zoom Level
var dLat			= 0.000;		// Default Lat
var dLng			= 0.000;		// Default Lng

var iIconSize		= 16;			// Default Cluster Icon Size
var dIconSizeMod	= 0.9;			// Icon size modifier
var iClustersDrawn	= 0;
var iStationsDrawn	= 0;

var oClusterDisplay		= new Array();
var oStationDisplay		= new Array();
var oGeoCoder			= null;
var oInfoWindowLoc		= null;

// JSON file holding the Station data
// noCache=Math.random(); added to force the browser to reload a fresh copy
var sJson				= "/mapstations.json?noCache=" + Math.random();

var oMapClusterManager	= null;		// Cluster Manager object
var oStations			= null;		// Array holding all station data. Build from the json file data.
var oClusterArray		= null;		// Array that holds a grid of all possible Clusters
var oActiveClusters		= null;		// Array that holds pointers to all Clusters with at least one Station
var dGridSizeLat		= 10;		// Size of the Lat grid, in degrees
var dGridSizeLng		= 10;		// Size of the Lng grid, in degrees
var iMinClusterStations	= 5;		// Lower threshold to stop clustering
var iZoomLabelDisplay	= 2;		// Zoom level at which the text labels are displayed
var iZoomCheckBounds	= 2;		// Zoom level at which to start checking the map viewport
var iZoomDrawStations	= 4;		// Zoom level at which to start drawing individual Stations
var iZoomShowSegments	= 4;		// Zoom level at which to start showing Cluster Segments
var iZoomMaxSegLevels	= 8;		// Max Zoom level to 'drill down' and create Cluster Segments

//-------------------------------------
// Set the Text of the Map Info Div
//-------------------------------------
function setMapInfo(sText) {

	if (oMapInfoDiv != null) {
		oMapInfoDiv.innerHTML = sText;
	}
}

//-------------------------------------
// Append Text to the Debug Div
//-------------------------------------
function dbgPrint(sText) {

	if (oDebugDiv != null) {
		oDebugDiv.innerHTML = oDebugDiv.innerHTML + sText + "<br>";
	}
}

//-------------------------------------
// Clear the Debug Div
//-------------------------------------
function dbgClear() {

	if (oDebugDiv != null) {
		oDebugDiv.style.display	= "block";
		oDebugDiv.innerHTML		= "";
	}
}

//--------------------------------------
// Find the top XY position of a (nested) element
//--------------------------------------
function getElementLocation(oElement) {
var oTmp	= oElement;
var iElmX	= 0;
var iElmY	= 0;

	if (oTmp.offsetParent) {
		while (1) {
			iElmX += oTmp.offsetLeft;
			iElmY += oTmp.offsetTop;
			if (!oTmp.offsetParent) {
				break;
			}
			oTmp = oTmp.offsetParent;
		}
	} else {
		iElmX += oTmp.x;
		iElmY += oTmp.y;
	}

	return {x:iElmX, y:iElmY};
}

//--------------------------------------
// Hides the Status Text
//--------------------------------------
function hideStatusText() {

	if ((oMapDiv != null) && (oStatusWindow != null)) {
		oStatusWindow.style.display	= "none";
		oStatusWindow.innerHTML		= "";
	}
}

//--------------------------------------
// Displays the Status Message
//--------------------------------------
function showStatusText(sText) {
var iMapTop,isl,ist;

	if ((oMapDiv != null) && (oStatusWindow != null)) {

		iMapTop = getElementLocation(oMapDiv);
		isl		= iMapTop.x + ((760 - 300) / 2);
		ist		= iMapTop.y + ((480 - 50) / 2);
	
		oStatusWindow.style.display	= "block";
		oStatusWindow.innerHTML		= sText;
		oStatusWindow.style.left	= isl + "px";
		oStatusWindow.style.top		= ist + "px";
	}
}

//-------------------------------------
// Get the current map bounds, center
// and SouthWest/NorthEast corners
//-------------------------------------
function getMapBounds() {

	oMapCenter	= oGMap.getCenter();
	oMapBounds	= oGMap.getBounds();
	oMapSW = oGMap.fromContainerPixelToLatLng(new GPoint(0,iMapHeight));
	oMapNE = oGMap.fromContainerPixelToLatLng(new GPoint(iMapWidth,0));
}

//-------------------------------------
// Checks if a Map Cluster intersects with the current viewport
//-------------------------------------
function checkBounds(oCluster) {
var dCluBottom,dCluLeft,dCluTop,dCluRight;
var dMapBottom,dMapLeft,dMapTop,dMapRight;
var clat2,clng2;

	clat2 = oCluster.dLatHeight / 2;
	clng2 = oCluster.dLngWidth  / 2;

	// Normalize Lat/Lng values
	dCluBottom	= oCluster.oCenter.lat() +  90 - clat2;
	dCluLeft	= oCluster.oCenter.lng() + 180 - clng2;
	dCluTop		= oCluster.oCenter.lat() +  90 + clat2;
	dCluRight	= oCluster.oCenter.lng() + 180 + clng2;
	dMapBottom	= oMapSW.lat() +  90;
	dMapLeft	= oMapSW.lng() + 180;
	dMapTop		= oMapNE.lat() +  90;
	dMapRight	= oMapNE.lng() + 180;

	if (dCluTop <= dMapBottom) { return false; }
	if (dCluBottom >= dMapTop) { return false; }

	// Check for dateline
	if (dMapLeft > dMapRight) {
		if ((dCluRight <= dMapLeft) && (dCluLeft >= dMapRight)) { return false; }
	} else {
		if (dCluRight <= dMapLeft) { return false; }
		if (dCluLeft >= dMapRight) { return false; }
	}

	return true;
}

//-------------------------------------
// Checks if a GLatLng is within the current viewport
//-------------------------------------
function checkLocation(oLatLng) {
var dLat,dLng;
var dMapBottom,dMapLeft,dMapTop,dMapRight;

	// Normalize Lat/Lng values
	dLat		= oLatLng.lat() +  90;
	dLng		= oLatLng.lng() + 180;
	dMapBottom	= oMapSW.lat() +  90;
	dMapLeft	= oMapSW.lng() + 180;
	dMapTop		= oMapNE.lat() +  90;
	dMapRight	= oMapNE.lng() + 180;

	if (dLat <= dMapBottom) { return false; }
	if (dLat >= dMapTop) { return false; }

	// Check for dateline
	if (dMapLeft > dMapRight) {
		if ((dLng <= dMapLeft) && (dLng >= dMapRight)) { return false; }
	} else {
		if (dLng <= dMapLeft) { return false; }
		if (dLng >= dMapRight) { return false; }
	}

	return true;
}

//--------------------------------------
// Takes a temperature in F and formats
// a string representation. This assumes
// 3276.7 as a dash-value. If fBoth is true,
// the metric temp will be appended.
//--------------------------------------
function formatTemp(inTemp,fBoth) {
var ste = "n/a";

	if (inTemp != 3276.7) {
		ste = "" + parseInt(inTemp) + "F";
		if (fBoth) { ste += " (" + parseInt((5/9)*(inTemp-32)) + "C)"; }
	}

	return ste;
}

//--------------------------------------
// Creates a GMarker object
//--------------------------------------
function makeStationMarker(oCenter,sImg,sDID,sTitle) {
var i2,oIcon,oMark;

	// Create the Station Icon using the default icon size
	i2 = parseInt(iIconSize / 2);

	oIcon = new GIcon();
	oIcon.image				= sImg;
	oIcon.shadow			= "";
	oIcon.iconSize			= new GSize(iIconSize, iIconSize);
	oIcon.shadowSize		= new GSize(0, 0);
	oIcon.iconAnchor		= new GPoint(i2, i2);
	oIcon.infoWindowAnchor	= new GPoint(i2, i2);

	oMark = new GMarker(oCenter, {title: sTitle, icon: oIcon} );

	GEvent.addListener(oMark, "click", function() {
		oInfoWindowLoc = oCenter;
		ajaxSendRequest("/mapgetdata.php?DID=" + sDID);
	});

	return oMark;
}

//--------------------------------------
// Clears all Map Markers and resets the visibility
// in the Cluster Marker array
//--------------------------------------
function clearMap() {
var n,i;

	oGMap.clearOverlays();	// Remove all map overlays
	
	for (n=0; n<oActiveClusters.length; n++) {
		i = oActiveClusters[n];
		oClusterArray[i].isOnMap = 0;
	}
}

//--------------------------------------
// Takes a temperature in F and finds the colored
// icon corresponding to the temperature.
// If not found, the icon name 'na.png' is returned.
//--------------------------------------
function getIconImageName(inTemp) {
var sTemp		= "/images/map/na.png";
var iImgName	= -1;
var iTemp		= inTemp;

	// Check for dashed values
	if (iTemp != 3276.7) {

		// Normalize the temp value, supported range is from -10 to 110
		iTemp += 10;
		
		iImgName = parseInt((iTemp - 1) / 10) + 1;
		
		// Double check range values
		if (iImgName < 0)  { iImgName = 0; }
		if (iImgName > 12) { iImgName = 12; }
		
		//if ((iImgName > -1) && (iImgName < 13)) {
			sTemp = "/images/map/" + iImgName + ".png";
		//}
	}

	return sTemp;
}


