if(typeof widgets=="undefined") widgets = {};
widgets.gmaps = function(args)
{
	this.args = args;
	var self = this;
	var $ = jQuery;
	
	this.initWidgetMap = function(args)
	{	
		self.map = maps[self.args.mapname] = new Map(self.args.mapname, self.args.mapname, self.args.defaultlat, self.args.defaultlng, self.args.defaultzoom);
		self.initOverlayCollections();
		self.map.create();
		
		self.map.zoomControl = new SVZoomControl();
		self.map.typeControl = new SVTypeControl();
		
		if(!self.args.enabledragging) self.map.gmap.disableDragging();
		if(!self.args.enablescrollzoom) self.map.gmap.disableScrollWheelZoom();
		if(self.args.mapdata != "listingdetail")
		{
			self.map.viewControl = new SVToolbarControl({toggleView: self.toggleView});
			self.map.gmap.addControl(self.map.viewControl);
			//self.map.gmap.disableDragging();
			//self.map.gmap.disableScrollWheelZoom();
		}
		else
		{
			self.map.gmap.addControl(self.map.zoomControl);
			self.map.gmap.addControl(self.map.typeControl);
		}
		
		self.map.widget = self;
		
		self.container = $("#map_" + self.map.name + "_container");
		
		$("a.streetView", self.container).click(function(){return self.toggleView("street")});
		$("a.mapView", self.container).click(function(){return self.toggleView("map")});
		
		//Make sure they are initialized with filter flags
		self.preparePlacemarks();
		
		if(self.args.streetview)
			self.initStreetView();
		
		if(typeof(DistanceFilter) != "undefined")
			self.distanceFilter = new DistanceFilter();
		
		if(self.args.mapdata == "listingdetail")
		{
			self.directions = new DrivingDirections(self.args.mapName,self.map);
			self.directions.init();
		}
		//Set view to map
		self.toggleView(self.args.currentmode, true);
	}
	this.initStreetView = function()
	{
		client = new GStreetviewClient();
		client.getNearestPanorama(placemarks[self.args.mapdata][0].point, self.streetViewResults);
	}
	this.streetViewResults = function(streetViewData)
	{
		if(streetViewData.code == GStreetviewClient.ReturnValues.SUCCESS)
		{
			self.container.find(".streetView").show();
			self.map.div.after("<div id=\"street_" + self.map.name + "\" class=\"add5pxAll\" style=\"display:none\"></div>");
			self.streetdiv = $("#street_" + self.map.name);
			self.streetdiv.css({width:parseInt(self.args.width),height:parseInt(self.args.height)});
			self.street = new GStreetviewPanorama(self.streetdiv.get(0), {latlng:placemarks[self.args.mapdata][0].point});
		}
		else
			self.container.find(".streetView").hide();
	}
	this.initOverlayCollections = function()
	{
		//Initialize Variables and Event Handlers
		overlays.map = self.map;
		overlays.pagesize = 99;
		overlays.addHandler("showhide",overlays.markPlacemarkListings,true);
		//overlays.addHandler("openinfobubble",overlays.updateBubble,true);
		overlays.addHandler("gotoplacemark",self.goToPlacemark,true);
		
		//Add Main overlay collection and set as default
		self.map.addCollection(overlays,true);
		
		if(self.args.mapdata != "listingdetail")
		{
			overlays.getInfoHTML = function(placemark)
			{
				return parsePlacemarkData(self.args.sampleinfohtml,placemark);
			}
		}
	}
	//Go to Marker and Open InfoWindow
	this.goToPlacemark = function(placemark)
	{
		$.scrollTo(self.map.div,400,{axis:'y',offset:-50});
		self.toggleView("map", false, true);
		placemark.marker.openInfoWindowHtml(placemark.marker.myInfoHTML);
		self.map.gmap.setCenter(placemark.marker.getLatLng(), self.args.defaultzoom);
		placemark.collection.execHandler("openinfobubble");
	}
	//Find a placemark in the placemarks collection
	this.findPlacemark = function(placemarkID)
	{
		for (var i = 0; i < placemarks[self.args.mapdata].length; i++){
			if(placemarks[self.args.mapdata][i].prikey == placemarkID)
				return placemarks[self.args.mapdata][i];
		}
		return null;
	}
	//This function sets up the filter fields on each placemark
	this.preparePlacemarks = function(){
		var itinLookup = [];
		if (typeof(placemarks)=='undefined') return false;
		if (!placemarks) return false;
	
		for (var i in placemarks){
			for (var j = 0; j < placemarks[i].length; j++){
				if(placemarks[i][j].latitude.length == 0 || placemarks[i][j].longitude.length == 0){
					placemarks[i].splice(j,1);
					j = j - 1;
				}
				else{
					placemarks[i][j].filteredBy = new Object();
					placemarks[i][j].filtered = false;
					placemarks[i][j].active = true;
					placemarks[i][j].point = new GLatLng(placemarks[i][j].latitude,placemarks[i][j].longitude);
					placemarks[i][j].itinerary = jQuery.inArray(placemarks[i][j].prikey, itinLookup) >= 0;
				}
			}
		}
	}
	//Runs whenever the filters are updated 
	this.updatedFilters = function(unfiltered){
		self.map.removePlacemarks(self.map.defaultCollection,true);
		self.map.addPlacemarks(unfiltered,self.map.defaultCollection);
		self.map.showPlacemarks(self.map.defaultCollection,1);
		self.map.setBoundsCenterAndZoom();
	}
	this.toggleView = function(view, firstLoad, recenter){
		firstLoad = typeof firstLoad == "undefined" ? false : firstLoad;
		recenter = typeof recenter == "undefined" ? true : recenter;
		
		if(firstLoad)
		{
			self.currentView = view;
			if (typeof(placemarks)!='undefined') self.updatedFilters(placemarks[self.args.mapdata]);
		}
		else
		{
			if(self.currentView == view)
				return false;
			if(self.currentView == "street")
			{
				self.streetdiv.hide();
				self.map.div.show();
				return false;
			}
			if(self.args.mapdata != "listingdetail")
			{
				view = self.currentView == "mini" ? "map" : "mini";
				searchContainer = $(self.map.div).parents(".listingsSearch");
				mapdiv = self.map.div.parent(".MapContainer");
				self.map.viewControl.toggle();
				var typeControlOffset = new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(102,10));
				if(view == "map")
				{
					finish = function(){self.map.gmap.checkResize();self.map.gmap.addControl(self.map.zoomControl);self.map.gmap.addControl(self.map.typeControl, typeControlOffset);self.map.gmap.returnToSavedPosition()};
					self.map.gmap.savePosition();
					animate1 = {top:0,right:0,width:searchContainer.innerWidth()-12,height:searchContainer.innerHeight()-12};
					mapdiv.css({position:"absolute",top:0,right:0,width: mapdiv.innerWidth()}).animate(animate1, 600, "swing", finish);
					self.map.gmap.enableDragging();
					self.map.gmap.enableScrollWheelZoom();
				}
				else
				{
					finish = function(){self.map.gmap.checkResize();self.map.gmap.removeControl(self.map.zoomControl);self.map.gmap.addControl(self.map.typeControl, typeControlOffset);self.map.gmap.returnToSavedPosition()};
					animate1 = {top:0,right:0,width:self.args.miniwidth,height:self.args.miniheight};
					mapdiv.animate(animate1, 600, "swing", finish);
					self.map.gmap.disableDragging();
					self.map.gmap.disableScrollWheelZoom();
				}
			}
			
			self.currentView = view;
		}
		
		/*
		else if(view == "street")
		{
			self.map.div.hide();
			self.streetdiv.show();
			self.street.show();
		}*/
		
		self.currentView = view;
		return false;
	}
	
	if(self.args.mapdata == "listingdetail")
	{
		var googleDirections;
		
		//Remove a placemark from the placemarks collection
		this.removePlacemark = function(placemarkID) {
			for (var i = 0; i < placemarks[self.args.mapdata].length; i++) {
				if (placemarks[self.args.mapdata][i].prikey == placemarkID) {
					placemarks[self.args.mapdata].splice(i);
				}
			}
			return null;
		}
		
		this.loadDirections = function(address) {
			removeAllOverlays();
			geocoder = new GClientGeocoder();
			var point = geocoder.getLocations(address, addToMap);
		}
		
		this.addToDirectionOverlays = function(prikey) {
			var placemark = self.findPlacemark(prikey);
			placemark.active = false;
			if (placemark.collection != directionOverlays) {
				placemark.directionsource = placemark.collection;
				self.map.removePlacemark(placemark, placemark.collection);
				self.map.addPlacemark(placemark, directionOverlays);
				self.map.showPlacemarks(directionOverlays, 1);
			}
		}
		
		this.removeFromDirectionOverlays = function(prikey) {
			var placemark = self.findPlacemark(prikey);
			placemark.active = true;
			
			self.map.removePlacemark(placemark, directionOverlays);
			if (String(placemark.prikey).indexOf("custom") < 0)
				self.map.addPlacemark(placemark, placemark.directionsource);
			else
				self.map.removePlacemark(placemark, placemark.collection);
			placemark.directionsource = null;
			placemark.collection.sortBy("name");
			self.map.showPlacemarks(placemark.collection, placemark.collection.currPage);
		}
		
		this.clearDirections = function(removeCustom) {
			if (self.directions.placemarkToField && self.directions.placemarkToField.val().length > 0) {
				var prikey = self.directions.placemarkToField.val();
				self.removeFromDirectionOverlays(prikey);
				self.directions.placemarkToField.val("");
			}
			
			if (self.directions.placemarkFromField && self.directions.placemarkFromField.val().length > 0) {
				var prikey = self.directions.placemarkFromField.val();
				self.removeFromDirectionOverlays(prikey);
				if(removeCustom)
					self.removePlacemark(prikey);
				self.directions.placemarkFromField.val("");
			}
			self.directions.clearDirections();
		}
		
		this.getDirections = function(prikeyFrom, prikeyTo) {
			var pFrom, pTo;
			self.clearDirections();
			
			if (prikeyFrom) {
				pFrom = self.findPlacemark(prikeyFrom);
				self.directions.directionsFrom(prikeyFrom);
			} else {
				pFrom = self.directions.src;
			}
			
			if (prikeyTo) {
				pTo = self.findPlacemark(prikeyTo);
				self.directions.directionsTo(prikeyTo);
			} else {
				pTo = self.directions.dst;
			}
			
			pFrom.isDst = 1;
			pTo.isDst = 0;
			
			if	(pFrom.marker)
				pFrom.marker.closeInfoWindow();
			if	(pTo.marker)
				pTo.marker.closeInfoWindow();
			
			if (!directionOverlays.check(prikeyTo))
				self.addToDirectionOverlays(prikeyTo);
			
			if (!directionOverlays.check(prikeyFrom))
				self.addToDirectionOverlays(prikeyFrom);
			
			if (prikeyFrom == prikeyTo)
				self.directions.getDirections();
			else
				self.directions.getDirectionsTo(pFrom, pTo);
			return false;
		}
	
		this.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 GLatLng(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 o;
		}
		this.customprikey = 0;
		this.defaultPlacemark = function(name) {
			var o = new Object();
			o.name = "";
			o.prikey = "custom_" + (++self.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;
		}
		
		//callpack function to add marker to map
		this.addToMap = function(placeMarkCollection) {
			//we only care about the first one since we only add one address
			point = placeMarkCollection.Placemark[0].Point;
			var adr = placeMarkCollection.Placemark[0].AddressDetails;
			
			var directionsFromMark = self.defaultPlacemark();
			
			directionsFromMark = self.parseGeocodingResults(placeMarkCollection, directionsFromMark);
			
			placemarks[args.mapdata].push(directionsFromMark);
			
			self.map.addPlacemark(directionsFromMark, custom);
			self.map.showPlacemarks(custom, 1);
			
			self.clearDirections();
			
			self.directions.placemarkFromField.val(directionsFromMark.prikey);
			self.directions.placemarkToField.val(directionsToMark.prikey);
			
			self.getDirections(self.directions.placemarkToField.val(), self.directions.placemarkFromField.val());
		}
		
		this.showFromDirections = function(key) {
			var obj = self.findPlacemark(key);
			directionsToMark = obj;
			var dirHTML = parsePlacemarkData('<div style="padding-top: 0.5em;"><input type="hidden" id="directionsTo" value="placemark:name@placemark:latitude,placemark:longitude"><span class="directionsFrom">Start address: <input type="text" id="directionsFrom"></span> &nbsp;<input type="submit" id="directionsSubmit" value="Go" onclick="maps[\'' + self.args.mapdata + '\'].getGoogleDirections(placemark:prikey);"></div>', obj);
			
			if (typeof obj.marker.myOrigInfoHTML == 'undefined' || obj.marker.myOrigInfoHTML == '') {
				obj.marker.myOrigInfoHTML = obj.marker.myInfoHTML;
			}
			obj.marker.fromHTML = dirHTML;
			obj.marker.myInfoHTML = obj.marker.myOrigInfoHTML + obj.marker.fromHTML;
			obj.marker.openInfoWindowHtml(obj.marker.myInfoHTML);
		}
		
		this.getGoogleDirections = function(key) {
			var obj = self.findPlacemark(key);
			
			geocoder = new GClientGeocoder();
			var address = $('#directionsFrom').val();
			var point = geocoder.getLocations(address, self.addToMap);
			
			if (typeof obj.marker.myOrigInfoHTML == 'string' && obj.marker.myOrigInfoHTML.length > 0) {
				obj.marker.myInfoHTML = obj.marker.myOrigInfoHTML;
			}
		}
	}
	
	$(this.initWidgetMap);
}

//String.prototype.trim = function () {return this.replace(/^\s*/, "").replace(/\s*$/, "");}
