if (typeof(SAIT) === "undefined") var SAIT = {};

/**
 * SAIT.Map Google Map Namespace
 *
 * Contains the methods/properties which initialize the map, 
 * custom markers/overlays, and search functionality.
 *
 * @param: none
 */

	SAIT.Map = {
		
		/*** CLASS CONSTANTS ***/
		SAIT_LOCATION: new GLatLng(51.064591, -114.090120),
		SAIT_ZOOM: 16,
		SELECT_CATEGORIES: "catInput",
		INPUT_SEARCH_TEXT: "s_txt",
		BTN_SEARCH: "s_btn",
		SELECT_CAMPUS_ID: "campus_id",
		CHK_MAP_OPTIONS: "chk_mapOptions",		
		PATH_XML_MARKERS: "includes/map.genMarkerXML.php",
		PATH_XML_POLYGONS: "includes/map.genPolygonXML.php",
		PATH_ICONS: "images/customIcons/",
		PATH_THUMBNAILS: "images/gallery/thumbs/",
		PATH_PHOTOS: "images/gallery/photos/",
				
		/*** CLASS VARIABLES ***/
		_mapContainer: "",
		_categories: {}, // {overlays:[], showOnload: 0|1}
    _gLocalResults: [], // Goole maps results container
		_gSaitResults: [], // SAIT specific results container
		_checkedAll: false, // Global variable to monitor state of select/deselect of all checkboxes.
		
		/**
		 * Method to perform a SAIT campus search. 
		 *
		 * @param: {String} Keyword(s) passed in through form textbox.
		*/
		_onSAITSearch: function(text) {
			var searchUrlMarkers = "includes/map.genSAITSearchM.php?search="+ text.toLowerCase();			
			var map = SAIT.Map._mapContainer;			
			
			// Search for Markers
			GDownloadUrl(searchUrlMarkers, function(data) {
				var xml = GXml.parse(data);
				var markers = xml.documentElement.getElementsByTagName("marker");
				
				if (markers.length != 0) {
					
					SAIT.Map._clearMap(); // clear map of all markers/polygons
					SAIT.Map._gSaitResults = []; // reset the global SAIT results array
					
					for (var i=0; i < markers.length; i++) {					
						var marker = SAIT.Map._createMarker(markers[i]);
						SAIT.Map._gSaitResults.push(marker);
						map.addOverlay(marker);
					} // end for
				} else {
					alert("No results found");
				}// end if
			});
			
			map.setCenter(SAIT.Map.SAIT_LOCATION, SAIT.Map.SAIT_ZOOM);
			
		},
		
		/**
		 * A class representing a single google.search.LocalSearch result 
		 * returned by the Google AJAX Search API
		 *
		 * @param: Object
		*/
    _localResult: function(result) {
			var map = SAIT.Map._mapContainer;
			
			this._result = result;
      map.addOverlay(this.marker());
    },
		
		/**
		 * Callback function for setSearchCompleteCallback method of
		 * the google.search.LocalSearch object.
		 * 
		 * @param: none
		*/
		_onLocalSearch: function() {
			var map = SAIT.Map._mapContainer;
			var localsearch = SAIT.Map._localSearch;
						
			if(localsearch.results.length == 0) {
				alert('No results found');
			} else {
				
				SAIT.Map._clearMap();
								
				SAIT.Map._gLocalResults = [];
				for (var i=0; i<localsearch.results.length; i++) {
        	SAIT.Map._gLocalResults.push(new SAIT.Map._localResult(localsearch.results[i]));
      	}
								
      	var first = localsearch.results[0];				      	
				map.setCenter(new GLatLng(parseFloat(first.lat),parseFloat(first.lng)),11);
			} // end if
    }, 
		
		/**
		 * Method attached unobstrusively to the search functionality
		 * of the map.
		 *
		 * @param: none
		*/
		doSearch: function() {
			var cat = document.getElementById(SAIT.Map.SELECT_CATEGORIES).value;
			var text = document.getElementById(SAIT.Map.INPUT_SEARCH_TEXT).value;
			
			if((cat != null) && (text != '')) {
				// Do a SAIT search
				if (cat == 'sait') {
					SAIT.Map._onSAITSearch(text);
				} else {
				// Do a Calgary wide search
					var localsearch = SAIT.Map._localSearch;
					localsearch.setCenterPoint(cat + ', alberta, canada');
	      	localsearch.execute(text + ', ' + cat + ', alberta, canada');
				}
			}
		},
		
		/**
		 * Method to initialize the google.search.LocalSearch functionality.
		 *
		 * @param: none
		*/
		_initializeMapSearch: function() {
			SAIT.Map._localSearch = new google.search.LocalSearch();
			SAIT.Map._localSearch.setSearchCompleteCallback(null, SAIT.Map._onLocalSearch);			
		},
		
		/**
		 * Method to clear the map of all markers, polygons,
		 * info windows, and reset the checkboxes under Map Options
		 *
		 * @param: none
		*/
		_clearMap: function() {
			var map = SAIT.Map._mapContainer;
			var chk = SAIT.Util._getElementsByClassName(SAIT.Map.CHK_MAP_OPTIONS,"input");
			
			// Close Info windows
			map.closeExtInfoWindow();
			
			// Clear search result markers (Sait & Calgary global results array)
			for (var i=0; i<SAIT.Map._gLocalResults.length; i++) {
					map.removeOverlay(SAIT.Map._gLocalResults[i].marker());
			}
			for (var i=0; i<SAIT.Map._gSaitResults.length; i++) {
					map.removeOverlay(SAIT.Map._gSaitResults[i]);
			}
			
			// Clear the Map Option checkboxes
			for(i=0; i<chk.length; i++) {
				chk[i].checked = false;
			}
			
			// Remove custom overlays (markers & polygons)
			for (var i in SAIT.Map._categories) {
				for (var j=0; j<SAIT.Map._categories[i].overlays.length; j++) {
					var overlay = SAIT.Map._categories[i].overlays[j];
					if(!overlay.isHidden()) {
						overlay.hide()						
					} 
				} // end for
			} // end for
		},
		
		/**
		 * Method to toggle the visibility of the custom overlays.
		 * Will toggle either groups of markers/polygons or all
		 * of them pending value of this.value param.
		 *
		 * @param: this.value (implicit)
		*/
		toggleOverlays: function() {
			var map = SAIT.Map._mapContainer;
			var category_id = this.value;
			
			// Clear all google search results
			for (var i=0; i<SAIT.Map._gLocalResults.length; i++) {
					map.removeOverlay(SAIT.Map._gLocalResults[i].marker());
			}
			// Clear all sait search results
			for (var i=0; i<SAIT.Map._gSaitResults.length; i++) {
					map.removeOverlay(SAIT.Map._gSaitResults[i]);
			}
			
			// Close Info windows
			map.closeExtInfoWindow();
			
			if(category_id == 'all') {
				var chk = SAIT.Util._getElementsByClassName(SAIT.Map.CHK_MAP_OPTIONS,"input");
				
				(SAIT.Map._checkedAll == false) ? SAIT.Map._checkedAll = true : SAIT.Map._checkedAll = false;
				
				for (var i in SAIT.Map._categories) {
					for (var j=0; j<SAIT.Map._categories[i].overlays.length; j++) {
						var overlay = SAIT.Map._categories[i].overlays[j];
							(SAIT.Map._checkedAll == false) ? overlay.hide() : overlay.show();
					} // end for
				} // end for
				
				for(i=0; i<chk.length; i++) {
					chk[i].checked = SAIT.Map._checkedAll;
				}
				
			} else {
				
				for(var i=0; i<SAIT.Map._categories[category_id].overlays.length; i++) {
					var overlay = SAIT.Map._categories[category_id].overlays[i];				
					(overlay.isHidden()) ? overlay.show() : overlay.hide();
				} // end for	
				
			} // end if
		},
		
		_createPolygon: function (node) {			
			var colour = node.getAttribute("markerColor");
			var showOnLoad = node.getAttribute("showOnLoad");
			var type = node.getAttribute("type");
			var points = node.getElementsByTagName("point");							
			var pts = [];
			
			for(var j=0; j<points.length; j++) {								
				 pts[j] = new GLatLng(parseFloat(points[j].getAttribute("lat")),parseFloat(points[j].getAttribute("lng")));
			}
			
			// Add the first point to the end of the pts array so the polygon will be closed.
			pts.push(new GLatLng(parseFloat(points[0].getAttribute("lat")),parseFloat(points[0].getAttribute("lng"))));
			var polygon = new GPolygon(pts, "#342223", 1, 0.1, colour, 0.3);
			
			return polygon;
		},
		
		_createMarker: function(node) {
			var iconID = node.getAttribute("iconID");
			var iconName = node.getAttribute("iconName");					
			var general = node.getAttribute("general");
			var address = node.getAttribute("address");
			var phone = node.getAttribute("phone");
			var email = node.getAttribute("email");
			var url = node.getAttribute("url");
			var hrs = node.getAttribute("hrs");
			var tags = node.getAttribute("tags");
			var iconType = node.getAttribute("iconType");
			var category_id = node.getAttribute("category_id");
			var showOnLoad = node.getAttribute("showOnLoad");
			var photos = node.getElementsByTagName("photo")
						
			var infoWindowOptions = {
				"id": iconID,
				"name": iconName,
				"general": general,
				"address": address,
				"phone": phone,
				"email": email,
				"siteUrl": url,
				"hrs": hrs,
				"tags": tags,
				"photos": photos
			};
			
			var point = new GLatLng(parseFloat(node.getAttribute("lat")), parseFloat(node.getAttribute("lng")));																				
			
			// Catch markers belonging to buildings (B) & parking (P) so we can define a custom marker/icon
			if(iconType == 'B' || iconType == 'P') {
				
				var iconLabel = iconName.substr(0,iconName.indexOf('-')-1);
				var labelOffSet_Width = (iconLabel.length == 1) ? -4 : -9; // -10 for one letter, -15 for two letters
				var iCustom = new GIcon();
				
				iCustom.image = SAIT.Map.PATH_ICONS + "icon_" + category_id + ".png";
				iCustom.iconSize = new GSize(24, 24);
				iCustom.iconAnchor = new GPoint(12, 15);
				iCustom.infoWindowAnchor = new GPoint(10, 0);
				
				var iconClass = (iconType == 'P') ? "LabeledMarker_markerLabel2" : "";				
				
				var iconOptions = {
					"icon": iCustom,
					"clickable": true,
					"title": iconName,
					"labelText": iconLabel,
					"labelClass": iconClass,
					"labelOffset": new GSize(labelOffSet_Width, -10) 
				}
				
				// Custom Marker created from the labeledmarker.js library
				var marker = new LabeledMarker(point,iconOptions);
				
			} else {
				
				var iCustom = new GIcon(G_DEFAULT_ICON);
				iCustom.image = SAIT.Map.PATH_ICONS + "icon_" + category_id + ".png";
				var iconOptions = { "icon": iCustom, "title": iconName}
				
				// Marker created from standard Google GMarker class
				var marker = new GMarker(point,iconOptions);
				
			} // end if
			
			GEvent.addListener(marker, 'click', function() {				
				SAIT.Map._createInfoWindow(marker, infoWindowOptions);
			});
			
			return marker;
		},
		
		/**
		 * Method to create custom info windows. Based off the
		 * openExtInfoWindow constructor of extinfowindow.js library.
		 *
		 * @param: {Gmarker} marker The marker associated with the info window
		 * @param: {Object} opt_opts A container for optional info window configuration
		 *		{String} iconID Unique marker/icon id
		 *		{String} name The title of the info window
		 *		{String} general Brief description of marker
		 *		{String} address
		 *		{String} phone
		 *		{String} email
		 *		{String} siteUrl
		 *		{String} mapUrl
		 *		{String} hrs
		 *		{String} city
		 * 		{String} province
		 *		{Array}  photos
		*/
		_createInfoWindow: function(marker,opt_opts) {
			var map = SAIT.Map._mapContainer;
			
			var id = opt_opts.id || "";
			var name = opt_opts.name || "";
			
			var general = opt_opts.general || "";			
			if(general != "") {general = "<div class='infoWin-general'>"+ general +"</div>"}
			
			var address = opt_opts.address || "";
			if(address != "") {address = "<div class='infoWin-address'><span class='infoWin-label'>Address:</span>" + address + "</div>"}
			
			var phone = opt_opts.phone || "";
			if(phone != "") {phone = "<div class='infoWin-phone'><span class='infoWin-label'>Phone: </span>" + phone + "</div>"}
			
			var email = opt_opts.email || "";
			if(email != "") {email = "<div class='infoWin-email'><span class='infoWin-label2'>Email:</span> <a href=\"mailto:"+ email + "\">"+ email +"</a></div>"}
			
			var hrs = opt_opts.hrs || "";
			if(hrs != "") {hrs = "<div class='infoWin-hrs'><span class='infoWin-label'>Hours</span>" + hrs + "</div>"}
			
			var city = opt_opts.city || "";			
			var prov = opt_opts.prov || "";
			var local = "";
			if((city != "") && (prov != "")) {local = "<div class='infoWin-local'>" + city +", "+ prov + "</div>"}
			
			var siteUrl = opt_opts.siteUrl || "";
			if(siteUrl != "") {siteUrl = "<div class='infoWin-url'><span class='infoWin-label'>Website:</span><a target=\"_blank\" href=\"" + siteUrl + "\">"+ siteUrl + "</a></div>"}
			
			var mapUrl = opt_opts.mapUrl || "";
			if(mapUrl != "") {mapUrl = "<div class='infoWin-url'><a target=\"_blank\" href=\"" + mapUrl + "\">View Map</a></div>"}
			
			var photos = (opt_opts.photos.length > 0) ? opt_opts.photos : false;
			var photoTab = "";
			var photoContent = "";
			
			// Fetch photos if current icon has them
			if (photos) {
				photoTab = '<li id="tab1">Photos</li>';
				photoContent ='<div id="tab1_content">';				
				for (var i=0; i<photos.length; i++){
					photoContent += '<a href="' + SAIT.Map.PATH_PHOTOS + photos[i].getAttribute("filename") + '" rel="lightbox[' + id +']" title="' + photos[i].getAttribute("caption")+ '"><img src="' + SAIT.Map.PATH_THUMBNAILS + "tn_" + photos[i].getAttribute("filename") + '" /></a>';
				}
				photoContent += '</div>';
			}

			// Open ExtInfoWindow with parameters
			marker.openExtInfoWindow (
				map,
				"custom_info_window_red",
				 "<ul id='infoWin-tabsHeader'>" +
					"<li id='tab0'>Info</li>" + photoTab + 
				"</ul>" +
				"<div class='infoWin-title'>" + name + "</div>" +
				"<div class='infoWin-section'>" + 
					"<div id='tab0_content'>" +	general + address + local + phone + email + hrs + siteUrl + mapUrl + "</div>" +
					photoContent +
				"</div>",
				{beakOffset: 3}
			);
	
			// Set-up the tabs for the ExtInfoWindow
			var tabs = new Array(document.getElementById("tab0"),document.getElementById("tab1"));
			
			if(tabs.length > 0){
				var tabContentsArray = new Array(tabs.length);
				tabs[0].className += " active";
				
				for(i=0; i<tabs.length; i++){					
					tabContentsArray[i] = document.getElementById("tab"+ i +"_content");
					if (tabContentsArray[i] != null) {
						if(i > 0){ SAIT.Map._hideContent(tabContentsArray[i]); }
						
						tabs[i].setAttribute("name", i.toString());						
						
						// IE only - hover pseudo class fix
						if (tabs[i].attachEvent) {
							GEvent.addDomListener(tabs[i],"mouseover",function(){
								this.className += " sfhover";
							});
							
							GEvent.addDomListener(tabs[i],"mouseout",function(){
								this.className = this.className.replace(new RegExp(" sfhover\\b"), "");
							});
						};
						
						
						GEvent.addDomListener(tabs[i],"click",function(){
							var tabIndex = this.getAttribute("name");						
							for(tabContentIndex=0; tabContentIndex<tabs.length; tabContentIndex++){
								//alert("Before: ("+ tabs[tabContentIndex].id + ") " +tabs[tabContentIndex].className);
								tabs[tabContentIndex].className = tabs[tabContentIndex].className.replace(new RegExp("\w?active\\b"), "");
								if(tabContentIndex == tabIndex){
									tabs[tabContentIndex].className += " active"
									SAIT.Map._showContent(tabContentsArray[tabContentIndex]);
								}else{
									SAIT.Map._hideContent(tabContentsArray[tabContentIndex]);
								}
								//alert("After: ("+ tabs[tabContentIndex].id + ") " +tabs[tabContentIndex].className);
							}
							map.getExtInfoWindow().resize();
						}); // end GEvent.addDomListener
					} // end if
				} // end for
			} // end if
		},
		
		/**
     * Helper function to hide the given DOM element
     * 
		 * @param {Object} element The DOM element that should be hidden
    */
      _hideContent: function(element){
        element.style.display = "none";
        element.style.position = "absolute";
      },
    /**
     * Helper function to show the given DOM element
     * 
		 * @param {Object} element The DOM element that should be displayed
    */
      _showContent: function(element){
        element.style.display = "block";
        element.style.position = "relative";
      },
		
		/**
		 * Method to create SAIT google map markers. Calls out to a php file to 
		 * generate the xml file. It then cycles through the xml file
		 * and extracts the required data.
		 *
		 * @param none
		*/
		_initSaitMarkers: function() {
			var map = SAIT.Map._mapContainer;
			
			GDownloadUrl(SAIT.Map.PATH_XML_MARKERS, function(data) {
				var xml = GXml.parse(data);
				var markers = xml.documentElement.getElementsByTagName("marker");
								
				for (var i=0; i < markers.length; i++) {
					var marker = SAIT.Map._createMarker(markers[i]);					
					map.addOverlay(marker);
					
					var category_id = markers[i].getAttribute("category_id");
					var showOnLoad = markers[i].getAttribute("showOnLoad");
					
					SAIT.Map._categories[category_id].overlays.push(marker);
					if(showOnLoad == '0') {marker.hide();}					
				} // end for
			});
		},
		
		/**
		 * Method to create SAIT google map polygons. Calls out to a php file to 
		 * generate the xml file. It then cycles through the xml file
		 * and extracts the required data.
		 *
		 * @param none
		*/
		_initSaitPolygons: function() {
			var map = SAIT.Map._mapContainer;
			
			GDownloadUrl(SAIT.Map.PATH_XML_POLYGONS, function(data) {
				var xml = GXml.parse(data);
				var polygons = xml.documentElement.getElementsByTagName("polygon");
				
				for (var i = 0; i < polygons.length; i++) {
					var polygon = SAIT.Map._createPolygon(polygons[i]);
					map.addOverlay(polygon);
				
					var category_id = polygons[i].getAttribute("category_id");
					var showOnLoad = polygons[i].getAttribute("showOnLoad");
					var type = polygons[i].getAttribute("type");
					
					SAIT.Map._categories[type].overlays.push(polygon);					
					if(showOnLoad == '0') {
						polygon.hide();
					}
				} // end for
			});
		},

		/**
		 * Method to set the focus of the map on another center point.
		 *
		 * @param {String} this.value Value of the selected drop down item
		*/
		setMapFocus: function() {			
			var map = SAIT.Map._mapContainer;			
			var args = this.value.split(',');
			
			SAIT.Map._clearMap();
			
			map.setCenter(new GLatLng(args[0],args[1]), parseInt(args[2]));
			
			for (var i in SAIT.Map._categories) {
				if (SAIT.Map._categories[i].showOnLoad) {
					for (var j=0; j<SAIT.Map._categories[i].overlays.length; j++) {
						SAIT.Map._categories[i].overlays[j].show();
						var chk = document.getElementById("opt_"+[i]);
						if (chk != null) {chk.checked = true}
					} 
				} // end if
			} // end for			
		},
		
		/**
		 * Method to initialize map controls such as Campus dropdown menu,
		 * search button, and map option checkboxes
		 *
		 * @param {none} 
		*/
		_initMapControls: function() {
			var campus = document.getElementById(SAIT.Map.SELECT_CAMPUS_ID);
			if(campus != null) { SAIT.Util._addEvent(campus, "change", SAIT.Map.setMapFocus) }
			
			var findBtn = document.getElementById(SAIT.Map.BTN_SEARCH);
			if(findBtn != null) {SAIT.Util._addEvent(findBtn, "click", SAIT.Map.doSearch)}
			
			var chk = SAIT.Util._getElementsByClassName(SAIT.Map.CHK_MAP_OPTIONS,"input");
			for(i=0; i<chk.length; i++) {				
					SAIT.Util._addEvent(chk[i],"click", SAIT.Map.toggleOverlays)
			} // end for
		},
		
		/**
		 * Method to load and initialize the map, markers, polygons, and
		 * map controls
		 *
		 * @param {none} 
		*/
		load: function() {
			if (GBrowserIsCompatible()) {
				var map = SAIT.Map._mapContainer = new GMap2(document.getElementById("map"));
				
				var loadingImg = document.getElementById("map");
				loadingImg.style.backgroundImage = "url(images/map-loader.gif)";
				loadingImg.style.backgroundRepeat = "no-repeat";
				loadingImg.style.backgroundPosition = "center";

				if(map !=  null) {
					//Center map & set Map Type
					map.setCenter(SAIT.Map.SAIT_LOCATION, SAIT.Map.SAIT_ZOOM);
					map.setMapType(G_HYBRID_MAP);
					
					//Default Google Map Controls
					map.addControl(new GSmallMapControl());						
					map.addControl(new GMapTypeControl());						
					
					//Load up Overlays: Markers & Polygons
					SAIT.Map._initSaitMarkers();
					SAIT.Map._initSaitPolygons();
					
					// Initialize Custom Map Controls
					SAIT.Map._initMapControls();
					
					// Initialize LocalSearch
					SAIT.Map._initializeMapSearch();
				} // end if
				
			} // end if
		}
			
	};
	
/**
 * Returns the GMap marker for this result, creating it with the given icon if it 
 * has not already been created.
 *
 * @param: none
*/
SAIT.Map._localResult.prototype.marker = function() {
	
	if (this.marker_) return this.marker_;
	
	var point = new GLatLng(parseFloat(this._result.lat), parseFloat(this._result.lng));	
	var iCustom = new GIcon(G_DEFAULT_ICON);
	iCustom.image = SAIT.Map.PATH_ICONS + "searchresult.png";
	var iconOptions = { "icon": iCustom, "title": this._result.titleNoFormatting }
	
	var phone = "";
	if (typeof this._result.phoneNumbers != "undefined") { phone = this._result.phoneNumbers[0]["number"]; }
	
	var marker = new GMarker(point,iconOptions);
	
	var infoWindowOptions = {
		"name": this._result.titleNoFormatting,
		"address": this._result.streetAddress,
		"city": this._result.city,
		"prov": this._result.region,
		"phone": phone,
		"mapUrl": this._result.url
	};
	
	SAIT.Map._createInfoWindow(marker, infoWindowOptions);
  	
	this.marker_ = marker;
  return marker;
};

SAIT.Util._addEvent(window, "load", SAIT.Map.load);
