
/*
 * Functionality for viewing and navigating a map
 */
function MapView() {
	
    var m_map;         // handle to Google map    
    var m_addrCache;   // save addresses/points so we can center on them later (using panTo)
    var m_layerManager;
    var m_baseIcon;    // base icon to derive custom icons from
    var m_searchControl; // Google maps ajax search
    var m_localSearch;   // Local search 
        
    // Track down and stash a pointer to some key DOM elements
	var m_mapInfo = null;

    var m_resources;
    
    var m_addressList; // HTML Address Table
    var m_layerList; // HTML Layer table
    
    var m_viewMapId = null;
    var m_isReadOnly = false;  
    
	var INDICATOR = "<img align='absbottom' src='images/indicator.gif' width='12' height='12' border='0'>";	      
	
    var MAP_VIEW  = "/mapView.jsp";   
    var KML_VIEW  = "/actionServlet?action=Kml";
    
    var m_format = "";
    
    var m_remoteConnection;    
    
    var m_thisMapper = this;
    var m_showLayerInfoDialog;
    var m_serverName = "http://maptrot.com";

	this.setFormat = function (f) {
		m_format = f;
	}
	
	this.setViewId = function (id) {
		m_viewMapId = id;
		setIsReadOnly(true);
	}
	
	this.setServerName = function (serverName) {
	    m_serverName = serverName;
	}
	
    var windowSize = function () {
		var myWidth = 0, myHeight = 0;
		if( typeof( window.innerWidth ) == 'number' ) {
		    //Non-IE
		    myWidth = window.innerWidth;
		    myHeight = window.innerHeight;
		} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		    //IE 6+ in 'standards compliant mode'
		    myWidth = document.documentElement.clientWidth;
		    myHeight = document.documentElement.clientHeight;
		} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		    //IE 4 compatible
		    myWidth = document.body.clientWidth;
		    myHeight = document.body.clientHeight;
		}
		return {width: myWidth, height: myHeight};
    }
	  
    var fixSizes = function () {
	  	var addressListDiv     = document.getElementById("addressListArea");
	  	var locScrollArea      = document.getElementById("locationScrollDiv");	  	
	  	var layScrollArea      = document.getElementById("layerScrollDiv");	  		  	
	  	var locTabContainerDiv = document.getElementById("locationTabContainer");	  	
		var tabDiv = document.getElementById("dojoTabPaneWrapper");
		var mapData = document.getElementById("mapControls");
		var listTop = mapData.offsetTop + mapData.offsetHeight-15;
		
		var hgtOffset = 70;
        if ("view" == m_format) {
			listTop += 20;
			hgtOffset = 30;
        }				    
        if ("print" == m_format) {
			listTop += 20;        	
        }		
        else if ("embed" == m_format) {
			listTop += 20;
        }		        

		
        var viewport = windowSize();
		var hgt = viewport.height-listTop;
		
		tabDiv.style.height = hgt + "px";	
		var scrollAreaHeightSetting = (hgt-hgtOffset)+"px";
		if (null != locScrollArea) {
			locScrollArea.style.height = scrollAreaHeightSetting;
		}
		if (null != layScrollArea) {		
			layScrollArea.style.height = scrollAreaHeightSetting;		
		}

	    locTabContainerDiv.style.height=hgt+"px";

		
		addressListDiv.style.top= listTop+ "px";			
		addressListDiv.style.height=hgt+"px";		
		
		//tabDiv.style.top= listTop+ "px";					

		var nonMapWidth = 240;
		var nonMapHeight = 73;
		
		if ("view" == m_format) {
			nonMapWidth = 200;
			nonMapHeight = 130;
		}		
		else if ("print" == m_format) {
			nonMapWidth = 190;
			nonMapHeight = 28;						
		}
		else
		if ("embed" == m_format) {
			nonMapWidth = 2;
			nonMapHeight = 2;

			if (navigator.appName.indexOf("Microsoft")!=-1) {
				var agt = navigator.userAgent.toLowerCase();
				if (agt.indexOf("msie 6") != -1) {
					// IE 6 has some problems with the w/h inside a frame, so adjust 
					nonMapHeight= 1;
					nonMapWidth = -15;
				}
			}
		 }			
		
		var w = viewport.width - nonMapWidth;
		var h = viewport.height - nonMapHeight;		

		var mapDiv = document.getElementById("map");
		mapDiv.style.width = w+"px";
		mapDiv.style.height= h+"px";
    }
    
    this.windowInit= function () {
    	fixSizes();
		init();

    }
    
    this.windowResize= function () {
    	fixSizes();
    }
	  
	
	var setIsReadOnly = function (b) {
		m_isReadOnly = b;
	}
	var isReadOnly = function () {
		return m_isReadOnly;
	}
	
	this.getMap = function () {
		return m_map;
	}
	
	this.setMapInfo = function (mapInfo) {
		m_mapInfo = mapInfo;
	}
	
	// Update links to print, email, link
    this.updateMapTools = function () {
		var kmlSpan= document.getElementById("kmlMap");    	    			
		var printSpan= document.getElementById("printMap");    	    			
		var emailSpan= document.getElementById("emailMap");    	    	
		var linkSpan= document.getElementById("linkMap");    	
		var embedSpan= document.getElementById("embedMap");    	
		var diggSpan  = document.getElementById("diggMap");
		var netscapeSpan  = document.getElementById("netscapeMap");		
		var redditSpan  = document.getElementById("redditMap");		
		var deliSpan  = document.getElementById("deliMap");				
		var stumbleSpan  = document.getElementById("stumbleMap");						
		
		var printLink = "";
		var emailLink = "";
		var linkLink = "";			
		var embedLink = "";					
		// Clear all the links, then recreate as needed
		kmlSpan.innerHTML   = m_resources.KML_ICON+m_resources.KML_TEXT;			
		printSpan.innerHTML = m_resources.PRINT_ICON+m_resources.PRINT_TEXT;					
		emailSpan.innerHTML = m_resources.EMAIL_ICON+" "+m_resources.EMAIL_TEXT;			
		linkSpan.innerHTML  = m_resources.LINK_ICON+" "+m_resources.LINK_TEXT;
		diggSpan.innerHTML  = m_resources.DIGG_ICON;
		netscapeSpan.innerHTML  = m_resources.NETSCAPE_ICON;		
		redditSpan.innerHTML  = m_resources.REDDIT_ICON;		
		deliSpan.innerHTML    = m_resources.DELICIOUS_ICON;		
		stumbleSpan.innerHTML = m_resources.STUMBLE_ICON;
		if (null != embedSpan) {
			embedSpan.innerHTML=m_resources.EMBED_ICON+" "+m_resources.EMBED_TEXT;				
		}
		// If there is a good map,  create links for print, email, link
		if (null != m_mapInfo) {

			var userNameInfo = "Created by "+m_mapInfo.getUserName();			
			if (("view" == m_format) || ("embed" == m_format) || ("print" == m_format)) {
				document.getElementById("maptrotInvite").innerHTML = userNameInfo+m_resources.RO_INVITE;				
			}
			
			printSpan.innerHTML = "<a title='Format this map for printing' href='javascript://' onclick='m_mapper.printMap()'>"+m_resources.PRINT_ICON+" "+m_resources.PRINT_TEXT+"</a>";						
			var linkUrl = m_serverName + MAP_VIEW+"?mapId="+m_mapInfo.getId();//+"&format=view";
			var kmlUrl  = m_serverName + KML_VIEW+"&mapId="+m_mapInfo.getId();
			var mapName = escape(m_mapInfo.getName());
			document.title = m_mapInfo.getName();						
	    	if (m_mapInfo.getPublished()) {
	    		if (null != kmlSpan) {
	    			kmlSpan.innerHTML = "<a title='KML for Location Data' href='"+kmlUrl+"' >"+m_resources.KML_ICON+" "+m_resources.KML_TEXT+"</a>";
	    		}
	    	}			
	    	if (m_mapInfo.getShared() || m_mapInfo.getPublished()) {
	    		if (null != emailSpan) {
					emailSpan.innerHTML = "<a title='Send an email with this map' href=mailto:?Subject="+encodeURIComponent("View This Map")+"&body="+encodeURIComponent(linkUrl)+"> "+m_resources.EMAIL_ICON+" "+m_resources.EMAIL_TEXT+"</a>";						    			5403
	    		}
				if (null != linkSpan) {
					linkSpan.innerHTML  = "<a title='Link to map' href='"+linkUrl+"' target='_blank'>"+m_resources.LINK_ICON+" "+m_resources.LINK_TEXT+"</a>";
		    	}
		    	if (null != embedSpan) {
    				embedSpan.innerHTML="<a title='Embed this map in a webpage, blog, etc.  Click here for the html to use' href='javascript://' onclick='m_mapper.embedMap()'>"+m_resources.EMBED_ICON+" "+m_resources.EMBED_TEXT+"</a>";
		    	}
				diggSpan.innerHTML     = "<a title='Digg this map' target='_blank' href='http://digg.com/submit?phase=2&url="+linkUrl+"&title="+mapName+"'>"+m_resources.DIGG_ICON+"</a>";						    	
				netscapeSpan.innerHTML = "<a title='Submit this map to Netscape' target='_blank' href='http://www.netscape.com/submit/?U="+linkUrl+"&T="+mapName+"'>"+m_resources.NETSCAPE_ICON+"</a>";				
				redditSpan.innerHTML   = "<a title='Submit this map to Reddit' target='_blank' href='http://reddit.com/submit?url="+linkUrl+"&title="+mapName+"'>"+m_resources.REDDIT_ICON+"</a>";
				deliSpan.innerHTML     = "<a title='Submit this map to del.icio.us' target='_blank' href='http://del.icio.us/submit?url="+linkUrl+"&title="+mapName+"'>"+m_resources.DELICIOUS_ICON+"</a>";				
				stumbleSpan.innerHTML  = "<a title='Submit this map to StumbleUpon' target='_blank' href='http://stumbleupon.com/submit?url="+linkUrl+"&title="+mapName+"'>"+m_resources.STUMBLE_ICON+"</a>";								
			}
		}
    }

	this.printMap = function () {
		var url = "/newWindow.jsp?jsp=mapView.jsp&mapId="+m_mapInfo.getId()+"&format=print";
		window.open(url,"_blank","location=no,resizable=yes,menubar=yes,scrollbars=auto,toolbar=no,width=670,height=670,dependent=no");		
	}	
	
    var doServletCall = function (action, callback, request, callError, sync) {
      if ((undefined != request) && (null != request)) {
      	request.action = action;
      }
      else {
	    request = {action: action};
      }
      if (undefined == callError) {
      	callError = defaultErrorCallback;
      }
      
      if (undefined == sync) {
      	sync = false;
      }

      m_remoteConnection.connect("/actionServlet", "POST", request, callback, callError);
    }
    

	var defaultErrorCallback= function (error) {
		//console.log("Call error");
		//console.log(error);		
		
	}	
	
	
    // Init the app
    var init = function() {
   
		m_remoteConnection = new XHConn();
		if (!m_remoteConnection) {
			alert("XMLHTTP not available. Try a newer/better browser."); 
			return;
		}
    	
		m_resources = new MaptrotResources();
      
	    // Get the map name and desc elements
		m_addressList = document.getElementById("addressList")
        m_addrCache = new Array();      
        m_layerManager = new ItemManager();
        
        m_layerList   = document.getElementById("layerList")
		m_showLayerInfoDialog = dojo.widget.byId("layerShowDialog");		  			        
        

      // View a map right away (view mode)
	  if (null != m_viewMapId) {
	  	    googleInit();
		  	loadTheMap (m_viewMapId);
		  }
	  // Blank map, show user info
	  else {
		googleInit();	  	
		//alert("no map specified");
	  }
    }
    
    this.setWaitCursor = function () {
		document.body.style.cursor = "wait";		    	
    }
    this.setDefaultCursor = function () {
		document.body.style.cursor = "default";		    	
    }
    
    var loadTheMap= function (mapId) {
    	//console.log("Load:"+mapId);
		var request = {Id: mapId};
		m_thisMapper.setWaitCursor();
        doServletCall ("GetMap", showLoadedMapResult, request);  				
    }
     
	this.clearMap = function () {
      	//clear points
    	m_map.closeInfoWindow();      	
        m_map.setCenter(new GLatLng(35.746512,-95.888672),4);          	
        m_map.clearOverlays();
        m_addrCache = new Array();
        m_layerManager = new ItemManager();
        m_mapInfo = null;
		m_thisMapper.updateMapTools();
	}
    // Things for google maps
    var googleInit = function() 
    {
      if (null != m_map) {
		m_thisMapper.clearMap();
      }
      if (GBrowserIsCompatible()) 
      {
        // Get the map
        m_map = new GMap2(document.getElementById("map"));
        // Crete a geocoder
        m_geocoder = new GClientGeocoder();
        m_geocodeCache = new GGeocodeCache();        
        
	    // Setup the controls
        if ('embed' == m_format) {
	        m_map.addControl(new GSmallMapControl());	        		    
        }
        else if ('print' == m_format) {
	        m_map.addControl(new GSmallMapControl());	    
	        m_map.addControl(new GScaleControl());	        	            		            	
        }
        else {
	        m_map.addControl(new GLargeMapControl());
	        m_map.addControl(new GScaleControl());	        
			m_map.addControl(new GOverviewMapControl());
        }
		m_map.addControl(new GMapTypeControl());        
        m_map.setCenter(new GLatLng(35.746512,-95.888672),4);    
		m_map.enableDoubleClickZoom();
        
        GEvent.addListener(m_map, "moveend", moveEndCallback);
        
        // Create a base icon for all of our markers that specifies the
		// shadow, icon dimensions, etc.
        baseIcon = new GIcon();
        baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
        baseIcon.iconSize = new GSize(20, 34);
        baseIcon.shadowSize = new GSize(37, 34);
        baseIcon.iconAnchor = new GPoint(9, 34);
        baseIcon.infoWindowAnchor = new GPoint(9, 2);
        baseIcon.infoShadowAnchor = new GPoint(18, 25);         
     
     	m_thisMapper.setupLocalSearch();
       }       
	}
	
	var valOrString = function (s) {
		return s ? s : "";
	}
	
	this.getLocations = function () {
		var ret= new Array();
		for (var i=0;i<m_addrCache.length;i++) {
		   var next = m_addrCache[i];
		   if (null == next) {
		   	continue;
		   }
		   ret.push({address: next.address, 
		             url:      valOrString(next.url),
		             urlTitle: valOrString(next.urlTitle),
		             note:     valOrString(next.note),
		             title:    valOrString(next.title),
		             latitude: next.point.lat(), longitude: next.point.lng()});
		}
		return ret; 
	}    	      		
	
	this.getLocation = function (index) {
		return m_addrCache[index];
	}
	
	this.removeLocation = function (index) {
    	m_map.closeInfoWindow();
	    m_map.removeOverlay(m_thisMapper.getLocation(index).marker);

    	m_addressList.deleteRow(getTableRow(index,m_addressList));
    	m_addrCache[index] = null;   // Null out the entry so it doesn't get saved		
	}
		

    // Pan to the address stored in the cache at the index
    this.centerOn = function(index)
    {
      m_map.closeInfoWindow();      
      m_map.panTo(m_addrCache[index].point);
      //m_map.setZoom(13);
      m_addrCache[index].marker.openInfoWindowHtml(m_addrCache[index].markerInfo);
    }
    
    
    var moveEndCallback= function () {
    	if (null != m_localSearch) {
			m_localSearch.setCenterPoint(m_map.getCenter());    	
    	}
    } 

	var updateText= function (fieldName, newValue) {
		var fieldElem = document.getElementById(fieldName);
		if (null != fieldElem) {
			fieldElem.innerHTML = newValue;
		}
	}
	var updateMapInfo = function () {
		updateText ("mapName", m_mapInfo.getName());
		updateText ("mapDescription", m_mapInfo.getDescription());		
		//console.log("Tags:"+m_mapInfo.getTags()+".");
		if ("" == m_mapInfo.getTags()) {
			document.getElementById("tags").style.display = "none";
		}
		else {
			document.getElementById("tags").style.display = "block";			
			updateText ("mapTags", m_mapInfo.getTags());
		}
		
		setBanner(m_mapInfo.getName());					
	}


    var showLoadedMapResult = function(result) {
    	if ((typeof (result) == "String")) {
    		setBanner(result);
			m_thisMapper.setDefaultCursor();    		
    		return;
    	}
    	var mapData= JSON.parse(result);
    	if (null != m_mapInfo) {
    		m_mapInfo.clear();
    	}
    	m_mapInfo = new MapInfo(mapData);

		var tabContainer   = dojo.widget.byId("locationTabContainer");
		var locTab         = dojo.widget.byId("locationsTab");		
		var layersTab      = dojo.widget.byId("layersTab");				
		
		if (("view" == m_format) || ("print" == m_format)) {
			if (0 == m_mapInfo.getLayers().length) {
				tabContainer.removeChild(layersTab);			
			}
			if (0 == m_mapInfo.getLocations().length) {
				tabContainer.removeChild(locTab);			
			}		
		}
		
		updateMapInfo();
	    m_thisMapper.updateMapTools();		
	    m_thisMapper.showMap(false);
		m_thisMapper.setDefaultCursor();    			    
    }
    
    this.showMap = function (isMine) {
		var locations = m_mapInfo.getLocations();
		for (var i=0;i<locations.length;i++) {
			var loc = locations[i];
			var point = null;
			if (undefined != loc.latitude) {
				point = new GLatLng(loc.latitude, loc.longitude);
			}
			if (null != point) {
				m_thisMapper.showAddressWithPoint(point, loc, null, true, isMine);				
			}
			else {
				m_thisMapper.showAddress(loc, null, true, isMine);
			}
		}
		var zoom = m_mapInfo.getZoom();
		var centerPoint = m_mapInfo.getCenter();	
		if (0 != zoom) {
			m_map.setCenter(centerPoint, zoom);
		}
		showLayers();		
		m_thisMapper.updateMapTools();
		
		fixSizes();
    }
    
	var showLayers= function () {
		var layers = m_mapInfo.getLayers();
    	for (var i=0;i<layers.length;i++) {
    		var nextLayer = layers[i];
    		var nl = new Layer(nextLayer.url, nextLayer.title, nextLayer.description);
	    	m_layerManager.addItem(nl.getId(), nl);
			m_thisMapper.showLayer(nl);
    	}
	}		
	
	this.getLayers = function () {
		var ols = m_layerManager.getItems();		
		var ret = new Array();
    	for (var i=0;i<ols.length;i++) {
    		var ol = ols[i];
    		if (null == ol) {
    			continue;
    		}
			ret.push({url: ol.getUrl(),
  			          title: valOrString(ol.getTitle()),
			          note:  valOrString(ol.getDescription())});
    	}		
    	return ret;
	}
	
	var goodLat = function (lat) {
		if (NaN == lat) {
			return false;
		}
		return ( (lat >= -90.0) &&
		         (lat <= 90.0));
	}
	
	var goodLng = function (lng) {
		if (NaN == lng) {
			return false;
		}		
		return ((lng >= -180.0) &&
				(lng <= 180.0));
		
	}	
	
	var isLatLng = function (address) {
		var ltlng = address.split(",");
		if (2 == ltlng.length) {
			if (isNaN(ltlng[0]) || isNaN(ltlng[1])) { 
				return false;
			}
			else {
				return true;
			}
		}
		return false;
	}	
	
	/*
	 * See if address is actually a lat/long string in form "lat, long", eg: "23.2, -23"
	 */
	var getLatLng = function (address) {
		if (!isLatLng(address)) {
			return null;
		}
		var ltlng = address.split(",");
		var lat = parseFloat(ltlng[0]);
		var lng = parseFloat(ltlng[1]);			      	
		if (goodLat(lat) && goodLng(lng)) {
			// Address seems to be a lat/lng, so return it
			return new GLatLng (lat, lng);
		}
		return null;
	}
	


    
    // Show address using geocoder, shows an alert if no address found
    // Note: this function asynchronously calls the inner function when the point is found (after talking to
    //       the google server)
    this.showAddress = function(locInfo, oldMarker, loadingMap, isMine, callback) {
      //var address = locInfo.getAddress();
      var address = locInfo.address;
      if ("" == address) {
      	alert("Please enter Address")
      	return false;
      }
     // See if the address is a lat/lng, then we don't have to geocode
     var point = getLatLng (address);
     if (null != point) {
		m_thisMapper.showAddressWithPoint(point, locInfo,oldMarker, loadingMap,isMine);      	
		if (undefined != callback) {
        	callback();
        }		
		return;     	
     }
     if (m_geocoder) 
      {  //console.log("geocoding...");
         m_geocoder.getLatLng(address, 
          function (point) 
            {
              if (!point) 
               {
				 alert("Address: "+address + " not found.");
               } 
              else 
              {    
              	m_thisMapper.showAddressWithPoint(point, locInfo ,oldMarker, loadingMap,isMine);
              	if (undefined != callback) {
              		callback();
              	}
              }
            } )
      }
    }


	var truncateString = function (s, limit) {
		if (s.length < limit) {
			return s;
		}
		return (s.substring(0, limit-3)+"...");
	}

	this.getMarkerInfo = function (title, address, note, url, urlTitle, addrNum, isMine) {
        var markerInfo = "";
		var imSearch = "";
        if ((undefined != title) && ("" != title )) {
        	markerInfo = "<div class='mapMarkerTitle'>"+title+"</div>";
	        imSearch = title;
        }
        else
        {
	        imSearch = address;        	
        }
        if (!isLatLng(address)) {
	        markerInfo += "<div class='mapMarkerAddress'>"+address+"</div>";
        }
        
        if ("" != note)
        {        	
			
            markerInfo += "<div class='mapMarkerNote'>"+note+"</div>";
        }
        if ("" != url) {
        	// If they don't put http:// in the front, add it for them
        	if (0 != url.indexOf("http://")) {
        		url = "http://" + url;
        	}
        	var urlTitleStr = urlTitle ? urlTitle : url;
        	var urlStr = "<a href='"+url+"' target='_new'>"+urlTitleStr+"</a>";
            markerInfo +="<div class='mapMarkerUrl'>"+urlStr+"</div>";
        }
        var zoomIn = "<span class='mapMarkerControl'><a href='#' onClick='m_mapper.zoomIn()'><img border='0' src='images/zoomIn.jpg'/></a></span>";
        var zoomOut = "<span class='mapMarkerControl'><a href='#' onClick='m_mapper.zoomOut()'><img border='0' src='images/zoomOut.jpg'/></a></span>";        

        var edit = "";
        if (isMine) {
	        edit= "<span class='mapMarkerControl'><a href='#' onClick='m_mapper.editAddress(\""+addrNum+"\")'><img border='0' src='images/edit.gif'/></a></span>";                
        }
        var delMap= "";
        if (isMine) {
	        delMap= "<span class='mapMarkerControl'><a href='#' onClick='m_mapper.deleteAddress(\""+addrNum+"\")'><img border='0' src='images/delete.gif'/></a></span>";                
        }        

        var canonicalAddr = m_geocodeCache.toCanonical(address).split(" ");
        addrOnly = "";
        csz      = "";        
        var last = canonicalAddr.pop();
        if (isNaN(last.substring(0,1))) {
        	state = canonicalAddr.pop();
        	csz = state+" "+last;
        	addrOnly = canonicalAddr.join (" ");
        }
        else {
        	csz =last;
        	addrOnly = canonicalAddr.join (" ");        	
        }

        var imageSearch = "<a target='_blank' href='http://flickr.com/search/?q="+imSearch+"'>flickr</a>";        	        	
        var webSearch = "&nbsp;&nbsp;<a target='_blank' href='http://google.com/search?q="+imSearch+"'>google</a>";

        markerInfo += "<div class='mapMarkerExternal'>"+imageSearch +webSearch+"</div>";
        markerInfo += zoomIn + zoomOut+edit+delMap;
		markerInfo = "<div class='mapMarkerRegion'>"+markerInfo+"</div>";
		return markerInfo;		
	}
	
	this.showAddressWithPoint = function (point, locInfo, oldMarker, loadingMap, isMine){    
		m_map.setCenter(point);             

		var imSearch = "";
		var title = locInfo.title;
		var address = locInfo.address;
		var note = locInfo.note;
		var url      = locInfo.url;
		var urlTitle = locInfo.urlTitle		

		var addrNum = locInfo.addressIndex;
		if (undefined == addrNum) {
			addrNum =m_addrCache.length;
		}
        var markerInfo = m_thisMapper.getMarkerInfo(title, address, note, url, urlTitle, addrNum, isMine);
        
        var marker;
        if (null == oldMarker) {
         marker = createMarker(point, markerInfo);
         m_map.addOverlay(marker);                 
        }
        else {
         marker = oldMarker;         
         updateMarker(oldMarker, point, markerInfo);
        }
        if (!loadingMap) {
            marker.openInfoWindowHtml(markerInfo);  
        }

		storeAddress(point, locInfo, marker, markerInfo)
	}

    // Creates a marker at the given point with the marker info for an overlay
    var createMarker = function(point, info) {
      var addrNum = m_addrCache.length;
      addrNum = addrNum % 26;
      var letter = String.fromCharCode("A".charCodeAt(0) + addrNum);         
      var icon = new GIcon(baseIcon);
      var im = "http://www.google.com/mapfiles/marker" + letter + ".png";
      icon.image = im;
      var opts = {icon: icon};

      var marker = new GMarker(point, opts);
      

      GEvent.addListener(marker, "click", function() 
      {
        marker.openInfoWindowHtml(info);
      });
      return marker;
    }
    
	var updateMarker = function(marker, point, info) {
		marker.setPoint(point);
		GEvent.clearListeners(marker,"click");
		GEvent.addListener(marker, "click", function() 
	      {
	        marker.openInfoWindowHtml(info);
	      });		
	}
	
	this.getLayer= function (id) {
		return m_layerManager.getItem(id);
	}
	
	this.updateLayer= function (id, url, title, note) {
		var layer = m_layerManager.getItem(id);
		layer.setUrl(url);
		layer.setTitle(title);
		layer.setDescription(note);
		m_map.removeOverlay(layer.getGMapOverlay());					
		m_layerManager.updateItem(id, layer);
		this.showLayer(layer);
	}
		
	this.addLayer= function (url, title, note) {		
		var l = new Layer(url, title, note);
		m_layerManager.addItem(l.getId(), l);
		m_thisMapper.showLayer(l);
	}
	
	this.showLayer = function (layerInfo) {
		
		if (null != layerInfo.getUrl()) {
			try {
				//Put it on the map and get the GMap layer info
				var geoXml = new GGeoXml(layerInfo.getUrl());
				m_map.addOverlay(geoXml);  
				layerInfo.setGMapOverlay(geoXml);  				
			}
			catch  (err){
				//console.log("Error: "+err.description)
				return;
			}
		}

		var id = layerInfo.getId();
		var theRow, checkBox, urlText, editCell, deleteCell;
		
		//see if the row is already there
		var findRow = getTableRow("LayerId"+id, m_layerList)
		if (-1 == findRow) {
			// no row
			theRow = m_layerList.insertRow(m_layerList.rows.length);			
			theRow.id="LayerId"+id;			
			checkBox   = theRow.insertCell(0);			
			urlText    = theRow.insertCell(1);					
			editCell   = theRow.insertCell(2);		
			deleteCell = theRow.insertCell(3);					

			checkBox.className   = "layerCheckCell";
			urlText.className    = "layerUrlCell";
			editCell.className   = "layerEditCell";
			deleteCell.className = "layerDelCell";					
		}
		else {
			theRow = m_layerList.rows[findRow];
			checkBox   = theRow.cells[0];
			urlText    = theRow.cells[1];
			editCell   = theRow.cells[2];
			deleteCell = theRow.cells[3];									
		}
		
	
		checkBox.innerHTML="<input onclick='m_mapper.checkBoxChanged("+id+")' type='checkbox' checked='true' id='LayerActive"+id+"' name='LayerActive"+id+"'>"
		var showText = ("" != layerInfo.getTitle()) ? layerInfo.getTitle() : layerInfo.getUrl();
		showText = truncateString(showText,25);     		
		urlText.innerHTML = "<a href='#' title='"+layerInfo.getUrl()+"' onclick='m_mapper.showLayerInfo(\""+id+"\")'>"+ showText+"</a>";

		if (!isReadOnly()) {
     	    editCell.innerHTML="<a title='Edit this layer' href='#' onclick='m_mapper.editLayer(\""+id+"\")' ><img border='0' src='images/edit.gif'/></a>";			
	    	deleteCell.innerHTML="<a title='Delete this layer' href='#' onclick='m_mapper.deleteLayer(\""+id+"\")' ><img border='0' src='images/delete.gif'/></a>";      
	  }		
	}
	
	this.layerVisible = function (id, isVis) {
		var layerInfo = m_layerManager.getItem(id);
		if (isVis) {
			m_map.addOverlay(layerInfo.getGMapOverlay());
		}
		else {
			m_map.removeOverlay(layerInfo.getGMapOverlay());			
		}
		
	}	
	
	
	this.deleteLayer = function (layerId) {
		
    	m_map.closeInfoWindow();		
		this.layerVisible(layerId, false);
		m_layerManager.deleteItem(layerId);
    	m_layerList.deleteRow(getTableRow("LayerId"+layerId,m_layerList));		
	}
	
	this.checkBoxChanged= function (id) {
		var box = document.getElementById("LayerActive"+id);
		m_thisMapper.layerVisible(id,box.checked);
	}	
	


	this.showLayerInfo = function (id) {
		var layer = m_layerManager.getItem(id);		
		document.getElementById("layerUrlInfo").innerHTML = layer.getUrl();

		var layerTitleWrapper = document.getElementById("layerTitleWrapper");
		if ("" == layer.getTitle()) {
			layerTitleWrapper.style.display="none";
		}
		else {
			document.getElementById("layerTitleInfo").innerHTML = layer.getTitle();			
			layerTitleWrapper.style.display="block";			
		}
		var layerNoteWrapper=document.getElementById("layerNoteWrapper");
		if ("" == layer.getDescription()) {
			layerNoteWrapper.style.display="none";
		}
		else {
			document.getElementById("layerNoteInfo").innerHTML = layer.getDescription();				
			layerNoteWrapper.style.display="block";			
		}

		var checked = document.getElementById("LayerActive"+id).checked;
		var layerActive = document.getElementById("layerActiveInfo");
		if (checked) {
			layerActive.innerHTML = "The Layer is Shown";
			layerActive.className = "layerActive";
		}
		else {
			layerActive.innerHTML = "The Layer is Not Shown";
			layerActive.className = "layerInactive";			
			
		}

		m_showLayerInfoDialog.show();
	}
	
	this.cancelShowLayer = function () {
		m_showLayerInfoDialog.hide();
	}

    //Add the address to the list on the left of the map. Add it to the end of the table.    
    var storeAddress = function (point, locInfo, marker, markerInfo) {
    	var address  = locInfo.address;
    	var title    = locInfo.title;
    	var note     = locInfo.note;
    	var url      = locInfo.url;
    	var urlTitle = locInfo.urlTitle;    	
    	var addrInfo = {point: point, address: address, title: title, 
    	                note: note,  url:url, urlTitle:urlTitle,
    	                marker: marker, markerInfo:markerInfo};          	
    	var imageCell, addressCell, editCell, deleteCell;
		var addrNum = locInfo.addressIndex;
		
    	if (undefined == addrNum) {
      		addrNum = m_addrCache.length;
			m_addrCache.push(addrInfo);

	      	var tableRow= m_addressList.rows.length;
		    var theRow=m_addressList.insertRow(tableRow);
	        // Set the row 
	        theRow.id = addrNum;
      
      		imageCell=theRow.insertCell(0);     
      		imageCell.width="12px"; 		
      		addressCell=theRow.insertCell(1);
      		addressCell.className = "addressCell";
      		editCell=theRow.insertCell(2);  
      		editCell.width="16px";
      		deleteCell=theRow.insertCell(3);  			
      		deleteCell.width="16px";
    	}
    	else {
    		m_addrCache[addrNum] = addrInfo;
    		
    		theRow =   m_addressList.rows[getTableRow(addrNum, m_addressList)];
    		imageCell = theRow.cells[0];
    		addressCell = theRow.cells[1];
    		editCell = theRow.cells[2];
    		deleteCell=theRow.cells[3];
    	}


      	// Put the image in the first cell 
      	imageCell.innerHTML="<img width=12 height=20 src='"+marker.getIcon().image+"'/>";  	imageCell.vAlign="top";
	    imageCell.vAlign="top";
      // Put the title or address in the second cell
      var addressHTML;
      if ( (undefined == title) || ("" == title)) {
		addressHTML = "<div class='addressListEntry'><a href='#' onclick='m_mapper.centerOn(\""+addrNum+"\")'>"+address+"</a></div>";
      }
      else {
      	var tooltip = address;
		addressHTML = "<div class='addressListEntry'><a href='#' onclick='m_mapper.centerOn(\""+addrNum+"\")' title='"+tooltip+"'>"+title+"</a></div>";  
		if ("print" == m_format) {
			addressHTML += "<div class='addressListAddress'>"+address+"</div>";
		}		
      }
      if ("" != note)
      {
      	var noteStr = "";
     	if (isReadOnly()) {
			noteStr = truncateString(note,44);     		
     	}
     	else {
			noteStr = truncateString(note,22);     		
     	}
        addressCell.innerHTML=addressHTML+"<div id='addressNoteMarker' class='addressListNote'>"+noteStr+"</div>"; 
      }
      else
      {
        addressCell.innerHTML=addressHTML;
      }
      addressCell.vAlign="top";

	  if (!isReadOnly()) {
	      editCell.innerHTML="<a title='Edit this address' href='#' onclick='m_mapper.editAddress(\""+addrNum+"\")' ><img border='0' src='images/edit.gif'/></a>";
	      deleteCell.innerHTML="<a title='Delete this address' href='#' onclick='m_mapper.deleteAddress(\""+addrNum+"\")' ><img border='0' src='images/delete.gif'/></a>";      
	  }
    }
    
    this.zoomIn = function () {
		m_map.setZoom(m_map.getZoom() + 5);	    
    }
    
    this.zoomOut= function () {
		m_map.setZoom(m_map.getZoom() - 5);
    }    
    
    // getTableRow translates an addrNum, which is an index based on when it was added to
    // the addrress cache, into a row table
    var getTableRow =function (id, domTable) {
    	var rows    = domTable.rows;
    	var numRows = rows.length;
    	for (var i = 0;i<numRows; i++) {
    		var nextRow = rows[i];
    		if (id == nextRow.id) {
    			return i;
    		}
    	}
    	return -1;
    }
    


    
	var clearBanner = function () {
		setBanner("");
	}
	
    var setBanner = function (s) {
		var banner = document.getElementById("titleBanner");
		if (null != banner) {
			banner.innerHTML=s;
		}    	
    }
        
  this.setupLocalSearch = function () {
      // Create a search control
	  m_searchControl = new GSearchControl(); 
	             
	  // Just do local search (you can add web/video/blog here)
      m_localSearch = new GlocalSearch();		
      m_searchControl.addSearcher(m_localSearch);

      // Tell the searcher to draw itself and tell it where to attach
      m_searchControl.draw(document.getElementById("searchcontrol"));
    }
 
}

    
