currentInfoWindow = null;

var WhereMaps = new function() {

	var internalFunction = function() {
		// empty
	};
	
	this.IntervalTimer = function (theMapManagerObj) {
		var self = this;
		var mmObj = theMapManagerObj;
		var intervalID = 0;
		var intervalTimer;
		var intervalPinArray;
		this.lastAutoInfoWindowObj = null;
		this.isMouseover = false;
		this.isPaused = false;

		function intervalTriggered() {
			if (self.isPaused || self.isMouseover) {
				return;
			}
			if (intervalPinArray[intervalID]) {
				if (!mmObj.shareInfoWindow && self.lastAutoInfoWindowObj) {
					self.lastAutoInfoWindowObj.close();
				}
				var drawPinReturned = mmObj.drawPin(intervalPinArray[intervalID]);
				self.lastAutoInfoWindowObj = drawPinReturned[1];
				intervalID++;
			} else {
				self.stopPinInterval();
			}
		}

		this.startPinInterval = function(pinArray, interval) {
			intervalPinArray = pinArray;
			intervalTimer = setInterval(intervalTriggered, interval);
		};

		this.stopPinInterval = function() {
			clearInterval(intervalTimer);
		};

		return self;
	};

	this.InlineMap = function(mapManagerRef) {
		
		var mapManagerObject = mapManagerRef;

		var self = this;
		
		this.setInlineMapInitVars = function (mapDivID, jinStaticHost, jinApiLocalRoot, activeCity, activeState, remoteloadURL) {
			this.mapDivID = mapDivID;
			this.jinStaticHost = jinStaticHost;
			this.jinApiLocalRoot = jinApiLocalRoot;
			this.activeCity = activeCity;
			this.activeState = activeState;
			this.defaultLocation = activeCity + ", " + activeState;
			this.remoteloadURL = remoteloadURL;
			this.skipCenterOnInit = false;
		};
		
		this.init = function () {
			var initZoom = 5;
			var initLatLng = new google.maps.LatLng(37.09024, -95.712891); // center of continental USA
		    var myOptions = {
		      zoom: initZoom,
		      center: initLatLng,
		      mapTypeId: google.maps.MapTypeId.ROADMAP,
		      mapTypeControl: true,
		      mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
		      navigationControl: true,
		      navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL}
		    };
		    var map = new google.maps.Map(document.getElementById(this.mapDivID), myOptions);
			mapManagerObj.setMap(map);
			mapManagerObj.shareInfoWindow = false;
			if (this.skipCenterOnInit === false) {
				mapManagerObj.centerOnAddressAndZoom(this.defaultLocation, 12);
				this.skipCenterOnInit = true;
			}
			if (this.remoteloadURL.length) {
				self.loadRemoteMapData(this.remoteloadURL, 2500);
			}
		};

		this.loadRemoteMapData = function (url, delay) {
			$.ajax({type: "GET",
					url: url,
					processData: true,
					data: {},
					dataType: "json",
					success: function(data) {
						//mapManagerObj.drawPinArray(data);
						mapManagerObj.intervalDrawPinArray(data, delay);
						},
					error: function(x,y,z) {
						//alert("error: " + x.responseText);
						}
			});
		};
		
		this.getRequestURI = function (poi){
			var poiId = poi.attributes.listingId;
			var requestURI = '/detail/'+ cleanTextForURL(poi.location.placeName) +'/' + poiId;
			if (poi.attributes.sourceId) { 
				var sourceId = poi.attributes.sourceId;
				if (sourceId == 'e' || sourceId == 'jb') {
					requestURI = '/events' + requestURI;
				}
			}
			
			
			return requestURI;
		};

	};
	
	this.MapManager = function() {
		var self = this;
		var map;
		var dService = new google.maps.DirectionsService();
		var dDisplay = new google.maps.DirectionsRenderer();
		var geocoder = new google.maps.Geocoder();
		var mapBounds = new google.maps.LatLngBounds();
		var pinCache = null;
		var commonInfoWindowObj = new google.maps.InfoWindow();
		this.markers = {
				poi: [],
				spotlight: [],
				search: []
				};
		this.shareInfoWindow = false;
	
		this.setMap = function(theMap) {
			map = theMap;
			dDisplay.setMap(map);
			if (pinCache) {
				self.drawPinArray(pinCache);
				pinCache = null;
			}
		};
	
		this.centerOnPoint = function(lat, lng) {
			map.setCenter(new google.maps.LatLng(lat, lng));
		};
		
		this.panToPoint = function(lat, lng) {
			map.panTo(new google.maps.LatLng(lat, lng));
		}
	
		this.zoomTo = function(zoom) {
			map.setZoom(zoom);
		};
	
		this.centerOnAddressAndZoom = function(addr, zoom) {
			self.geocode(addr, function(position) {
				map.setCenter(position);
				if (zoom) {
					map.setZoom(zoom);
				}
			});
		};
		
		this.panToAddress = function(addr) {
			self.geocode(addr, function(position) {
				map.panTo(position);
			});
		};
		
		this.panToMarker = function(marker) {
			map.panTo(marker.getPosition());
		}
	
		this.updateBounds = function(marker, zoomOffset) {
			mapBounds.extend(marker.getPosition());
			//map.setCenter(mapBounds.getCenter());
			map.panTo(mapBounds.getCenter());
			if (zoomOffset) {
				// disabled for now, behave as normal
				map.fitBounds(mapBounds);
			} else {
				map.fitBounds(mapBounds);
			}
		};
	
		this.zoomPinBounds = function(markers) {
			var bounds = new google.maps.LatLngBounds();
			for (var i = 0; i < markers.length; i++) {
				bounds.extend(new google.maps.LatLng(markers[i].getPosition()));
			}
			map.setCenter(bounds.getCenter());
			map.fitBounds(bounds);
		};
	
		this.geocode = function(addr, callback) {
			if (geocoder) {
				geocoder.geocode( { 'address': addr}, function(results, status) {
					if (status == google.maps.GeocoderStatus.OK) {
						callback(results[0].geometry.location);
					} else {
						//alert("geocoder response failed: " + status)
						callback(null);
					}
				});
			} else {
				//alert("geocoder not ready");
			}
		};
		
		this.geocodeInternal = function(addr, callback) {
			var geocodeURL = inlineMap.jinApiLocalRoot + '/module/data/api?path=' + encodeURIComponent('/api/geocoding.json?address=' + encodeURIComponent(addr.replace(/,/g, "")));
			$.ajax({type: "GET",
					url: geocodeURL,
					processData: true,
					data: {},
					dataType: "json",
					success: function(data) {
						//console.info('pass geocodeInternal data: ' + data);
						callback(data);
						},
					error: function(x,y,z) {
						console.info("geocodeInternal error: " + x.responseText);
						}
			});
		};
		
		this.locationToString = function(locObj) {
			var addrString = "";
			
			if (locObj.street) {
				addrString += locObj.street + " ";
			}
			
			if (locObj.city) {
				addrString += locObj.city + " ";
			}
			
			if (locObj.state) {
				addrString += locObj.state + " ";
			}
			
			if (locObj.zip) {
				addrString += locObj.zip;
			}
			
			return addrString;
		}
	
		this.toggleMarkers = function(markerGroup, newState) {
			for (var i = 0; i < markerGroup.length; i++) {
				markerGroup[i].setMap(newState ? map : null);
			}
		};
		
		this.openInfoWindow = function(infowindow, marker) {
			showInfoWindow(infowindow, map, marker);
		}
	
		this.drawPin = function(pin, i) {
			if (pin.drawonmap === false) {
				return null;
			}
			if (pin.pintype != "search") {
				if (!pin.location) {
					console.info('pin missing location data');
					return null;
				} else if (!pin.location.point || (pin.location.point.lat === null) || (pin.location.point.lng === null)) {
					console.info('pin missing lat/lng - send to geocoder');
					var geocodeReturn = function(position) {
						if (position === null) {
							console.info('geocode position returned null');
							return null;
						}
						console.info('new pin point: ' + position.locations[0].lat + ", " + position.locations[0].lng);
						if (!pin.location.point) {
							pin.location.point = {};
						}
						pin.location.point.lat = position.locations[0].lat;
						pin.location.point.lng = position.locations[0].lng;
						self.drawPin(pin, i);
					}
					self.geocodeInternal(self.locationToString(pin.location), geocodeReturn);
					return null;
				}
			}
			if (pin.location && (pin.location.placeName === null)) {
				pin.location.placeName = "Name Unavailable";
			}
			var thisMarker = null;
			if (pin.pintype == "poi") {
				thisMarker = dropPinPOI(pin,i);
				this.markers.poi.push(thisMarker[0]);
				self.updateBounds(thisMarker[0], 0);
				return thisMarker;
			} else if (pin.pintype == "spotlight") {
				thisMarker = dropPinSpotlight(pin,i);
				this.markers.spotlight.push(thisMarker[0]);
				//self.updateBounds(thisMarker[0]);
				return thisMarker;
			} else if (pin.pintype == "search") {
				thisMarker = dropPinSearch(pin,i);
				this.markers.search.push(thisMarker[0]);
				// disable updateBounds on (live) search pins for now - need to find a better way to determine pan/center/zoom intent
				//self.updateBounds(thisMarker[0], -1);
				self.panToMarker(thisMarker[0]);
				return thisMarker;
			} else {
				return null; // invalid pintype
			}
		};
	
		this.drawPinArray = function(pinArray) {
			var thisMarkerArray = [];
			if (pinArray.length) {
				if (!map) {
					pinCache = pinArray;
				} else {
					if ((pinArray[0].pintype == "poi") && (pinArray.length == 1)) {
						thisMarkerArray.push(self.drawPin(pinArray[0]));
//						self.panToMarker(pinArray[0]);
					} else {
						for (var i = 0; i < pinArray.length; i++) {
							thisMarkerArray.push(self.drawPin(pinArray[i], (i + 1)));
						}
					}
				}
			}
			return thisMarkerArray;
		};
	
		this.intervalDrawPinArray = function(pinArray, interval) {
			if (interval) {
				intervalObj.startPinInterval(pinArray, interval);
			} else {
				self.drawPinArray(pinArray);
			}
		};
	
		this.calcRoute = function(dStart, dEnd, tbtDiv, dMethod) {
			var travelMode = google.maps.DirectionsTravelMode.DRIVING;
		    if (dMethod == 'driving') {
				travelMode = google.maps.DirectionsTravelMode.DRIVING;
			} else if (dMethod == 'walking') {
				travelMode = google.maps.DirectionsTravelMode.WALKING;
			}
			var request = {
				origin:dStart, 
				destination:dEnd,
				travelMode: travelMode
			};
			dService.route(request, function(result, status) {
				if (status == google.maps.DirectionsStatus.OK) {
					dDisplay.setDirections(result);
					dDisplay.setPanel(tbtDiv);
				}
			});
		};
	
		function showInfoWindow(infowindow, map, marker) {
            if(infowindow == null || map == null || marker == null)
                return;
			if(currentInfoWindow != null)
				currentInfoWindow.close();
			infowindow.open(map, marker);
			currentInfoWindow = infowindow;
        }
		function dropPinPOI(poi, i) {
			var pinURL;
			if (i) {
				pinURL = inlineMap.jinStaticHost + '/img/map-pins/map-pin-' + i + '.png';
			} else {
				pinURL = inlineMap.jinStaticHost + '/img/map-pins/pin.png';
			}
			var pinImage = new google.maps.MarkerImage(pinURL,
				// size
				new google.maps.Size(40, 40),
				// origin
				new google.maps.Point(0,0),
				// anchor
				new google.maps.Point(20, 40));

			var pinShadow = new google.maps.MarkerImage(inlineMap.jinStaticHost + '/img/map-pins/pin_shadow.png',
				// size
				new google.maps.Size(60, 40),
				// origin
				new google.maps.Point(0,0),
				// anchor
				new google.maps.Point(30, 40));

			var marker = new google.maps.Marker({
				position: new google.maps.LatLng(poi.location.point.lat, poi.location.point.lng),
				map: map,
		        icon: pinImage,
		        shadow: pinShadow,
				title: truncateText(poi.location.placeName, 25)
			});

			var infowindow;
			if (self.shareInfoWindow) {
				infowindow = commonInfoWindowObj;
			} else {
				infowindow = new google.maps.InfoWindow();
			}
		
			infowindow.content = '<div class="mapInfoWindow_poi"><ul>';
			if (poi.location.placeName != poi.name) {
				infowindow.content += '<li>' + truncateText(poi.location.placeName, 25) + '</li>';
			}
			
			infowindow.content += '<li><a href="' + inlineMap.jinApiLocalRoot + '/' + inlineMap.activeState + '/' + inlineMap.activeCity + inlineMap.getRequestURI(poi) + '">' + truncateText(poi.name, 25) + '</a></li>';
			if (poi.location.phone) {
				infowindow.content += '<li>' + formatPhoneNumber(poi.location.phone) + '</li>';
			}
			infowindow.content += '<li>' + poi.location.street + ', ' + poi.location.city + ' ' + poi.location.state + ' ' + poi.location.zip + '</li>' +
				'</ul></div>';
	
			if (poi.autoopeninfowindow) {
                showInfoWindow(infowindow, map, marker);
			}

			google.maps.event.addListener(marker, 'click', function() {
                showInfoWindow(infowindow, map, marker);
			});

			var returnArray = [];
			returnArray.push(marker);
			returnArray.push(infowindow);
			return returnArray;
		}
	
		function dropPinSpotlight(poi, i) {
			var pinURL;
			if (i) {
				pinURL = inlineMap.jinStaticHost + '/img/map-pins/map-pin-recommended-' + i + '.png';
			} else {
				pinURL = inlineMap.jinStaticHost + '/img/map-pins/pin.png';
			}
			var pinImage = new google.maps.MarkerImage(pinURL,
				// size
				new google.maps.Size(40, 40),
				// origin
				new google.maps.Point(0,0),
				// anchor
				new google.maps.Point(20, 40));
	
			var pinShadow = new google.maps.MarkerImage(inlineMap.jinStaticHost + '/img/map-pins/pin_shadow.png',
				// size
				new google.maps.Size(60, 40),
				// origin
				new google.maps.Point(0,0),
				// anchor
				new google.maps.Point(30, 40));
	
			var marker = new google.maps.Marker({
				position: new google.maps.LatLng(poi.location.point.lat, poi.location.point.lng), 
				map: map, 
		        icon: pinImage, 
		        shadow: pinShadow, 
				title: truncateText(poi.location.placeName, 25)
			});
	
			var infowindow;
			if (self.shareInfoWindow) {
				infowindow = commonInfoWindowObj;
			} else {
				infowindow = new google.maps.InfoWindow();
			}
		
			var poiID;
			if (poi.attributes.sourceId) {
				poiID = poi.attributes.sourceId + '_' + poi.attributes.sourceItemId;
			} else {
				poiID = poi.attributes.sourceItemId;
			}
			infowindow.content = '<div class="mapInfoWindow_poi"><ul>' +
				'<li><a href="' + inlineMap.jinApiLocalRoot + '/' + inlineMap.activeState + '/' + inlineMap.activeCity + '/detail/' + truncateText(poi.location.placeName, 25) + '/' + poiID + '">' + truncateText(poi.location.placeName, 25) + '</a></li>';
			if (poi.location.phone) {
				infowindow.content += '<li>' + formatPhoneNumber(poi.location.phone) + '</li>';
			}
			infowindow.content += '<li>' + poi.location.street + ', ' + poi.location.city + ' ' + poi.location.state + ' ' + poi.location.zip + '</li>' +
				'</ul></div>';
			
			if (poi.autoopeninfowindow) {
                showInfoWindow(infowindow, map, marker);
			}
	
			google.maps.event.addListener(marker, 'click', function() {
                showInfoWindow(infowindow, map, marker);
			});
	
			var returnArray = [];
			returnArray.push(marker);
			returnArray.push(infowindow);
			return returnArray;
		}
	
		function dropPinSearch(search) {
			var pinImage = new google.maps.MarkerImage(inlineMap.jinStaticHost + '/img/map-pins/where-pin.png',
				// size
				new google.maps.Size(40, 40),
				// origin
				new google.maps.Point(0,0),
				// anchor
				new google.maps.Point(20, 40));
	
			var pinShadow = new google.maps.MarkerImage(inlineMap.jinStaticHost + '/img/map-pins/pin_shadow.png',
				// size
				new google.maps.Size(60, 40),
				// origin
				new google.maps.Point(0,0),
				// anchor
				new google.maps.Point(30, 40));
	
			var marker = new google.maps.Marker({
				position: new google.maps.LatLng(search.lat, search.lng), 
				map: map, 
		        icon: pinImage, 
		        shadow: pinShadow, 
		        title: search.keyword
			});
	
			var infowindow;
			if (self.shareInfoWindow) {
				infowindow = commonInfoWindowObj;
			} else {
				infowindow = new google.maps.InfoWindow();
			}
		
			infowindow.content = '<div class="mapInfoWindow_search">' +
				'<div class="icon-bg"><img src="' + inlineMap.jinStaticHost + '/img/whereview_icon.png" alt="where logo" /></div>' +
				'<p>Someone searching for <br />' +
				'<a href="' + inlineMap.jinApiLocalRoot + '/' + inlineMap.activeState + '/' + inlineMap.activeCity + '/search/' + search.keyword + '">' + search.keyword + '</a> <br />' +
				'using the WHERE&reg; app' +
				'</p></div>';
	
			if (search.autoopeninfowindow) {
                showInfoWindow(infowindow, map, marker);
			}
	
			google.maps.event.addListener(marker, 'click', function() {
                showInfoWindow(infowindow, map, marker);
			});
	
			var returnArray = [];
			returnArray.push(marker);
			returnArray.push(infowindow);
			return returnArray;
		}
	
		return self;
	}
};
