;(function($) {
	$.fn.svGoogleMaps = function(options) {
		var $svGM = $.fn.svGoogleMaps;
		
		$svGM.args = $.extend({}, $svGM.defaults, options);
		$svGM.args.mapObj = this.get(0);
		$svGM.args.mapName = this.attr('id').substring(4);
		$svGM.args.placemarks[$svGM.args.mapName] = $svGM.preparePlacemarks($svGM.args.pMarks);
		$svGM.initialInfoWindow = function() {
			// Empty function
		};
		
		/*
		 * Overlays
		 */
		$svGM.ov = {
			initial: Overlays()
		};
		
		$svGM.ov = $.extend({}, $svGM.ov, {
			direction: DirectionOverlays(),
			itinerary: ItineraryOverlays(),
			pinned: PinnedOverlays(),
			custom: CustomOverlays(),
			local_search: LocalSearchOverlays()
		});
		
		$svGM.args.m = new Map($svGM.args.mapName, "map_" + $svGM.args.mapName, $svGM.args.defaultLat, $svGM.args.defaultLng, $svGM.args.defaultZoom);
		$svGM.initOverlayCollections($svGM.args.showPlacemarkListings, $svGM.args.markPlacemarkListings);
		$svGM.args.m.create();
		
		var curDate = new Date();
		$svGM.loadItinerary = $.getJSON($svGM.args.fuse_root + '/includes/cftags/GoogleMaps/Helpers/Itinerary.cfc?method=getItinJSON&timestamp=' + curDate.getTime(), function(data) {
			if (typeof data !== 'undefined' && data !== null) {
				// if no items in the itinerary, change the text and 
				if (!data.itinArray.length) {
					jQuery(jQuery.fn.svGoogleMaps.args.iContain+' .gContent').html('You currently have no listings in your Trip Planner. Start planning your trip by searching the map below and clicking the "Add to Trip Planner" button on a listing.');
					return true;
				}
				for (var i = 0; i < data.itinArray.length; i++) {
					$svGM = jQuery.fn.svGoogleMaps;
					if (($svGM.args.mapType == 'detailMap' && $svGM.args.placemarks[$svGM.args.mapName][0].prikey == data.itinArray[i].RECID)
							|| $svGM.args.mapType !== 'detailMap') {
						$svGM.updatePlacemarkItinerary(data.itinArray[i].RECID);
					}
				}
			}
			//window.setTimeout(jQuery.fn.svGoogleMaps.initialInfoWindow, 500);
		});
		
		/*$svGM.loadItinerary = $svGM.args.loadItin;
		$svGM.loadItinerary();*/
		
		//Intialize Directions Object
		if ($svGM.args.showDirections) {
			$svGM.args.directions = new DrivingDirections($svGM.args.mapName, $svGM.args.m);
			$svGM.args.directions.init();
		}
		
		//Initialize Map
		var startMapExplorer = function() {
			var $svGM = $.fn.svGoogleMaps;
			//$svGM.args.m.gmap.addMapType(google.maps.PHYSICAL_MAP);
			//$svGM.args.m.gmap.addControl(new google.maps.HierarchicalMapTypeControl());
			
			// Add ExtMapTypeControl with options
			var ext = new ExtMapTypeControl({ posRight: 215, showTraffic: true, showMore: true, layers: { photos: true, wikipedia: true } });
			$svGM.args.m.gmap.addControl(ext);
			
			// Add ContextMenuControl to the map
			/*$svGM.args.m.gmap.addControl(new ContextMenuControl({whatsHere: false}));*/
			
			//Make sure they are initialized with filter flags
			$svGM.registerFilters();
			$svGM.runFilters();
			
			if ($svGM.args.action == 'nearby' && $svGM.args.listingID.length > 0) {
				var foundMarker = $svGM.findPlacemark($svGM.args.listingID);
				if (foundMarker != null) {
					$svGM.updatedFilters([foundMarker]);
					$svGM.findNearBy($svGM.args.listingID);
				} else {
					//alert('could not find listing');
				}
				if ($svGM.args.showPrint.length > 0 && $svGM.args.markerFrom.length > 0 && $svGM.args.markerTo.length > 0) {
					$svGM.args.directions.getDirections($svGM.args.markerFrom, $svGM.args.markerTo);
				}
			}
		};
		
		//Initialize Map
		var startListings = function() {
			var $svGM = $.fn.svGoogleMaps;
			
			// Open the first info window
			$svGM.initialInfoWindow = function() {
				var p = $svGM.args.placemarks[$svGM.args.mapName][0];
				p.marker.openInfoWindowHtml(parsePlacemarkData(p.infoWindowPlaceholder, p));
				p.collection.execHandler('openinfobubble', p);
			}
			
			//$svGM.args.m.gmap.addMapType(google.maps.PHYSICAL_MAP);
			//$svGM.args.m.gmap.addControl(new google.maps.HierarchicalMapTypeControl());
			
			// Add ExtMapTypeControl with options
			var ext = new ExtMapTypeControl({ posRight: 215, showTraffic: false, showMore: false, layers: { photos: true, wikipedia: true } });
			$svGM.args.m.gmap.addControl(ext);
			
			// Add ContextMenuControl to the map
			/*$svGM.args.m.gmap.addControl(new ContextMenuControl({whatsHere: false}));*/
			
			/*
			 * We are going to use the default icons (so no category-specific ones) and display up to 150 placemarks per page
			 */
			$svGM.ov.initial.catIcons = false;
			$svGM.ov.initial.pagesize = 150;
			
			/*
			 * Pass in all of the placemarks to be displayed
			 */
			$svGM.updatedFilters($svGM.args.placemarks[$svGM.args.mapName]);
		};
		
		//Initialize Map
		var startDetailed = function() {
			var $svGM = $.fn.svGoogleMaps;
			
			// Open the first info window
			$svGM.initialInfoWindow = function() {
				var p = $svGM.args.placemarks[$svGM.args.mapName][0];
				p.marker.openInfoWindowHtml(parsePlacemarkData(p.infoWindowPlaceholder, p));
				p.collection.execHandler('openinfobubble', p);
			}
			
			//$svGM.args.m.gmap.addMapType(google.maps.PHYSICAL_MAP);
			//$svGM.args.m.gmap.addControl(new google.maps.HierarchicalMapTypeControl());
			
			// Add ExtMapTypeControl with options
			var ext = new ExtMapTypeControl({ posRight: 215, showTraffic: false, showMore: false, layers: { photos: true, wikipedia: true } });
			$svGM.args.m.gmap.addControl(ext);
			
			// Add ContextMenuControl to the map
			/*$svGM.args.m.gmap.addControl(new ContextMenuControl({whatsHere: false}));*/
			
			/*
			 * We are going to use the default icons (so no category-specific ones) and display up to 150 placemarks per page
			 */
			$svGM.ov.initial.catIcons = false;
			$svGM.ov.initial.pagesize = 150;
			
			/*
			 * Pass in all of the placemarks to be displayed
			 */
			$svGM.updatedFilters($svGM.args.placemarks[$svGM.args.mapName]);
		};
		
		if ($svGM.args.mapType == 'mapExplorer') {
			startMapExplorer();
		} else if ($svGM.args.mapType == 'detailMap') {
			startDetailed();
		} else {
			startListings();
		}
		
		if ($svGM.args.showLocalSearch && $svGM.args.searchContain) {
			google.load('search', '1', {nocss: true, callback: jQuery.fn.svGoogleMaps.instantiateLocalSearch});
		}

		return this;
	};
	
	$.fn.svGoogleMaps.defaults = {
		mContent: '#gMainContent',
		dContain: '#gDirectionsContainer',
		pContain: '#gPlacemarkContainer',
		iContain: '#gItineraryContainer',
		fContain: '#gFilterContainer',
		mContain: '#gMapContainer',
		catContain: '#gCategoryFilterContainer',
		catFilterList: '.gCatList',
		catFilterTitle: '.gCatTitle',
		subCatFilterList: '.gSubCatList',
		subCatFilterTitle: '.gSubCatTitle',
		searchContain: '',
		listingNoImage: 'notavailable.gif',
		maps: {},
		placemarks: {},
		mapObj: {},
		m: {},
		customprikey: 0,
		listingID: '',
		localSearchPriKey: 0,
		directionsPriKey: 0,
		directions: '',
		placemarkHtml: '',
		defaultLat: '',
		defaultLng: '',
		defaultZoom: 12,
		miniZoom: 13,
		itinLookup: {},
		showPrint: false,
		showLocalSearch: true,
		currPanoPoint: null,
		svPano: null
	};
	
	$.extend($.fn.svGoogleMaps, {
		objs: {},
		
		goToPlacemark: function(prikey) {
			var p = this.findPlacemark(prikey);

			/*
			** @change: abastidas
			** @ticket: 50959
			** when "map it" links are clicked, we want to make sure and expand the map
			** if it's currently closed
			*/
			if ($('.mapHolder .gmapBox').css('display') == "none") {
				$('.handle').html('Click to hide mapped events');
				$(".mapHolder .gmapBox").show("blind", {direction:"vertical"}, 1000);
			}
			
			jQuery.scrollTo("#map_" + this.args.mapName, 400, {axis:"y", offset:-50});
			p.marker.openInfoWindowHtml(parsePlacemarkData(p.infoWindowPlaceholder, p));
			
			
			return false;
		},
		
		initOverlayCollections: function(showPlacemarkListings, markListings) {
			//Initialize Variables and Event Handlers
			if (showPlacemarkListings == true)
				this.ov.initial.addHandler("showhide", this.ov.initial.showPlacemarkListings, true);
			
			if (markListings == true)
				this.ov.initial.addHandler("showhide", this.ov.initial.markPlacemarkListings, true);
			
			this.ov.initial.addHandler("openinfobubble", this.infoWindowOpen, true);
			this.ov.pinned.addHandler("openinfobubble", this.infoWindowOpen, true);
			this.ov.itinerary.addHandler("openinfobubble", this.infoWindowOpen, true);
			
			this.ov.initial.catIcons = true;
			
			this.ov.pinned.getInfoHTML = this.ov.itinerary.getInfoHTML = this.ov.initial.getInfoHTML = function() {
				return jQuery.fn.svGoogleMaps.args.infoWindowHTML;
			};
			
			//Initialize Variables and Event Handlers
			this.ov.itinerary.addHandler('showhide', this.ov.itinerary.showListings, true);
			
			this.args.m.addCollection(this.ov.initial, true);
			this.args.m.addCollection(this.ov.pinned, false);
			this.args.m.addCollection(this.ov.direction, false);
			this.args.m.addCollection(this.ov.custom, false);
			this.args.m.addCollection(this.ov.itinerary, false);
			this.args.m.addCollection(this.ov.local_search, false);
			
			//Initialize Variables and Event Handlers
			//this.ov.pinned.addHandler("showhide", this.ov.pinned.showPinnedListings, true);
			
			//Initialize Variables and Event Handlers
			//this.ov.itinerary.addHandler("showhide", this.ov.itinerary.markPlacemarkListings, true);
			this.ov.itinerary.addHandler("gotoplacemark", this.goToPlacemark, true);
		},
		
		transferFromOverlays: function(prikey, dstCollection, cancelHandlers) {
			var placemark = this.findPlacemark(prikey);
			
			if (placemark !== null) {
				placemark.active = false;
				
				this.ov.initial.removePlacemark(placemark, cancelHandlers);
				dstCollection.addPlacemark(placemark, cancelHandlers);
				dstCollection.showPlacemark(placemark, cancelHandlers);
				
				//dstCollection.showPlacemarks(dstCollection.currPage, cancelHandlers);
				this.ov.initial.showPlacemarkListings();
			}
		},
		
		transferToOverlays: function(prikey, srcCollection, cancelHandlers) {
			var placemark = this.findPlacemark(prikey);
			
			if (placemark !== null) {
				placemark.active = true;
				
				this.ov.initial.sortBy("name");
				
				srcCollection.removePlacemark(placemark, cancelHandlers);
				this.ov.initial.addPlacemark(placemark, cancelHandlers);
				this.ov.initial.showPlacemark(placemark, cancelHandlers);
				
				//this.ov.initial.showPlacemarks(this.ov.initial.currPage, cancelHandlers);
				this.ov.initial.showPlacemarkListings();
			}
		},
		
		//Pin an overlay to the map (make permanent)
		pinMe: function(prikey, cancelHandlers) {
			if (typeof cancelHandlers == 'undefined')
				cancelHandlers = false;
			
			var placemark = this.findPlacemark(prikey);
			placemark.active = false;
			
			if (placemark.collection != this.ov.pinned) {
				placemark.pinned = true;
				
				placemark.pinnedsource = placemark.collection;
				
				placemark.collection.removePlacemark(placemark, cancelHandlers);
				this.ov.pinned.addPlacemark(placemark, cancelHandlers);
				this.ov.pinned.showPlacemarks(1, cancelHandlers);
			}
		},
		
		//UnPin an overlay to the map
		unpinMe: function(prikey, cancelHeaders) {
			if (typeof cancelHandlers == 'undefined')
				cancelHandlers = false;
			
			var placemark = this.findPlacemark(prikey);
			placemark.active = true;
			placemark.pinned = false;
				
			this.ov.pinned.removePlacemark(placemark, cancelHandlers);
			placemark.pinnedsource.addPlacemark(placemark, cancelHandlers);
			placemark.pinnedsource.showPlacemarks(placemark.collection.currPage, cancelHandlers);
			
			placemark.pinnedsource = null;
		},
		
		//This function sets up the filter fields on each placemark
		preparePlacemarks: function(placemarks) {
			for (var i = 0; i < placemarks.length; i++) {
				if (placemarks[i].latitude.length == 0 || placemarks[i].longitude.length == 0) {
					placemarks.splice(i, 1);
					i = i - 1;
				} else {
					placemarks[i] = jQuery.extend({}, placemarks[i], {
						filteredBy: new Object(),
						filtered: false,
						active: true,
						pinned: false,
						point: null,
						marker: null,
						itinerary: false,
						infoWindowPlaceholder: ''
					});
				}
			}
			
			return placemarks;
		},
		
		//Run all filters
		runFilters: function() {
			for (var i in this.args.m.allFilters) {
				this.args.m.allFilters[i].run();
			}
		},
		
		registerFilters: function() {
			var catFilter = new CategoryFilter();
			this.args.maps[this.args.mapName].registerFilter("catFilter", catFilter);
			
			var distanceFilter = new DistanceFilter();
			this.args.maps[this.args.mapName].registerFilter("distanceFilter", distanceFilter);
		},
		
		//Runs whenever the filters are updated
		updatedFilters: function(unfiltered) {
			this.args.m.defaultCollection.removePlacemarks(true);
			this.args.m.defaultCollection.addPlacemarks(unfiltered, true);
			this.args.m.defaultCollection.showPlacemarks(1, false);
		},
		
		//Find a placemark in the placemarks collection
		findPlacemark: function(placemarkID, mName) {
			var name = typeof mName == 'undefined' ? this.args.mapName : mName;
			
			for (var i = 0; i < this.args.placemarks[name].length; i++){
				if (this.args.placemarks[name][i].prikey == placemarkID)
					return this.args.placemarks[name][i];
			}
			return null;
		},
		
		swapInfoTab: function(prikey, selTab, updateHeaders) {
			var ptabs = "Description,Directions,Email,CustomAddress,Street".split(",");
			if (updateHeaders) {
				//Mark all tab headers as unselected
				jQuery(".infoTab").each(function(e) { jQuery(this).removeClass("tabActive"); });
				//Mark clicked header as selected
				jQuery("#infoTab" + selTab).each(function(e) { jQuery(this).addClass("tabActive"); });
			}
			
			for (var i = 0; i < ptabs.length; i++) {
				jQuery("#infoTab_" + ptabs[i] + "_" + prikey).hide();
			}
			
			var infoWindow = jQuery.fn.svGoogleMaps.args.m.gmap.getInfoWindow();
			
			if (selTab == 'Street') {
				jQuery("#infoTab_" + selTab + "_" + prikey).show();
			} else {
				jQuery("#infoTab_" + selTab + "_" + prikey).css('opacity', '0').css('display', 'block');
			}
			
			jQuery.fn.svGoogleMaps.args.m.gmap.updateInfoWindow(infoWindow.getTabs());
			
			if (selTab != 'Street') {
				jQuery("#infoTab_" + selTab + "_" + prikey).animate({opacity: 1}, 750);
			}	
			
			return false;
		},
		
		
		/* Begin Driving Directions Code */
		
		//Loads the list of currently visible markers to choose as a destination when getting driving directions
		loadMarkerList: function(prikey) {
			var markerFrom = jQuery("#markerFrom").get(0);
			if (markerFrom) {
				markerFrom.options.length = 0;
				var placemarks = this.args.m.getVisiblePlacemarks();
				for (var i = 0; i < placemarks.length; i++) {
					if (placemarks[i].prikey != prikey && placemarks[i].prikey.indexOf('custom') == -1) {
						var o = new Option();
						o.value = placemarks[i].prikey;
						
						if (placemarks[i].prikey.indexOf('localSearch') > -1) {
							o.text = placemarks[i].name + ': ' + placemarks[i].addr1 + ', ' + placemarks[i].city + ', ' + placemarks[i].state;
						} else {
							o.text = placemarks[i].name;
						}
						
						if (o.text.length > 40)
							o.text = o.text.substring(0, 37) + "...";
						
						markerFrom.options[markerFrom.options.length] = o;
					}
				}
				if (markerFrom.options.length == 0) {
					var o = new Option();
					o.value = '';
					o.text = '---No Locations Available---';
					markerFrom.options[0] = o;
					markerFrom.disabled = true;
				}
			}
		},
		
		addToDirectionOverlays: function(prikey) {
			var placemark = this.findPlacemark(prikey);
			
			if (placemark.collection.name != this.ov.direction.name) {
				placemark.active = false;
				placemark.directionsource = placemark.collection;
				
				placemark.collection.removePlacemark(placemark);
				this.ov.direction.addPlacemark(placemark);
				this.ov.direction.showPlacemark(placemark);
			}
		},
		
		removeFromDirectionOverlays: function(prikey, rDir) {
			var placemark = this.findPlacemark(prikey);
			
			if (placemark.collection == this.ov.direction) {
				placemark.active = true;
				
				placemark.collection.removePlacemark(placemark);
				
				if (placemark.directionsource.name != this.ov.custom.name || rDir) {
					placemark.directionsource.addPlacemark(placemark);
				} else {
					placemark.directionsource.removePlacemark(placemark);
					placemark.directionsource = null;
					placemark.collection = null;
					delete placemark;
				}
				
				placemark.directionsource = null;
				
				if (placemark.collection) {
					placemark.collection.sortBy("name");
					
					placemark.collection.showPlacemarks(placemark.collection.currPage);
				}
			}
		},
		
		clearDirections: function(delMarks, rDir) {
			if (!rDir || rDir != true) {
				if (this.args.m.circle) {
					this.args.m.gmap.addOverlay(this.args.m.circle);
				}
				jQuery(this.args.mContent + ', ' + this.args.iContain + ', ' + this.args.fContain + ', ' + this.args.mContain + ', ' + this.args.pContain + ', ' + this.args.dContain).removeClass('gDirectionsWide');
				this.args.m.gmap.checkResize();
			}
			
			if (this.args.directions.placemarkToField && this.args.directions.placemarkToField.val().length > 0) {
				var prikey = this.args.directions.placemarkToField.val();
				
				this.removeFromDirectionOverlays(prikey, rDir);
				this.args.directions.placemarkToField.val('');
			}
			
			if (this.args.directions.placemarkFromField && this.args.directions.placemarkFromField.val().length > 0) {
				var prikey = this.args.directions.placemarkFromField.val();
				
				this.removeFromDirectionOverlays(prikey, rDir);
				this.args.directions.placemarkFromField.val('');
			}
			this.args.directions.clearDirections();
			
			if (delMarks && delMarks == true) {
				for (var i = 0; i < this.args.placemarks[this.args.mapName].length; i++) {
					if (String(this.args.placemarks[this.args.mapName][i].prikey).search('custom') != -1)
						this.args.placemarks[this.args.mapName].splice(i);
				}
			}
			if (this.args.listingID.length > 0)
				this.pinMe(this.args.listingID);
		},
		
		reverseDirections: function() {
			var src = this.args.directions.placemarkFromField.val();
			var dst = this.args.directions.placemarkToField.val();
			
			this.getDirections(src, dst, true);
		},
		
		getMarkerDirections: function(prikeyFrom, prikeyTo) {
			if(jQuery(".infoTab_Directions input[type=radio][name=direction]:checked").val() == "to") {
				this.getDirections(prikeyTo, prikeyFrom);
			} else {
				this.getDirections(prikeyFrom, prikeyTo);
			}
		},
		
		getDirections: function(prikeyFrom, prikeyTo, rDir) {
			var pFrom, pTo;
			
			this.clearDirections(false, rDir);
			
			if (!rDir) {
				if (this.args.m.circle) {
					this.args.m.gmap.removeOverlay(this.args.m.circle);
				}
				jQuery(this.args.mContent + ', ' + this.args.iContain + ', ' + this.args.fContain + ', ' + this.args.mContain + ', ' + this.args.pContain + ', ' + this.args.dContain).addClass('gDirectionsWide');
				this.args.m.gmap.checkResize();
			}
			
			if (prikeyFrom) {
				pFrom = this.findPlacemark(prikeyFrom);
				this.args.directions.directionsFrom(prikeyFrom);
			} else {
				pFrom = this.args.directions.src;
			}
			
			if (prikeyTo) {
				pTo = this.findPlacemark(prikeyTo);
				this.args.directions.directionsTo(prikeyTo);
			} else {
				pTo = directions.dst;
			}
			
			pFrom.isDst = 1;
			pTo.isDst = 0;
			
			if (pFrom.marker)
				pFrom.marker.closeInfoWindow();
			if(pTo.marker)
				pTo.marker.closeInfoWindow();
			
			if (!this.args.m.collections.directionOverlays.check(prikeyTo)) {
				this.addToDirectionOverlays(prikeyTo);
			}
			
			if(!this.args.m.collections.directionOverlays.check(prikeyFrom)) {
				this.addToDirectionOverlays(prikeyFrom);
			}
			
			this.args.directions.getDirectionsTo(pFrom, pTo);
			
			return false;
		},
		
		addAddress: function(prikey) {
			var name = jQuery("#custom").val();
			//Read Address Fields
			var toFrom = (this.addAddress.arguments.length>1 && (this.addAddress.arguments[1]=='to' || this.addAddress.arguments[1]=='from')) ? this.addAddress.arguments[1] : '';
			
			var g = new google.maps.ClientGeocoder();
			g.getLocations(name, this.addCustomFromGeocoder);
			
			if ((toFrom && toFrom=='to') || (!toFrom && jQuery(".infoTab_CustomAddress input[type=radio][name=directionCustom]:checked").val() == "to")) {
				this.args.directions.placemarkFromField.val(prikey);
			} else {
				this.args.directions.placemarkToField.val(prikey);
			}
		},
		
		addCustomFromGeocoder: function(results) {
			/*
			 * Since we're being called from a callback, 'this' does not point to the right place...
			 */
			var $svGM = jQuery.fn.svGoogleMaps;
			
			var name = jQuery("#custom").val();
			var o = $svGM.defaultPlacemark();
			
			o = $svGM.parseGeocodingResults(results, o);
			
			$svGM.args.placemarks[$svGM.args.mapName].push(o);
			
			$svGM.ov.custom.addPlacemark(o);
			
			if (jQuery(".infoTab_CustomAddress input[type=radio][name=directionCustom]:checked").val() == "to") {
				$svGM.args.directions.placemarkToField.val(o.prikey);
			} else {
				$svGM.args.directions.placemarkFromField.val(o.prikey);
			}
			$svGM.getDirections($svGM.args.directions.placemarkFromField.val(), $svGM.args.directions.placemarkToField.val());
		},
		
		parseGeocodingResults: function(results, o) {
			if (results.Status.code != 200) {
				alert("We're sorry, but we couldn't find that address.");
				return null;
			} else{
				var p = results.Placemark[0];
				o.latitude = p.Point.coordinates[1];
				o.longitude = p.Point.coordinates[0];
				o.point = new google.maps.LatLng(o.latitude,o.longitude);
				o.iconstyle = "default";
				o.description = "";
				o.weburl = "";
				
				if (p.address)
					o.name = p.address;
				
				if (p.AddressDetails.Country) {
					var currLevel = p.AddressDetails.Country;
					o.country = currLevel.CountryNameCode;
					
					if (currLevel.AdministrativeArea) {
						var prevLevel = currLevel;
						currLevel = currLevel.AdministrativeArea;
						o.state = currLevel.AdministrativeAreaName;
						
						if (p.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea) {
							prevLevel = currLevel;
							currLevel = p.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea;
						}
						if (currLevel.Locality) {
							prevLevel = currLevel;
							currLevel = currLevel.Locality;
							o.city = currLevel.LocalityName;
							
							if (currLevel.PostalCode)
								o.zip = currLevel.PostalCode.PostalCodeNumber;
							
							if (currLevel.Thoroughfare) {
								currLevel = currLevel.Thoroughfare;
								o.addr1 = currLevel.ThoroughfareName;
								o.name = o.addr1;
							}
						}
					}
				}
			}
			return this.preparePlacemarks([o])[0];
		},
		
		parseLocalSearchResult: function(result, o) {
			o.prikey = "localSearch_" + (++this.args.localSearchPriKey);
			o.latitude = result.lat;
			o.longitude = result.lng;
			o.point = new google.maps.LatLng(o.latitude,o.longitude);
			o.iconstyle = 'default';
			o.description = '';
			o.name = result.titleNoFormatting;
			o.weburl = result.url;
			o.country = result.country;
			o.state = result.region;
			o.city = result.city;
			o.zip = result.zip;
			o.addr1 = result.streetAddress;
			
			return this.preparePlacemarks([o])[0];
		},
		
		//Create a blank custom placemark and add it to the "custom" collection
		defaultPlacemark: function(name) {
			var o = new Object();
			o.name = "";
			o.prikey = "custom_" + (++this.args.customprikey);
			o.addr1 = "";
			o.addr2 = "";
			o.addr3 = "";
			o.city = "";
			o.state = "";
			o.zip = "";
			o.country = "";
			o.description = "";
			o.weburl = "";
			o.active = false;
			o.filteredBy = new Object();
			o.filtered = false;
			o.phone = "";
			o.iconstyle = "default";
			
			return o;
		},
		/*End Driving Directions Code*/
		
		findNearBy: function(prikey) {
			if (jQuery("#distanceFromID").val().length > 0) {
				this.clearNearBy();
				this.unpinMe(jQuery("#distanceFromID").val(), true);
				jQuery("#distanceFromID").val("");
			}
			jQuery("#" + this.args.mapName + "_DistanceFilter .widgetContCont").show();
			
			this.pinMe(prikey,true);
			
			jQuery("#distanceFromID").val(prikey);
			this.args.m.allFilters.distanceFilter.run();
			
			return false;
		},
		
		clearNearBy: function() {
			this.args.m.circle = null;
			this.args.m.cancelCentering = false;
			jQuery('#' + this.args.mapName + '_distance').val('');
			this.runFilters();
			
			return false;
		},
		
		clearFilters: function() {
			/*
			 * Hide subcats and uncheck selected cats and subcats
			 */
			jQuery(this.args.catContain + ' li.gCatList div.gSubCatList').hide("normal");
			
			var checkedList = jQuery(this.args.catContain + ' input[type="checkbox"]');
			for (var i = 0; i < checkedList.length; i++) {
				if (checkedList[i].checked) {
					checkedList[i].checked = false;
				}
			}
			this.clearNearBy();
		},
		
		email: function(prikey){
			jQuery.ajax({
				url: this.args.emailUrl,
				type: "POST",
				data: {
					listingID: prikey,
					friendemail: jQuery("input[name='mapEmailTo']").val(),
					friendname: jQuery("input[name='mapNameTo']").val(),
					youremail: jQuery("input[name='mapEmailFrom']").val(),
					yourname: jQuery("input[name='mapNameFrom']").val(),
					comments: jQuery("textarea[name='mapEmailNote']").val()
				},
				success: function(data, textStatus) {
					jQuery("#infoTab_Email_" + prikey).html("E-mail sent successfully.");
				},
				error: function(xmlhr, textStatus, errorThrown) {
					jQuery("#infoTab_Email_" + prikey).html("The email could not be sent. Please try again later.");
				}
			});
			jQuery("#infoTab_Email_" + prikey).html("<div style=\"margin:100px auto;text-align:center\"><img src=\"" + imgroot + "/includes/images/loading.gif\" alt=\"Loading\" /></div>");
			
			return false;
		},
		
		infoWindowOpen: function(placemark) {
			client = new google.maps.StreetviewClient();
			client.getNearestPanoramaLatLng(placemark.point, function(point) {
				if (point === null) {
					jQuery('#infoTabStreet').css('display', 'none');
				} else {
					jQuery.fn.svGoogleMaps.args.currPanoPoint = point;
					window.setTimeout(function() {
						jQuery('#infoTabStreet').css('display', 'inline');
						jQuery.fn.svGoogleMaps.loadStreet(jQuery.fn.svGoogleMaps.args.currPanoPoint);
					}, 1000);
				}
			});
		},
		
		loadStreet: function(point) {
			if (point !== null) {
				this.args.svPano = new google.maps.StreetviewPanorama(jQuery("#street").get(0), {latlng: point});
				
				var handlePErrors = function(errorCode) {
					if (errorCode == 603) {
						jQuery("#street").html("Error: Flash doesn't appear to be supported by your browser");
					}
					if (errorCode == 600) {
						jQuery("#street").html("No data found for this location");
					}
					return;
				}
				
				google.maps.Event.addListener(jQuery.fn.svGoogleMaps.args.svPano, "error", handlePErrors);
				google.maps.Event.addListener(jQuery.fn.svGoogleMaps.args.svPano, "initialized", function(loc) { logit('Initialized Streetview'); });
			} else {
				jQuery("#street").html("No data found for this location");
			}
		},
		
		updatePlacemarkItinerary: function(prikey) {
			var p = this.findPlacemark(prikey);
			
			if (p !== null) {
				p.itinerary = !p.itinerary;
				
				if (p.itinerary) {
					jQuery('#hideItin_' + prikey).hide();
					jQuery('#hideItinAdded_' + prikey).show();
					//For updating the listingDetail link
					if ($("#mtListing").length != 0){
						$("#mtListing").html('<a href="../MyTucson" class="eleven" style="color:#A11E24;">Added to myTucson</a>');
					}
				} else {
					jQuery('#hideItin_' + prikey).show();
					jQuery('#hideItinAdded_' + prikey).hide();
				}
				
				if (this.args.showItinerary) {
					p.infoWindowPlaceholder = this.ov.itinerary.getInfoHTML();
					
					if (p.itinerary) {
						this.transferFromOverlays(prikey, this.ov.itinerary);
					} else {
						this.transferToOverlays(prikey, this.ov.itinerary);
					}
				}
			}
		},
		
		clone: function(obj) {
			if (obj == null || typeof(obj) != 'object') 
				return obj;
			
			if (obj.constructor == Array) {
				var temp = [];
				for (var i = 0; i < obj.length; i++) {
					temp.push(obj[i]);
				}
				return temp;
			}
			
			var temp = {};
			for (var key in obj) 
				temp[key] = obj[key];
			
			return temp;
		},
		
		instantiateLocalSearch: function() {
		// load search form
			// search box
			$svGM.objs.searchControl = new google.search.SearchControl();
			searcher = new google.search.LocalSearch(); // create the object
			searcher.setCenterPoint($svGM.args.m.gmap); // bind the searcher to the map
			
			// Create a SearcherOptions object to ensure we can see all results
			var options = new google.search.SearcherOptions(); // create the object
			options.setExpandMode(google.search.SearchControl.EXPAND_MODE_CLOSED);
			// USE THE BELOW TO SET THE DIV CONTAINER FOR THE RESULTS LIST, where d = a div
			//options.setRoot(d);
			
			// Add the searcher to the SearchControl
			$svGM.objs.searchControl.addSearcher(searcher , options);
			
			// callback
			$svGM.objs.searchControl.setSearchCompleteCallback(searcher, function () {
				$svGM.ov.local_search.removePlacemarks(false);
				
				var results = searcher.results;
				var firstPrikey = '';
				for (i = 0; i < results.length; i++) {
					var result = results[i];
					var o = $svGM.defaultPlacemark();
					
					o = $svGM.parseLocalSearchResult(result, o);
					
					$svGM.args.placemarks[$svGM.args.mapName].push(o);
					$svGM.ov.local_search.addPlacemark(o);
					if (i == 0)
						firstPrikey = o.prikey;
				}
				$svGM.ov.local_search.showPlacemarks(1, false);
				
				// Open the info window for the first result
				var p = $svGM.findPlacemark(firstPrikey);
				p.marker.openInfoWindowHtml(parsePlacemarkData(p.infoWindowPlaceholder, p));
			});
		
			$svGM.objs.searchControl.draw(jQuery($svGM.args.searchContain).get(0));
		
			gscInput = jQuery('input.gsc-input');
			if (gscInput.get(0).value==gscInput.get(0).defaultValue) gscInput.get(0).value = 'Search the map...';
			else gscInput.addClass('active');
			gscInput.bind('focus',function (e) {
				if (jQuery(this).get(0).value=='Search the map...') {
					jQuery(this).get(0).value = '';
					jQuery(this).addClass('active');
				}
			});
			gscInput.bind('blur',function (e) {
				if (jQuery(this).get(0).value=='') {
					jQuery(this).get(0).value = 'Search the map...';
					jQuery(this).removeClass('active');
				}
			});
			jQuery('.gsc-clear-button').unbind('click').find('div').click(function() {
				$svGM = jQuery.fn.svGoogleMaps;
				
				$svGM.ov.local_search.removePlacemarks(false);
				
				/*
				 * Remvove the custom Local Search placemarks from the placemarks list
				 */
				for (var i = 0; i < $svGM.args.placemarks[$svGM.args.mapName].length; i++) {
					if (String($svGM.args.placemarks[$svGM.args.mapName][i].prikey).search('localSearch') != -1)
						$svGM.args.placemarks[$svGM.args.mapName].splice(i);
				}
			});
			
			gscHolder = $("#gMapContainer > div.gHeader").css();
			gscHolder.css("padding", "12px 14px 5px 14px");
		// end search form if
		}
	});
})(jQuery);

/*
jQuery(document).ready(function() {
	jQuery('#ListingsExplorer').svGoogleMaps.init();
});
*/
