var in_array = function(needle,haystack) {
	for(var i = 0, l = haystack.length; i < l; i++) {
		if(haystack[i] == needle) {
			return true;
		}
	}
	return false;
}

var GowallaTools = {
	
	visited: 0,
	page: 1,
	user: null,
	map: null,
	markers: [],
	markerImages: [],
	radius: null,
	geocoder: null,
	stamps: [],
	itemFinderCache: [],
	itemFinderSpots: 0,
	mapStatus: '',
	
	createMap: function(lat, lng) {
		GowallaTools.geocoder = new GClientGeocoder();
		GowallaTools.map = new google.maps.Map2(document.getElementById("map")); //, {mapTypes:[OSM]}
		GowallaTools.map.setUIToDefault();
		if (lat && lng) {
			GowallaTools.centerMap(lat, lng, 4);
		} else {
			GowallaTools.centerMap(39.05231, -94.60728, 4);
		}
		
	},
	
	centerMapAccurate: function(position) {
		var lat = position.coords.latitude;
		var lng = position.coords.longitude;
		GowallaTools.centerMap(lat, lng, 13);
		GowallaTools.loadMap();
	},
	
	failCenterMapAccurate: function() {
		GowallaTools.centerMap(39.05231, -94.60728, 4);
		GowallaTools.loadMap();
	},
	
	centerMap: function(lat, lng, zoom) {
		if(!zoom) {
			zoom = 12;
		} 
		GowallaTools.map.setCenter(new google.maps.LatLng(lat, lng), zoom);
	},
	
	loadMap: function() {
		if (!$('#map-status').length) {
			GowallaTools.loadUserDetails();
			GowallaTools.getVisited();
			GowallaTools.setupMapEvents();
		}
	},
	
	locationSearch: function(location) {
		$('#map-status').addClass('loading').find('p').removeClass('moved').removeClass('some').removeClass('all').html('Searching for "'+location+'"');
		GowallaTools.geocoder.getLocations(location, function(l) {
			if (!l.Placemark) {
				alert("That location was not found - please try another.");
			} else {
				$('#location').val('');
				$('#map').addClass('moving');

				var point = l.Placemark[0].Point;
				point = new GLatLng(point.coordinates[1],point.coordinates[0]);
				var exData = l.Placemark[0].ExtendedData; 
				var bounds = exData ? exData.LatLonBox : undefined; 
				var zoom = 13;
				if (bounds) {
					var llbounds = new GLatLngBounds(new GLatLng(bounds.south, bounds.west),new GLatLng(bounds.north, bounds.east));
					zoom = GowallaTools.map.getBoundsZoomLevel(llbounds);
				}
				GowallaTools.map.setCenter(point, zoom);
				$('#map').removeClass('moving');
				GowallaTools.displaySpots();
			}
		});
	},
	
	checkUser: function(username) {
		var username = $('input#username').val();
		$('input#username').trigger('blur').val('').addClass('loading');
		$('input#submit').fadeOut('fast');
		$.get('_user.php', {user: username}, function(data) {
			if (data != 'error') {	
				GowallaTools.user = JSON.parse(data);
				if (!GowallaTools.user.username) {
					GowallaTools.user.username = username;
				}
			}
			
			if (!GowallaTools.user) {
				$('input#username').val(username).removeClass('loading');
				$('input#submit').show();
				alert('That Gowalla Username does not exist - please try again.');
			} else {
				$('.initial').fadeOut('slow',function() {
					$(this).remove();
					$('#content').css('padding','0').append('<div id="nav-bar"><form method="get" action=""><input type="text" id="location" name="location" value="" /><input type="submit" value="Search" id="location-submit" /></form><div id="map-utilities"></div></div><div id="map"></div>');
					GowallaTools.createMap();
					GowallaTools.loadMap();
				});
			}
		});
	},
	
	loadUserDetails: function() {
		$('#map').after('<div id="map-status"><p></p></div>');
		$('#map-status').after('<div id="information"><div id="profile"></div><div id="spot"></div><div id="items"></div></div><div id="media"><h3>Flickr Photos</h3><div id="flickr"><p>Click on a spot to find photos!</div></div>');
		$('#information').hide().slideDown('slow');
		$('#profile').append('<h3>'+GowallaTools.user.first_name+' '+GowallaTools.user.last_name+'</h3><img src="'+GowallaTools.user.image_url+'" alt="" /><div class="spots"><span>'+GowallaTools.user.stamps_count+'</span> Visited Spots</div><div class="pins"><span>'+GowallaTools.user.pins_count+'</span> Pins Obtained</div><div class="vaulted"><span>'+GowallaTools.user.vaulted.length+'</span> Vaulted Items</div>');
		
		$('#nav-bar form').submit(function() {
			GowallaTools.locationSearch($('#location').val());
			return false;
		});
	},
	
	getVisited: function() {
		$.get('_visited.php', {user: GowallaTools.user.username}, function(count) {
			GowallaTools.visited = count;		
			GowallaTools.displaySpots();
		});
	},
	
	displaySpots: function() {
		
		GowallaTools.map.clearOverlays();
		GowallaTools.clearSelectedItem();
		
		// clear old data
		GowallaTools.markers.length = 0;
		GowallaTools.stamps.length = 0;
		GowallaTools.markerImages.length = 0;	
		

		$('#map-status').addClass('loading').find('p').removeClass('moved').removeClass('some').removeClass('all').html('Loading the 250 most recent spots in this area.');
		$('#map-utilities input').remove();
		$('#map').removeClass('dupes');
					
		var sw = GowallaTools.map.getBounds().getSouthWest().toString();
		var ne = GowallaTools.map.getBounds().getNorthEast().toString();
		$.get('_spots.php', {sw: sw, ne: ne}, function(data) {
			var stamps = JSON.parse(data);

			// load
			var x = '';
			for (x in stamps) { 
				if (stamps[x]) {
					var stamp = stamps[x];
					if (stamp.name) {
						var point = new GLatLng(stamp.lat,stamp.lng);
						GowallaTools.map.addOverlay(GowallaTools.createMarker(point,x,stamp));
					}
				}
			}
			$('#map-status').removeClass('loading');
			if (stamps.length == 250) {
				$('#map-status p').addClass('some').html('The most recent <strong>250 spots</strong> in this area are currently displayed. Move or Zoom In and press "redraw" to see more.');
			} else {
				$('#map-status p').addClass('all').html('There are currently <strong id="visible-spots">'+stamps.length+' spots</strong> <span>in this area.</span>');
			}
			
			GowallaTools.mapStatus = $('#map-status').html();

			$('#flickr p').html('Click on a spot to find photos!');

			$('#map-utilities').append('<input type="button" id="dupe-finder" value="Show Suspected Duplicates" />');
			$('#dupe-finder').click(function() {
				if ($('#map').hasClass('dupes')) {
					GowallaTools.hideDupes();
					$(this).val('Show Suspected Duplicates');
				} else {
					GowallaTools.showDupes();
					$(this).val('Show All Spots');
				}
			});	
			
			$('#map-utilities').append('<input type="button" id="item-finder" value="Item Finder" />');
			$('#item-finder').click(function() {
				GowallaTools.itemFinder();
				$('#map-status').addClass('loading').find('p').html('Removing all spots in this area that have no items you need...');
				$(this).fadeOut('slow',function() {
					$(this).remove();
				});
			});
			
			$('#map-utilities').hide().fadeIn('slow');
			
		});
	},
	
	clearSelectedItem: function() {
		GowallaTools.removeRadius();
		$('#items').html('');
		$('#spot').html('');
		$('#flickr').html('<p>Select a spot to load photos.</p>');
	},
	
	showDupes: function() {
		GowallaTools.dupeSpots = 0;
		GowallaTools.clearSelectedItem();
		GowallaTools.resetMarkerImages();
		
		$('#item-finder').hide();
		
		$('#map').addClass('dupes');
		for (x in GowallaTools.markers) {
			if (!GowallaTools.stamps[x].visits_count) {
				var pin = 'http://labs.google.com/ridefinder/images/mm_20_purple.png';
				GowallaTools.markers[x].setImage(pin);
				GowallaTools.dupeSpots++;
			} else {
				GowallaTools.markers[x].hide();
			}
		}
		
		var dupeSpotsFound = (GowallaTools.dupeSpots == 1) ? '1 suspected duplicate spot' : GowallaTools.dupeSpots+' suspected duplicate spots';
		$('#map-status p').html('Currently displaying <strong>'+dupeSpotsFound+'</strong>');

		$('#map-status p').addClass('moved');			
		GowallaTools.mapMoved();
	},
	
	hideDupes: function() {
		GowallaTools.dupeSpots = 0;
		GowallaTools.clearSelectedItem();
		
		$('#item-finder').show();
		
		$('#map').removeClass('dupes');
		for (x in GowallaTools.markers) {
			if (!GowallaTools.stamps[x].visits_count) {
				GowallaTools.markers[x].setImage(GowallaTools.markerImages[x]);	
			} else {
				GowallaTools.markers[x].show();
			}
		}
		
		$('#map-status').html(GowallaTools.mapStatus);
	},
	
	itemFinder: function() {
		GowallaTools.itemFinderSpots = 0;
		GowallaTools.clearSelectedItem();
		$('#dupe-finder').hide();
		
		for (x in GowallaTools.markers) {
			if (!GowallaTools.stamps[x].items_count) {
				GowallaTools.map.removeOverlay(GowallaTools.markers[x]);
				delete GowallaTools.markers[x];
			} else {
				GowallaTools.itemFinderCache.push(x);
			}
		};
		GowallaTools.itemFinderProcess();
	},
	
	itemFinderProcess: function() {
		if (GowallaTools.itemFinderCache.length > 0) {
			var x = GowallaTools.itemFinderCache.shift();
			if (GowallaTools.stamps[x] == undefined) {
				return false;
			}
			$.get('_items.php',{url: GowallaTools.stamps[x].items_url},function(data) {
				var items = JSON.parse(data);
				var found = false;
				for (y in items) {
					for (var i=0; i < items[y].length; i++) {
						var item = items[y][i];
						if (!in_array(item.name,GowallaTools.user.vaulted)) {
							var pin = 'http://labs.google.com/ridefinder/images/mm_20_yellow.png';
							GowallaTools.markers[x].setImage(pin);
							GowallaTools.markerImages[x] = pin;
							found = true;
						}
					};
					if (found) {
						GowallaTools.itemFinderSpots++;
					}
				}
				if (!found) {
					GowallaTools.map.removeOverlay(GowallaTools.markers[x]);
					delete GowallaTools.markers[x];
				}
				GowallaTools.itemFinderProcess();
			});
		} else {
			if (!GowallaTools.itemFinderSpots) {
				$('#map-status').removeClass('loading').find('p').html('Alas, there are <strong>0 spots</strong> in this area containing items that you need for your vault. Try searching elsewhere... oh, and Good Luck!');
			} else {
				var itemFinderLocationsFound = (GowallaTools.itemFinderSpots == 1) ? '1 spot' : GowallaTools.itemFinderSpots+' spots';
				$('#map-status').removeClass('loading').find('p').html('Now displaying <strong>'+itemFinderLocationsFound+'</strong> that contain items missing from your vault.');
			}
			
			$('#map-status p').addClass('moved');			
			GowallaTools.mapMoved();
		}
	},
	
	setupMapEvents: function() {
		GEvent.addListener(GowallaTools.map, "dragend", function() {
			GowallaTools.mapMoved();
		});
		GEvent.addListener(GowallaTools.map, "zoomend", function() {
			GowallaTools.mapMoved();
		});		
	},
	
	mapMoved: function() {
		if (!$('#map').hasClass('moving')) {
			if ($('#map-status').hasClass('loading')) {
				setTimeout("GowallaTools.mapMoved()",500);
			} else {
				var _status = $('#map-status p');
				if (!_status.hasClass('moved')) {
					_status.addClass('moved');
					if (_status.hasClass('some')) {
						_status.html('There are <strong>250 spots</strong> currently being displayed. The map has been moved so press "redraw" to get spots in this area.');
					} else {
						_status.find('span').html('being displayed.  The map has been moved so press "redraw" to get spots in this area.');
					}
				}
				if (!$('#redraw').length) {
					_status.append('<input type="button" id="redraw" class="button" value="Redraw" />');
					$('#redraw').click(function() {
						GowallaTools.displaySpots();
					});
				}
			}
		}
	},
	
	resetMarkerImages: function() {
		for (i in GowallaTools.markers) {
			if ($('#map').hasClass('dupes')) {
				if (!GowallaTools.markers[i].isHidden()) {
					GowallaTools.markers[i].setImage('http://labs.google.com/ridefinder/images/mm_20_purple.png');
				}
			} else {
				GowallaTools.markers[i].setImage(GowallaTools.markerImages[i]);
			}
		}
	},
		
	createMarker: function(point, index, stamp) {		
		var tinyIcon = new GIcon();
		if (stamp.type == 'visited') {
			tinyIcon.image = "http://labs.google.com/ridefinder/images/mm_20_green.png";
		} else {
			tinyIcon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
		}
		tinyIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
		tinyIcon.iconSize = new GSize(12, 20);
		tinyIcon.shadowSize = new GSize(22, 20);
		tinyIcon.iconAnchor = new GPoint(6, 20);
		tinyIcon.infoWindowAnchor = new GPoint(5, 1);
		markerOptions = { icon:tinyIcon };
					
		GowallaTools.markers[index] = new GMarker(point, markerOptions);
		GowallaTools.stamps[index] = stamp;
		GowallaTools.markerImages[index] = tinyIcon.image;
		
		GEvent.addListener(GowallaTools.markers[index], "click", function() {
			// set active icon
			GowallaTools.resetMarkerImages();
			GowallaTools.markers[index].setImage('http://labs.google.com/ridefinder/images/mm_20_blue.png');
			
			// add radius
			GowallaTools.drawRadius(stamp.radius/1000,GowallaTools.radius,point,40);
			
			
			// display information
			$('#items').html('');
			$('#spot').html('');
			$('#flickr').html('<p>Loading...</p>');
			
			$('#spot').attr('rel',stamp.id);
			$('#spot').append('<h3><a href="http://gowalla.com'+stamp.url+'" target="_blank">'+stamp.name+'</a></h3>');
			$('#spot').append('<img src="'+stamp.image_url+'" alt="" class="icon" />');
			
			if (stamp.items_count == 1) {
				item_count = 'is <strong>1 item</strong>';
			} else {
				item_count = 'are <strong>'+stamp.items_count+' items</strong>';
			}
			
			$('#spot').append('<p>There '+item_count+' at this spot.<br />You can check in from <strong>'+stamp.radius+'m</strong> away.</p>');
			if (stamp.items_count > 0) {
				$('#items').append('<h3>Items at this spot</h3><ul></ul>');
				$.get('_items.php',{url: stamp.items_url},function(data) {
					$('#items ul').html('');
					var items = JSON.parse(data);
					for (x in items) {
						for (var i=0; i < items[x].length; i++) {
							var item = items[x][i];
							var missing = '';
							if (!in_array(item.name,GowallaTools.user.vaulted)) {
								missing = 'class="missing"';
							}
							$('#items ul').append('<li  '+missing+'><p class="item-name">'+item.name+'</p><img src="'+item.image_url+'" alt="" title="'+item.name+'" /><p class="item-number">#'+item.issue_number+'</p></li>');
						};
					}
					if ($('#items ul li.missing').length) {
						$('#spot p').append('<br />There is an item you need here.');
					}
				});
			}
			
			$.get('_flickr.php',{lat: stamp.lat, lng: stamp.lng, radius: stamp.radius, id: stamp.id},function(data) {
				var photos = JSON.parse(data);
				$('#flickr p').remove();
				if ($('#spot').attr('rel') == stamp.id) {
					if (photos.length) {
						for (x in photos) {
							if (photos[x].small != undefined) {
								$('#flickr').append('<a href="'+photos[x].large+'" title="'+photos[x].description+'" rel="prettyPhoto[flickr]"><img src="'+photos[x].small+'" alt="'+photos[x].description+'" /></a>');
							}
						}
						$("a[rel^='prettyPhoto']").prettyPhoto();
					} else {
						$('#flickr').append('<p>There were no photos found at this location.');
					}
				}
			});

		});
		
		
		return GowallaTools.markers[index];
	},
	
	drawRadius: function(radius, circle, center, nodes, liColor, liWidth, liOpa, fillColor, fillOpa) {
		GowallaTools.removeRadius();
		
		var latConv = center.distanceFrom(new GLatLng(center.lat()+0.1, center.lng()))/100;
		var lngConv = center.distanceFrom(new GLatLng(center.lat(), center.lng()+0.1))/100;

		var points = [];
		var step = parseInt(360/nodes)||10;
		for(var i=0; i<=360; i+=step) {
			var pint = new GLatLng(center.lat() + (radius/latConv * Math.cos(i * Math.PI/180)), center.lng() + (radius/lngConv * Math.sin(i * Math.PI/180)));
			points.push(pint);
	        bounds = new GLatLngBounds();
			bounds.extend(pint);
		}
		points.push(points[0]);
		fillColor = "#0055ff";
		liWidth = 2;
		var poly = new GPolygon(points,liColor,liWidth,liOpa,fillColor,fillOpa);
		GowallaTools.map.addOverlay(poly);
		GowallaTools.radius = poly;
		return poly;
	},
	
	removeRadius: function() {
		if (GowallaTools.radius) {
			GowallaTools.map.removeOverlay(GowallaTools.radius);
		}
	}
	
};

$(document).ready(function() {
	
	var initial_username = $('input#username').val();
	$('input#username').click(function() {
		if ($(this).val() == initial_username) {
			$(this).removeClass('inactive');
			$(this).val('');
		}
		if ($(this).hasClass('loading')) {
			$(this).trigger('blur');
		}
	});
	$('input#username').blur(function() {
		if (!$(this).val() && !$(this).hasClass('loading')) {
			$(this).addClass('inactive');
			$(this).val(initial_username);
		}
	});
	$('form#enter-username').submit(function() {
		GowallaTools.checkUser();
		return false;
	});
	
});