function CMSUMap(title, container, mapPointTotal)
{
	//set the private variables
	var m_title = title;
	var m_lat = 0; 
	var m_lng = 0; 
	var m_vXmlFiles = new Array(); 
	var m_vMapPoints = new Array();
	var m_map = null;
	var m_container = container;	//div container for map
	
	var m_totalMapPoints = mapPointTotal;
	var m_currCount = 0;
	
	
	//I'm not sure if this is how I want to do it
	var m_typeToShow = null;
	var m_mapPointNameToShow = null;
	

	//public member varialbles
	this.resetMap = resetMap;
	this.searchFor = searchFor;
	this.searchForID = searchForID;
	this.destroyMap = destroyMap;
	this.showMapPointsByType = showMapPointsByType;
	this.hideMapPointsByType = hideMapPointsByType;
	this.immediatelyShow = immediatelyShow;
	this.immediatelyShowMapPoint = immediatelyShowMapPoint;
	
	
	//start creating the map
	GDownloadUrl("xml/locations.xml?nocache="+Math.random(), getMapInfo);
	
	/*
	Function: initializeMap
	Purpose: create the map
	*/
	function initializeMap()
	//var initializeMap = function()
	{
		// Creates a map and centers it on MSU.
		m_map = new GMap2(m_container);
		m_map.setCenter(new GLatLng(m_lat, m_lng), 15);
		
		if (m_title == "MSU Campus")
			setCustomMap();
		
		m_map.addControl(new GLargeMapControl());
		m_map.addControl(new GScaleControl());
		m_map.addControl(new GMapTypeControl());
		
		//hides the minimap
		m_map.addControl(MiniMap);
		MiniMap.hide();
		
		//enable zoom scrolling
		m_map.enableScrollWheelZoom();
		
		// Find the closest mappoint on click
		GEvent.addListener(m_map, 'click', function(overlay, latlng) {
			if (latlng){
				//this probably isn't the greatest way to search it...
				for (var i=0; i<m_vMapPoints.length; i++){
					var oMapPoint = m_vMapPoints[i];
					//check to see that it's a certain distance 
					//(in meters) from any mappoint on the map
					if((latlng.distanceFrom(oMapPoint.getMarker().getLatLng())) < 50){
						showMapPoint(oMapPoint);
						panToMapPoint(oMapPoint);
					}
				}
			}
		});//end find closest mappoint on click
		
		//load in all the points in the xml files
		for (var i=0; i<m_vXmlFiles.length; i++)
		{
			GDownloadUrl(m_vXmlFiles[i] +"?nocache="+Math.random(), retrieveFileContents);
		}
		
	};//end initializeMap
	
	/*
	Function: initializePoint
	Parameters:
		-category = the category that the point will pertain to
		-xmlNode = an entire xml node from the file
	Purpose: initialize a single point's information
	*/
	function initializePoint (category, xmlNode)
	{
		var oMapPoint = new CMapPoint(category, xmlNode);
		m_vMapPoints.push(oMapPoint);
		
		//if there is something to show immediately
		if (m_typeToShow != null)
		{
			if ( (oMapPoint.compareToTypes(m_typeToShow)) ||
				 (oMapPoint.getCategory() == m_typeToShow) )
			{
				showMapPoint(oMapPoint);
			}
		}
		if (m_mapPointNameToShow != null)
		{
			if (oMapPoint.compareToIdOrAbbv(m_mapPointNameToShow))
			{
				showMapPoint(oMapPoint);
				panToMapPoint(oMapPoint);
			}
		}
	}
	
	/*
	Function: setCustomMap
	Purpose: Sets a custom map overlay for the area comprised of images
	*/
	function setCustomMap()
	{
		//sets the copyrights for our mapn
		var copyright = new GCopyright(1,
				new GLatLngBounds(new GLatLng(42.669436,-84.517565),
					new GLatLng(42.736075,-84.459500)), 
				14, "Board of Trustees");
		var copyrightCollection = new GCopyrightCollection('Michigan State University:');
		copyrightCollection.addCopyright(copyright);
	
		//sets the tiles for our overlay
		var gtl = new GTileLayer(copyrightCollection,14,17);
		gtl.getTileUrl=function(a,b){
			if (b==14 && a.x>=4345 && a.x<=4348 && a.y>=6036 && a.y<= 6040) {
			  return tile_path+"/x14/base_"+a.x+"_"+a.y+"_14.gif";
			} else if (b==15 && a.x>=8691 && a.x<=8696 && a.y>=12073 && a.y<= 12081) {
			  return tile_path+"/x15/base_"+a.x+"_"+a.y+"_15.gif";
			} else if (b==16 && a.x>=17382 && a.x<=17392 && a.y>=24146 && a.y<= 24162) {
			  return tile_path+"/x16/base_"+a.x+"_"+a.y+"_16.gif";
			} else if (b==17 && a.x>=34768 && a.x<=34784 && a.y>=48293 && a.y<= 48322) {
			  return tile_path+"/x17/base_"+a.x+"_"+a.y+"_17.gif";
			} else {
				   return "http://www.google.com/mapfiles/transparent.gif";
			}
		}
		
		//adds the custom map with our tiles over the regular map
		var customMap = new GMapType([G_NORMAL_MAP.getTileLayers()[0], gtl],
				 G_NORMAL_MAP.getProjection(), 'MSU',{errorMessage:"Out of bounds"});
	
		// added by MDM 9-16-08
		customMap.getMaximumResolution = function() {
			return 17;
		}
	
		m_map.addMapType(customMap);
		m_map.setMapType(customMap);
	}
	
	
	/*
	Function: getMapInfo
	Purpose: get the map info we need to load in
	*/
	function getMapInfo(data, responseCode)
	{
		if (responseCode == 200)
		{
			var xml = GXml.parse(data);
			var MSULocationsNode = xml.documentElement;
			var vMSULocation = MSULocationsNode.getElementsByTagName("MSULocation");
			
			//initialize each Item
			if (vMSULocation != null)
			{
				for (var i = 0; i < vMSULocation.length; i++){
					var xmlNode = vMSULocation[i];
					if (m_title == xmlNode.getAttribute("title"))
					{
						//parse the lat and lng
						m_lat = parseFloat(xmlNode.getAttribute("lat"));
						m_lng = parseFloat(xmlNode.getAttribute("lng"));
						
						try{
							//get each xml file of data associated with this map
							if (xmlNode.getElementsByTagName("xmlFile")[0].hasChildNodes()){
								vXmlFiles = xmlNode.getElementsByTagName("xmlFile");
								
								//get the name of the last file
								for (var j=0; j<vXmlFiles.length; j++)
								{
									m_vXmlFiles.push(vXmlFiles[j].childNodes[0].nodeValue);
								}
							}
							
						}
						catch (e)
						{
						}
						initializeMap();
						break;
					}
				}
			}
		} else if(responseCode == -1) {
			alert("Data request timed out. Please try later.");
		} else { 
			alert("Request resulted in error. Check XML file is retrievable.");
		}
	};//end getMapInfo
	
	/*
	Function: retrieveFileContents
	Purpose: call back method to parse the xml
	*/
	function retrieveFileContents(data, responseCode)
	{
		if (responseCode == 200)
		{
			var xml = GXml.parse(data);
			var mapsNode = xml.documentElement;
			var category = mapsNode.getAttribute("category");
			
			var vMarkers = mapsNode.getElementsByTagName("ItemList");
			
			//initialize each Item
			if (vMarkers != null)
			{
				for (var i = 0; i < vMarkers.length; i++){
					initializePoint(category, vMarkers[i]);
					m_currCount ++;
					
					if (m_currCount == m_totalMapPoints)
					{
						//console.log(m_currCount);
						displayMapWhenReady();
					}
				}
			}
		} else if(responseCode == -1) {
			alert("Data request timed out. Please try later.");
		} else { 
			alert("Request resulted in error. Check XML file is retrievable.");
		}
	}//end retrieveFileContents
	
	/*
	Function: panToMapPoint
	Parameters:
		-oMapPoint:  the mapPoint to pan to on the map
	Purpose: focus the map on a specific mappoint
	*/
	function panToMapPoint(oMapPoint)
	{
		m_map.panTo(oMapPoint.getLatLng());
		if (oMapPoint.getInfoTabs() != null){
	 		oMapPoint.getMarker().openInfoWindowTabsHtml(oMapPoint.getInfoTabs());
		}
		else{
			oMapPoint.getMarker().openInfoWindowHtml(oMapPoint.getGeneralInfo());
		}
	}//end panToMapPoint
	
	/*Function: showMapPoint
	Paramter: oMapPoint
	Purpose: show a MapPoint MapPoint on the map*/
	function showMapPoint(oMapPoint)
	{
		//if it's not visible, show it
		if (!oMapPoint.is_visible)
		{
			m_map.addOverlay(oMapPoint.getMarker());
			oMapPoint.is_visible = true;
		}
	}//end showMapPoint
	
	/*
	Function: hideAllMapPoints
	Purpose: hide all of the mappoints from the map by removeOverlay-ing them
	*/
	function hideAllMapPoints()
	{
		for (var i in m_vMapPoints)
		{
			m_vMapPoints[i].is_visible = false;
			m_map.removeOverlay(m_vMapPoints[i].getMarker());
		}
	}//end hideAllMapPoints
	
	/*
	Function: hideMapPoint
	Paramter: 
		-oMapPoint: the mapPoint to hide
	Purpose: hide a MapPoint MapPoint on the map
	*/
	function hideMapPoint(oMapPoint)
	{
		//if it's currently visible, hide it
		if (oMapPoint.is_visible)
		{
			m_map.removeOverlay(oMapPoint.getMarker());
			oMapPoint.is_visible = false;
		}
	}
	
	/*
	Function: showMarkersByType
	Parameter: 
		-type: what to filter by
	Purpose: show markers by a given type, for use with checkboxes mostly
	*/
	function showMapPointsByType(type)
	{
		//go through each MapPoint and figure out if it's viewable
		for (var i in m_vMapPoints){
			if (m_vMapPoints[i].compareToTypes(type)){
				showMapPoint(m_vMapPoints[i]);
			}
		}
	}//end showMapPointsByType
	
	/*
	Function: hideMarkersByType
	Parameter: 
		-type: what to filter by
	Purpose: hide markers by a given type, for use with checkboxes mostly
	*/
	function hideMapPointsByType(type)
	{
		//go through each MapPoint and figure out if it's viewable
		for (var i in m_vMapPoints){
			if (m_vMapPoints[i].compareToTypes(type)){
				hideMapPoint(m_vMapPoints[i]);
			}
		}
	}//end hideMapPointsByType
	
	/*
	Function: resetMap 
	Purpose: reset the map to the intial state
	*/
	function resetMap()
	{
		//make sure none of the mappoints are visible
		hideAllMapPoints();
	
		//reset the map
		m_map.setCenter(new GLatLng(m_lat, m_lng), 15);
		
		//remove all the markers
		m_map.clearOverlays();
	}//end resetMap
	
	/*
	Function: searchForID
	Parameters:
		-searchTerm: the search id to search by
	Purpose: search the map by id
	*/
	function searchForID(searchTerm)
	{
		var isFound = false;
		for (var i in m_vMapPoints)
		{
			if (m_vMapPoints[i].compareToID(searchTerm))
			{
				showMapPoint(m_vMapPoints[i]);
				panToMapPoint(m_vMapPoints[i]);
				isFound = true;
				break;
			}
		}
		return isFound;
	}//end searchForID
	
	/*
	Function: searchFor
	Parameters:
		-searchTerm: what to search for
	Purpose: search the map based on a search term
	*/
	function searchFor(searchTerm)
	{
		var isFound = false;
		var vMapPointResults = new Array();
		
		searchTerm = searchTerm.replace(/^\s+|\s+$/g, "");
		//create a regex search pattern 
		var searchPattern = null;
		if ((searchTerm == "north") || (searchTerm == "south") || (searchTerm == "east") ||
			(searchTerm == "west") ||  (searchTerm == "building") || (searchTerm == "hall"))
		{
			searchPattern = new RegExp(searchTerm, 'i');	
		}
		else
		{
			//replace anything at the beginning
			var searchPattern = searchTerm.replace(/^(north|south|east|west|building|hall)/gi, "");
			
			//remove common words from the search string
			var searchPattern = searchTerm.replace(/(north|south|east|west|building|hall)$/gi, "");
			searchPattern = searchPattern.toLowerCase();
			searchPattern = searchPattern.replace(/^\s+|\s+$/g, "");
			searchPattern = new RegExp(searchPattern, 'i');
		}
		
		for (var i=0; i<m_vMapPoints.length; i++){
			//check if the name, alternative name, or abbrv match exactly
			if (m_vMapPoints[i].compareTo(searchTerm) || 
				m_vMapPoints[i].matchOn(searchPattern)){
				isFound = true;
				vMapPointResults.push(m_vMapPoints[i]);	//add the result
			}
		}
		
		//if you found something
		if (isFound)
		{
			for (var i=0; i<vMapPointResults.length; i++){
				showMapPoint(vMapPointResults[i]);
				
				//pan if there is only 1 result
				if (vMapPointResults.length == 1)
				{
					panToMapPoint(vMapPointResults[i]);
				}
			}
		}
		vMapPointResults = [];	//clear out the results
		return isFound;
	}//end searchFor
	
	/*
	Function: destroyMap
	Purpose: unitialize the map
	*/
	function destroyMap()
	{
		m_title = "";
		m_lat = 0; 
		m_lng = 0; 
		m_vXmlFiles = []; 
		m_vMapPoints = [];
		
		resetMap();
		
		m_map = null;
	}//end destroyMap
	
	/*
	Function: immediatelyShow
	Parameters:
		-type: what to immediately show on the map
	Purpose: this should only be used to show a mappoint when linking to a page
	*/
	function immediatelyShow(type)
	{
		m_typeToShow = type;
	}//end immediatelyShow
	
	/*
	Function: immediatelyShow
	Parameters
		-name: name/id of mappoint to show
	Purpose: immediately show a mappoint when loading a page
	*/
	function immediatelyShowMapPoint(name)
	{
		m_mapPointNameToShow = name;
	}//end immediatelyShowMapPoint

	function displayMapWhenReady()
	{
		var divResultsBox = document.getElementById('resultsBox');
		var divResults = document.getElementById('results');
		
		divResultsBox.className = "hide";
		divResults.className = "hide";
	}
}//end CMSUMap