/**
 * @author marast
 */
var map;
var geocoder; 

function initGMap(divId) 
{
  if (GBrowserIsCompatible()) 
  {
    var opts = 
    { 
	resultList : G_GOOGLEBAR_RESULT_LIST_SUPPRESS, 
	suppressInitialResultSelection : true, 
	showOnLoad: true
  	};
    if(!divId){
        divId = "map_div";
    }
    map = new GMap2(document.getElementById(divId), {googleBarOptions: opts});
    map.addControl(new GSmallMapControl());
     map.addControl(new GMapTypeControl());
  }
  
} // initGMap()

/*
	address:    String
	callbackFn: function(response)
*/
function getAddressLatLang(address, callbackFn)
{
	//alert('Lat lang address for '+address);
	if (!geocoder) {
		geocoder = new GClientGeocoder();
		//geocoder.setCache(null);
	}
	
	if (geocoder)
	{
		//geocoder.setCache(null);
		//if(geocoder.getCache())
		//	geocoder.getCache().reset();
		//	
		//geocoder.setCache(null);
		geocoder.getLocations(address, callbackFn);
		//geocoder.getLatLng(address, callbackFn);
	}

} // getAddressLatLang()
	
function zoomToFit(addrArray) 
{
	pointCount = 0;
	var bounds = new GLatLngBounds();
	
	for (var i = 0; i < addrArray.length; i++) 
	{
		if (addrArray[i].point != undefined && addrArray[i].point != "")
		{
			bounds.extend(addrArray[i].point);
  			pointCount++;
  		}
	}
	
	if (pointCount > 1)
	{
		map.setZoom(map.getBoundsZoomLevel(bounds));
		map.setCenter(bounds.getCenter());
	}
	
	
} // zoomToFit()
	
function zoomToFitButton(addrArray) 
{
	pointCount = 0;
	var bounds = new GLatLngBounds();
	
	for (var i = 0; i < addrArray.length; i++) 
	{
		if (addrArray[i].point != undefined && addrArray[i].point != "")
		{
			bounds.extend(addrArray[i].point);
  			pointCount++;
  		}
	}
	
	if (pointCount > 0)
	{
		map.setZoom(map.getBoundsZoomLevel(bounds));
		map.setCenter(bounds.getCenter());
	}
	
	
} // zoomToFitButton()
    
/* ext-js Window handle */
var win;

/* Array if Academy Detail i.e. addresses */
var addressesToMap = [];

/* How many times map callback was called */
var callBackCount = 0;

/* How many addresses are we loading in this iteration */
var addressesToLoad = 0;

function logMessage(str, append){
	var debugDiv = document.getElementById("debug_div");
	
	if (debugDiv) {	
		if (append != undefined && append == false) {
			debugDiv.innerHTML = str
		}
		else 
			debugDiv.innerHTML += str;
		debugDiv.innerHTML += "<br />";
	}
}

/* Returns indices from addressesToMap[] which match
 * given 'address'
 */
function getAddressIndices(address)
{
	var i = 0;
	var retIndices = [];

	for (i = 0; i < addressesToMap.length; i++)
	{
		//alert(addressesToMap[i].toJSONString());
			if (addressesToMap[i].address == address)
			retIndices.push(i);
		//if(addressesToMap[i].address.id==address.id){
			//retIndices.push(addressesToMap[i].id);
		//}
		
		
	} // for

	return retIndices;

} // getAddressIndices()

/* Callback for Google GeoCoding API */
function gmapCallbackFn(response)
{
	  callBackCount++; // Count how many times callback is called.

	  if (!response)
	  {
	  	logMessage('Got null response');
	  	return;
	  }

	  if (response.Status.code != 200)
	  {
	  	logMessage(response.name + ' Code ' + response.Status.code + ' Error Returned');
	  	return;
  	  }

	  // Retrieve the object
      var place = response.Placemark[0];

      // Retrieve the latitude and longitude
      var point = new GLatLng(place.Point.coordinates[1],
                              place.Point.coordinates[0]);

      // Center the map on this point
      map.setCenter(point, 13);

      var addrIndices = getAddressIndices(response.name);
      
     //  var addrIndices getAddressId(response.name)

	  /* Update lat/lang of matching addresses
	   * There could be multiple matches as we may have
	   * removed addr1, addr2 etc. to map address at broader
	   * level and that could make multiple addresses have same
	   * state, city or country
	   */
      var i = 0;
      for (i = 0; i < addrIndices.length; i++)
     	 addressesToMap[addrIndices[i]].point = point;

	  var markerIcon = new GIcon(G_DEFAULT_ICON);
	  markerIcon.image = "/cnamsassets/images/locators/markers/marker" + (getAddressId(addrIndices[0]) + 1) + ".png";

      // Set up our GMarkerOptions object
	  markerOptions = { icon:markerIcon };

	  // Create a marker
      var marker = new GMarker(point, markerOptions);
		
      // Add the marker to map
      map.addOverlay(marker);

      // Add address information to marker
      GEvent.addListener(marker, "click", function() {
	         marker.openInfoWindowHtml(place.address);
	            });

} // gmapCallbackFn()

/* Wait till all the callbacks for 'addressesToLoad'
 * are invoked.
 *
 */
function waitForMapToLoad()
{
	if (callBackCount != addressesToLoad)
		setTimeout(waitForMapToLoad, 500);
	else
	{
		/* All Callbacks have been called
		 * but some addresses could be still not mapped.
		 */
		checkForMissingAddresses();
	}

} // waitForMapToLoad()

function checkForMissingAddresses()
{
	var i = 0;
	var missingCount = 0;
	for (i = 0; i < addressesToMap.length; i++)
	{
		var acadDetail = addressesToMap[i];
		if (acadDetail.point == undefined)
		{
			//logMessage(acadDetail.address + " is not yet mapped");

			/* Try to map address at broader level
			 * by removing addr1, addr2, city, state and zip
			 * in that order
			 */

			if (isDefined(acadDetail.addr1))
				acadDetail.addr1 = undefined;
			else if (isDefined(acadDetail.addr2))
				acadDetail.addr2 = undefined;
			else if (isDefined(acadDetail.zip))
				acadDetail.zip = undefined;
			else if (isDefined(acadDetail.city))
				acadDetail.city = undefined;
			else if (isDefined(acadDetail.state))
				acadDetail.state = undefined;
			else
			{
				// Address cannot be mapped by country name also, so give up
				logMessage("Giving up on " + acadDetail.country);

				/* set acadDetail.point to something else that undefined
				 * so that it wont be counted as missing address
				 */
				acadDetail.point = "";
				missingCount--; // Dont count as being not mapped this address.
			}

			missingCount++;
		}

	} // for

	if (missingCount > 0)
	{
		mapAddresses();
	}
	else
	{
		zoomToFit(addressesToMap);
		map.addControl(new ZoomToFitControl(addressesToMap));
	}

} // checkForMissingAddresses()

function isDefined(addrElem)
{
	return (addrElem != undefined && addrElem != '' && addrElem != 'null');
} // isDefined()

function makeAddress(acadDetail)
{
	var address = '';
	
	address += (!isDefined(acadDetail.addr1)  ? '' : (acadDetail.addr1 + ','));
	address += (!isDefined(acadDetail.addr2)  ? '' : (acadDetail.addr2 + ','));
	address += (!isDefined(acadDetail.city)  ? '' : (acadDetail.city + ','));
	address += (!isDefined(acadDetail.state)  ? '' : (acadDetail.state + ','));
	address += (!isDefined(acadDetail.zip)  ? '' : (acadDetail.zip + ','));
	address += (!isDefined(acadDetail.country)  ? '' : acadDetail.country);
	return address;

} // makeAddress()

function pause(millis)
{
	var date = new Date();
	var curDate = null;

	do { curDate = new Date(); }
	while(curDate-date < millis);

} // pause()

/* mapAddresses: Map addresses in 'addressesToMap' whose 'point'
 * is still undefined
 */
function mapAddresses()
{
	addressesToLoad = 0;
	callBackCount = 0;
	var i = 0;
	map.clearOverlays();
	for (i = 0; i < addressesToMap.length; i++)
	{
		var acadDetail = addressesToMap[i];

		//if (acadDetail.point == undefined)
		{
			var address = makeAddress(acadDetail);
			acadDetail.address = address;
			logMessage("Trying to map " + address);

			getAddressLatLang(address, gmapCallbackFn);
			addressesToLoad++;

			// some delay to avoid Google 620 (Too Many requests) error.
			pause(200);

		}

	} // for i

	waitForMapToLoad();

} // mapAddresses()


function showAddresses()
{
	
	mapAddresses();
/*
	var screenWidth=screen.width;
	var screenHeight=screen.height;
	if(!win)
	{
				win = new Ext.Window({
					contentEl: 'map_div',
					layout:'fit',
					width:Math.floor(9*screenWidth/20),
					height:Math.floor(screenHeight/3),
					closeAction:'hide',
					plain: true,
					x:Math.floor(screenWidth/2),
					y:Math.floor(3*screenHeight/10)
					//,title: 'Map All'
				});
	}
	win.show();
*/
} // showAddresses()


/*
 * @Author: Mayank
 * This function defines the structure for address used for the google map.
 */
function Address(){
	this.id = "";
	this.addr1 = "";
	this.addr2 = "";
	this.city = "";
	this.state = "";
	this.zip = "";
	this.country = "";

	// populates the address object 
	this.populateData = function(id, addr1, addr2, city, state, zip, country){
		this.id = id;
		this.addr1 = addr1;
		this.addr2 = addr2;
		this.city = city;
		this.state = state;
		this.zip = zip;
		this.country = country;
		return this;
	}
	
	this.toJSONString = function()
	{
		return YAHOO.lang.JSON.stringify(this);
	}
}

function getAddressId(index){
	//alert(addressesToMap.length);
	//alert(addressesToMap[index].toJSONString());
	return (addressesToMap[index].id);
}
// We define the function first
    function ZoomToFitControl() {
    }
    
    // To "subclass" the GControl, we set the prototype object to
    // an instance of the GControl object
    ZoomToFitControl.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.
    ZoomToFitControl.prototype.initialize = function(map) {
      var container = document.createElement("div");
    
      var fitToZoomButton = document.createElement("button");
      this.setButtonStyle_(fitToZoomButton);
      container.appendChild(fitToZoomButton);
      var text = document.createTextNode('Zoom To Fit');
      fitToZoomButton.appendChild(text);

      GEvent.addDomListener(fitToZoomButton, "click", function() {
        zoomToFitButton(addressesToMap);
      });
    
      map.getContainer().appendChild(container);
      return container;
    }
    
    // By default, the control will appear in the top left corner of the
    // map with 7 pixels of padding.
    ZoomToFitControl.prototype.getDefaultPosition = function() {
       if(navigator.appName == "Microsoft Internet Explorer")
		{
			return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(252, 7));
		}
		else
		{
			return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(206, 7));
		}
      
    }
    
    // Sets the proper CSS for the given button element.
    ZoomToFitControl.prototype.setButtonStyle_ = function(button) {
      //button.style.textDecoration = "underline";
      button.style.color = "#000000";
      button.style.backgroundColor = "white";
      button.style.fontFamily = "Arial,sans-serif";
      button.style.border = "1px black solid";
      button.style.borderColor="black";
     // button.style.position="absolute";
     // button.style.padding = "2px";
     button.style.marginBottom = "20px";
     // button.style.marginLeft = "200px";
      //button.style.textAlign = "center";
      button.style.width = "8em";
       button.style.height = "19px";
      button.style.fontSize = "12px";
      button.style.cursor = "pointer";
}

function closeMap() {
	try {
		if(win)
		{
			win.hide();	
		}	
	}
	catch(e){alert(e);}
}