// JavaScript Document

// GControl for changing map types (my own version so I can popup progress messages)

// users of this code may define their own 'showMapChangingMessage()' method. 

var visible_controls = '';

function MyOwnMapTypesControl(controls, oTheMap, oTopoCustomMap, oOpenStreet1CustomMap, oOpenStreet2CustomMap)
{
	if ((controls == null) || (controls == ''))
	   visible_controls = 'hwy sat hyb topo ter';
	else
	   visible_controls = controls;
	
	
	this.moMessageDiv = null; // for popping up status messages.
	this.mbMapLoading = false;
	this.mbMapLoadingDialogShowing = false;
	this.moMessageDivOnClickHandler;
	this.moLastCenterPoint;
	this.moLastZoom;
	this.miMapTilesLoadedEventCount = 0;
	
	// define variables that reference the google map object
	// and for the custom topographical map layer.
	// provide backwards-compatibility with older style of usage
	// that assumed the global variables 'map' and 'topocustommap'.
	
	this.moTheMap;   
	this.moTopoCustomMap;
	
	if (oTheMap)
	{
		this.moTheMap = oTheMap;
		this.moTopoCustomMap = oTopoCustomMap;
		this.moOpenStreet1CustomMap = oOpenStreet1CustomMap;
		this.moOpenStreet2CustomMap = oOpenStreet2CustomMap;
	}
	else
	{
		this.moTheMap = map;
		this.moTopoCustomMap = topocustommap;
	}
}

MyOwnMapTypesControl.prototype = new GControl();

// Creates a one DIV for each of the buttons and places them in a container
// DIV which is returned as our control element. We add the control to
// to the map container and return the element for the map class to
// position properly.
MyOwnMapTypesControl.prototype.initialize = function(map) {
	
  var oThis = this;
   
  var container = document.createElement("div");

  var button1;
  var button2;
  var button3;
  var button4;
  var button5;
  var button6;
  var button7;
  
  if (visible_controls.search(/hwy/) != -1)
  {
	  var button1Div = document.createElement("div");
	  this.setButtonStyle_(button1Div);
	  container.appendChild(button1Div);
	  
	  button1 = document.createTextNode("Highway");
	  
	  button1Div.appendChild(button1);
	  GEvent.addDomListener(button1Div, "click", function() 
	  {
		 
		  
		if (button1Div.style.fontWeight != "bold")
		{
			button1Div.style.fontWeight = "bold";
			
			if (button2Div != null)
			   button2Div.style.fontWeight = "normal";
			 
			if (button3Div != null) 
			   button3Div.style.fontWeight = "normal";
			
			if (button4Div != null)
			   button4Div.style.fontWeight = "normal";
			
			if (button5Div != null)
			   button5Div.style.fontWeight = "normal";
			
			if (button6Div != null)
			   button6Div.style.fontWeight = "normal";
			   
			if (button7Div != null)
			   button7Div.style.fontWeight = "normal";
			   
			setTimeout( function() { oThis.changeMapType(G_NORMAL_MAP) } , 75);
		}
		//map.setMapType(G_NORMAL_MAP);
	  });
  }
  
  
  if (visible_controls.search(/sat/) != -1)
  {
	  var button2Div = document.createElement("div");
	  this.setButtonStyle_(button2Div);
	  container.appendChild(button2Div);
	  
	  button2 = document.createTextNode("Satellite");
	  
	
		
	  button2Div.appendChild(button2);
	  GEvent.addDomListener(button2Div, "click", function() 
	  {
		if (button2Div.style.fontWeight != "bold")
		{
			button2Div.style.fontWeight = "bold";
	
			if (button1Div != null)
			   button1Div.style.fontWeight = "normal";
			 
			if (button3Div != null) 
			   button3Div.style.fontWeight = "normal";
			
			if (button4Div != null)
			   button4Div.style.fontWeight = "normal";
			
			if (button5Div != null)
			   button5Div.style.fontWeight = "normal";
			   
			if (button6Div != null)
			   button6Div.style.fontWeight = "normal";
			   
			if (button7Div != null)
			   button7Div.style.fontWeight = "normal";
			   
			setTimeout( function() { oThis.changeMapType(G_SATELLITE_MAP) } , 75);
			
		}
	  });
  }
  
  if (visible_controls.search(/hyb/) != -1)
  {
	  var button3Div = document.createElement("div");
	  this.setButtonStyle_(button3Div);
	  container.appendChild(button3Div);
	  
	  button3 = document.createTextNode("Hwy & Sat");
	  
	  button3Div.appendChild(button3);
	  GEvent.addDomListener(button3Div, "click", function() 
	  {
		if (button3Div.style.fontWeight != "bold")
		{
			button3Div.style.fontWeight = "bold";
			
			if (button1Div != null)
			   button1Div.style.fontWeight = "normal";
			 
			if (button2Div != null) 
			   button2Div.style.fontWeight = "normal";
			
			if (button4Div != null)
			   button4Div.style.fontWeight = "normal";
			
			if (button5Div != null)
			   button5Div.style.fontWeight = "normal";

			if (button6Div != null)
			   button6Div.style.fontWeight = "normal";
			   
			if (button7Div != null)
			   button7Div.style.fontWeight = "normal";
			   
			setTimeout( function() { oThis.changeMapType(G_HYBRID_MAP) } , 75);
		}
	  });
  }
  
  if (visible_controls.search(/topo/) != -1)
  {
	  var button4Div = document.createElement("div");
	  this.setButtonStyle_(button4Div);
	  container.appendChild(button4Div);
	  
	  button4 = document.createTextNode("Topographic");
	  
	  button4Div.appendChild(button4);
	  GEvent.addDomListener(button4Div, "click", function() 
	  {
		if (button4Div.style.fontWeight != "bold")
		{
			button4Div.style.fontWeight = "bold";
	
			if (button1Div != null)
			   button1Div.style.fontWeight = "normal";
			 
			if (button2Div != null) 
			   button2Div.style.fontWeight = "normal";
			
			if (button3Div != null)
			   button3Div.style.fontWeight = "normal";
			
			if (button5Div != null)
			   button5Div.style.fontWeight = "normal";
			   
			if (button6Div != null)
			   button6Div.style.fontWeight = "normal";
			   
			if (button7Div != null)
			   button7Div.style.fontWeight = "normal";
			
			setTimeout( function() { oThis.changeMapType(oThis.moTopoCustomMap) } , 75);
		}
	  });
  }
  
  if (visible_controls.search(/ter/) != -1)
  {
	  var button5Div = document.createElement("div");
	  this.setButtonStyle_(button5Div);
	  container.appendChild(button5Div);
	  
	  button5 = document.createTextNode("3D Terrain");
	  
	  button5Div.appendChild(button5);
	  GEvent.addDomListener(button5Div, "click", function() 
	  {
		if (button5Div.style.fontWeight != "bold")
		{
			button5Div.style.fontWeight = "bold";
			
			if (button1Div != null)
			   button1Div.style.fontWeight = "normal";
			 
			if (button2Div != null) 
			   button2Div.style.fontWeight = "normal";
			
			if (button3Div != null)
			   button3Div.style.fontWeight = "normal";
			
			if (button4Div != null)
			   button4Div.style.fontWeight = "normal";
			   
			if (button6Div != null)
			   button6Div.style.fontWeight = "normal";
			   
			if (button7Div != null)
			   button7Div.style.fontWeight = "normal";
			   
			setTimeout( function() { oThis.changeMapType(G_PHYSICAL_MAP) } , 75);		
		}
	  });
  }
  
  if (visible_controls.search(/os1/) != -1)
  {
	  var button6Div = document.createElement("div");
	  this.setButtonStyle_(button6Div);
	  container.appendChild(button6Div);
	  
	  button6 = document.createTextNode("OS1");
	  
	  button6Div.appendChild(button6);
	  GEvent.addDomListener(button6Div, "click", function() 
	  {
		if (button6Div.style.fontWeight != "bold")
		{
			button6Div.style.fontWeight = "bold";
	
			if (button1Div != null)
			   button1Div.style.fontWeight = "normal";
			 
			if (button2Div != null) 
			   button2Div.style.fontWeight = "normal";
			
			if (button3Div != null)
			   button3Div.style.fontWeight = "normal";
			
			if (button4Div != null)
			   button4Div.style.fontWeight = "normal";
			   
			if (button5Div != null)
			   button5Div.style.fontWeight = "normal";
			   
			if (button7Div != null)
			   button7Div.style.fontWeight = "normal";
			
			setTimeout( function() { oThis.changeMapType(oThis.moOpenStreet1CustomMap) } , 75);
		}
	  });
  }
  
    if (visible_controls.search(/os2/) != -1)
  {
	  var button7Div = document.createElement("div");
	  this.setButtonStyle_(button7Div);
	  container.appendChild(button7Div);
	  
	  button7 = document.createTextNode("OS2");
	  
	  button7Div.appendChild(button7);
	  GEvent.addDomListener(button7Div, "click", function() 
	  {
		if (button7Div.style.fontWeight != "bold")
		{
			button7Div.style.fontWeight = "bold";
	
			if (button1Div != null)
			   button1Div.style.fontWeight = "normal";
			 
			if (button2Div != null) 
			   button2Div.style.fontWeight = "normal";
			
			if (button3Div != null)
			   button3Div.style.fontWeight = "normal";
			
			if (button4Div != null)
			   button4Div.style.fontWeight = "normal";
			   
			if (button5Div != null)
			   button5Div.style.fontWeight = "normal";
			   
			if (button6Div != null)
			   button6Div.style.fontWeight = "normal";
			
			setTimeout( function() { oThis.changeMapType(oThis.moOpenStreet2CustomMap) } , 75);
		}
	  });
  }
  
  var currentMapType = this.moTheMap.getCurrentMapType();
  
  if (visible_controls.search(/hwy/) != -1)
  {
	  if (currentMapType == G_NORMAL_MAP) // G_MAP_TYPE)
		 button1Div.style.fontWeight = "bold";
  }
	 
  if (visible_controls.search(/sat/) != -1)
  {  
	  if (currentMapType == G_SATELLITE_MAP) // G_SATELLITE_TYPE)
		 button2Div.style.fontWeight = "bold";
  }
  
  if (visible_controls.search(/hyb/) != -1)
  {
	  if (currentMapType == G_HYBRID_MAP) // G_HYBRID_TYPE)
		 button3Div.style.fontWeight = "bold";
  }

  if (visible_controls.search(/topo/) != -1)
  {
	  if (currentMapType == this.moTopoCustomMap)
		 button4Div.style.fontWeight = "bold"; 
  }
  
  if (visible_controls.search(/ter/) != -1)
  {
	  if (currentMapType == G_PHYSICAL_MAP)
		 button5Div.style.fontWeight = "bold"; 
  }

  if (visible_controls.search(/os1/) != -1)
  {
	  if (currentMapType == this.moOpenStreet1CustomMap)
		 button6Div.style.fontWeight = "bold"; 
  }
  
  if (visible_controls.search(/os2/) != -1)
  {
	  if (currentMapType == this.moOpenStreet2CustomMap)
		 button7Div.style.fontWeight = "bold"; 
  }
  
  this.moTheMap.getContainer().appendChild(container);
  this.moLastCenterPoint = this.moTheMap.getCenter();
  this.moLastZoom = this.moTheMap.getZoom();
  
  GEvent.addListener(this.moTheMap, "tilesloaded", function() { oThis.mapTilesLoaded() } );
  
  GEvent.addListener(this.moTheMap, "moveend", function() { oThis.potentiallyShowMapLoadingMessage(); } );
  
  GEvent.addListener(this.moTheMap, "movestart", function() { 
															 
														  oThis.miMapTilesLoadedEventCount = 0; 
														  
														  } );
  
  return container;
}

// By default, the control will appear in the top left corner of the
// map with 7 pixels of padding.
MyOwnMapTypesControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 7));
}

// Sets the proper CSS for the given button element.
MyOwnMapTypesControl.prototype.setButtonStyle_ = function(button) {
  button.style.color = "#000000";
  button.style.backgroundColor = "white";
  button.style.font = "small Arial";
  button.style.border = "1px solid black";
  button.style.padding = "2px";
  button.style.marginBottom = "3px";
  button.style.textAlign = "center";
  button.style.width = "6em";
  button.style.cursor = "pointer";
}

MyOwnMapTypesControl.prototype.potentiallyShowMapLoadingMessage = function()
{
	var oThis = this;
	
	if (typeof dojo != "undefined")
	{
		var oCurrentCenterPoint = oThis.moTheMap.getCenter();
		var oCurrentZoom = oThis.moTheMap.getZoom();

	    var iDistanceScrolledInMetres = oCurrentCenterPoint.distanceFrom(oThis.moLastCenterPoint);	
        console.log("Current Zoom is " + oCurrentZoom);
		
		var fThreshold = Math.pow((19 - oCurrentZoom), 2.3) * 100;
		console.log("Threshold is " + fThreshold);
		console.log("Distance from last center point to this center point : " + iDistanceScrolledInMetres + " metres");
		
		oThis.moLastCenterPoint = oCurrentCenterPoint;
		
		// if we've moved only a little bit, then don't risk loading the loading dialog, because
		// in the situation of moving a little bit, we usually don't get a tilesloadedevent -- and then
		// we're screwed because we won't know to pop down the dialog and it'll get stuck up.
		// for changes in zoom, we're ok - tilesloaded always seems to get fired when zooming.
		if ( (iDistanceScrolledInMetres > fThreshold) || (oCurrentZoom != oThis.moLastZoom) || (iDistanceScrolledInMetres == 0) )
		{
			// if there have been no map tiles loaded event between the 
			// time that we 
	
			console.log("Potentially show map loading message.  Wait 1 second, then do the pop-up");
			
		   setTimeout( function() { oThis.showMapChangingMessage() } , 999);
		
		   this.mbMapLoading = true;
		
			
			console.log("Starting to load map.  Start timer for loading dialog...");
		}
		else
		{
			console.log("Didn't move by enough to be safe enough to be sure to avoid missing tiles loaded.  skip loading dialog.");
		}
		
		oThis.moLastZoom = oCurrentZoom;
	}
}

MyOwnMapTypesControl.prototype.changeMapType = function(oMapType)
{
	
	this.potentiallyShowMapLoadingMessage();

	this.moTheMap.setMapType(oMapType);
}


//notused

function changeMapType(map, maptype) 
{
   return (function()
   {
      map.setMapType(maptype);
   });
}




MyOwnMapTypesControl.prototype.showMapChangingMessage = function()
{
	var oThis = this;
	
	// if the map is still loading by the time we run this function, then
	// pop up a loading... dialog.
	
	// if we've received tiles loaded events in the intervening time
	// between starting the map pop up timer and now, short circuit and stop.
	if (oThis.miMapTilesLoadedEventCount > 0)
	{
		console.log("showMapChangingMessage().  There were " + oThis.miMapTilesLoadedEventCount + " tiles loaded events between the time we called potentiallyShowMapLoadingMessage() and now.  Stop the dialog pop-up.");
		this.mbMapLoading = false;
		oThis.miMapTilesLoadedEventCount =0;
		return;
	}
	
    if (this.mbMapLoading  == true)
	{
	    console.log("Enough time has passed.  map still loading, pop up dialog.");
		
	    var oMapCoords = dojo.position(this.moTheMap.getContainer(), true);
		//console.log("map coords:");
		//console.dir(oMapCoords);

		if (this.moMessageDiv == null)
		{
			console.log("first time through, message div is null - creating...");
			
			this.moMessageDiv = dojo.create("div");
			
			this.moMessageDiv.innerHTML ='<div class="map_tiles_loading_div_inner_large"><img src="/Images/ajax-loader-small-88a5e1.gif"><br>Loading Map Tiles....</div><div class="map_tiles_loading_div_inner_small">(click to hide)</div>';
			
				// style the div
			dojo.style(this.moMessageDiv,
					   {
						   position: "absolute",
						   visibility: "visible"
					   }
					  );
			
			dojo.addClass(this.moMessageDiv, "map_tiles_loading_div");
			

			
			// user can pop down the loading dialog at any time.
		    this.moMessageDivOnClickHandler = dojo.connect(this.moMessageDiv, "onclick", function(e) { oThis.removeMapChangingMessage(); } );
		}
		else
		{
			console.log("second or more times through, message div is not null - using existing message dialog");
		}
		
		// place the div relative to the body
		dojo.place(this.moMessageDiv, this.moTheMap.getContainer());
			
		var oMessageCoords = dojo.position(this.moMessageDiv, true);
		//console.log("message dialog co-ords:");
		///console.dir(oMessageCoords);
		
		var iMessageDialogTopX  =  ( (oMapCoords.w/2) - (oMessageCoords.w/2) );
		var iMessageDialogTopY  =  ( (oMapCoords.h/2) - (oMessageCoords.h/2) );
		
		//console.log("message dialog top x = " + iMessageDialogTopX);
		//console.log("message dialog top y = " + iMessageDialogTopY);
		
		// now that we know all the coords we need, properly center the message.
		dojo.style(this.moMessageDiv,
				   {
					   left: iMessageDialogTopX + "px",
					   top: iMessageDialogTopY + "px",
					   opacity: "0.0"
				   }
				  );
		dojo.fadeIn({node:this.moMessageDiv, duration:500}).play();
		
		this.mbMapLoadingDialogShowing = true;
		

		
        
	}
	
}

MyOwnMapTypesControl.prototype.removeMapChangingMessage = function()
{
   this.mbMapLoading = false;
	
	console.log("removeMapChangingMessage()...");
	
   if (this.mbMapLoadingDialogShowing == true)
   {
	   console.log("this.mbMapLoadingDialogShowing is true.  Closing dialog...");
	   
	   this.mbMapLoadingDialogShowing = false;
	   
	   if (this.moMessageDiv != null)
	   {
		   console.log("just before performing fade out of dialog");
	   dojo.fadeOut({node:this.moMessageDiv, duration:500}).play();
	   
	   var oThis = this;
	   // wait 500ms so we don't message up our fade.
	   setTimeout( function() 
			{ 
			   console.log("1000ms after fade out of dialog");
			   
			// hide the dialog, we don't need it anymore (but we'll reuse it later if we need to pop it up again)
			/*
			   dojo.style(this.moMessageDiv,
				   {
					   visibility: "hidden"
				   }
				  );
			  */ 
			   oThis.moMessageDiv.parentNode.removeChild(oThis.moMessageDiv);
			   
			   /* we used to just destroy it.
			   // remove any message dialog that might be up.
			   dojo.disconnect(oThis.moMessageDivOnClickHandler);
			   dojo.destroy(oThis.moMessageDiv);
			   */
			   
			} , 1000);
	   }
   }

}

MyOwnMapTypesControl.prototype.mapTilesLoaded = function()
{
	console.log(">>>>>>>>>>>>>mapTilesLoaded<<<<<<<<<<<<<<");
	
	this.miMapTilesLoadedEventCount++;
	
	if (typeof dojo != "undefined")
	{
		console.log("removing any loading dialog, setting map loading to false.");
		
        this.removeMapChangingMessage();
	}
	
	/*
	//alert('map tiles finished loading');
	var oChildren = this.moTheMap.getContainer().children;
	
	//var oChildren = this.moTrackMapDiv.children; 
	
	//var oInternalMapObject = oChildren[1];
	
	var oClippingDiv = oChildren[0];
	
    var oClippingDivChild = oClippingDiv.children[0];
	
	var oClippingDivChildSecondElement = oClippingDivChild.children[1];
	
	var oMapTilesContainer = oClippingDivChildSecondElement.children[0];

	var oMapTilesArray = oMapTilesContainer.children;
	*/
	/*
	console.log("there are " + oMapTilesArray.length + " map tiles.");
	for (i=0; i < oMapTilesArray.length; i++)
	{
		console.log("map " + i + ": src=" + oMapTilesArray[i].src + ", loaded = " + this.isImageLoaded(oMapTilesArray[i]));
		
	}
	*/
	
	
	
}


MyOwnMapTypesControl.prototype.isImageLoaded = function(img) 
{
    // During the onload event, IE correctly identifies any images
    // that weren't downloaded as not complete. Others should too.
    // Gecko-based browsers act like NS4 in that they report this
    // incorrectly: they always return true.
    if (!img.complete) {
        return false;
    }

    // However, they do have two very useful properties: naturalWidth
    // and naturalHeight. These give the true size of the image. If
    // it failed to load, either of these should be zero.
    if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0) {
        return false;
    }

    // No other way of checking: assume it's ok.
    return true;
}
