var map, icon, focus, searchText, formText, geocoder;
var tweets = new Array();
var updates = 5;

$(document).ready(function() {
	$('#javascript').hide();
	google.load('maps', '2', {'callback': mapsLoaded});
});

function mapsLoaded() {	
	if (google.maps.BrowserIsCompatible()) {	
		setStatus('Loading...');
		
		$.ajaxSetup({
			'timeout': 10000,
			'error': function (XMLHttpRequest, textStatus, errorThrown) {
				setStatus('Failed to load tweets', 5);
			}
		});
	
		//focus = new google.maps.LatLng(google.loader.ClientLocation.latitude, google.loader.ClientLocation.longitude);
		
		initGMaps();
		initMenu();
		initMore();
		initSearchBox();
		initStatusForm();
		
		$(document).oneTime('1s', function() { loadTweets(true); }).everyTime('30s', function() { loadTweets(false); });
	}
	else {
		setStatus('Browser not compatible');
	}
}

function initMore() {
	$('#more').click(function() {
		updates =  (updates == 5) ? 10 : 5;
		$(this).text((updates == 5) ? 'Show more...' : 'Show less...');
		if (updates == 5) {
			$('#list li:gt(4)').slideUp(500, function() { 
				updateList(); 
			});
		}
		else {
			updateList();
			$('#list li:gt(4)').hide().slideDown(500);
		}
		return false;
	});
}

function initMenu() {
	$('a[href=#find]').click(function() { $('body').scrollTo('#find', 500); return false; });
	$('a[href=#hear]').click(function() { $('body').scrollTo('#hear', 500); return false; });
	$('a[href=#say]').click(function() { $('body').scrollTo('#say', 500); return false; });
	$('a[href=#see]').click(function() { $('body').scrollTo('#see', 500); return false; });
	$(window).resize(function() {
		$('#menu').css('left', ($(this).width()/2)-550);
	}).resize();
}

function initStatusForm() {
	$('#submit').click(function() {
		$.post('/app/json.php?method=update', 
			{ user: $('#user').val(), pass: $('#pass').val(), text: $('#text').val() },
			function(data) {
				if (data.updated) {
					$('#user').val('');
					$('#pass').val('');
					$('#text').val('');
					alert('Message posted to Twitter!');
				}
				else {
					alert('Update failed. Check your username and password.');
				}
			},
			'json');
	});
	formText = $('form #text').focus(function() {
		if ($(this).val() == formText) $(this).val('');
	}).blur(function() {
		if ($(this).val().length == 0) $(this).val(formText);
	}).val();
	$('form #user').focus(function() {
		if ($(this).val() === 'username') $(this).val('');
	});
	$('form #pass').focus(function() {
		if ($(this).val() === 'password') $(this).val('');
	});	
}

function initSearchBox() {
	searchText = $('#search').focus(function() {
		if ($(this).val() == searchText) $(this).val('');
	}).blur(function() {
		if ($(this).val().length == 0) $(this).val(searchText);
	}).keyup(function(e){
    	if (e.keyCode == 13) {
    		setStatus('Searching...');
        	findAddress($(this).val());
    	}
	}).val();
}

function initGMaps() {
	map = new google.maps.Map2(document.getElementById("map"));
	map.setUIToDefault();
	map.setMapType(G_NORMAL_MAP);
	map.setCenter(new google.maps.LatLng(38, -98), 4);
	
	icon = new google.maps.Icon(G_DEFAULT_ICON);
	icon.iconAnchor = new google.maps.Point(14, 38);
	icon.iconSize = new google.maps.Size(28, 76);
	icon.image = '/images/icon.Generic64.png';
	icon.shadow = '/images/icon.Shadow64.png';
	icon.shadowSize = new google.maps.Size(76, 76);
	icon.infoWindowAnchor = new google.maps.Point(14, 7);
	
	geocoder = new google.maps.ClientGeocoder();
}

function sortTweetsById() {
	tweets = tweets.sort(function(x, y) {
		return y.id - x.id;
	});
}

function sortTweetsByDistance() {
	tweets = tweets.sort(function(x, y) {
		x = x.located ? x.distance : 25000; // miles
		y = y.located ? y.distance : 25000; // miles
		return x - y;
	});
}

function findAddress(a) {
	geocoder.getLatLng(a, function(p) {
      	if (!p) {
        	setStatus('Could not find "'+a+'"');
      	}
      	else {
      		setStatus('', 1);
      		map.setCenter(p, 9);
        	focus = p;
      	}
    });
}

function linkify(s) {
	var urls = s.match(/http\S+/ig);
	if (urls) {
		for (u = 0; u < urls.length; u++) {
			var url = urls[u];
			var t = (url.length > 30) ? url.substr(0, 27)+'...' : url;
			var a = '<a href="'+url+'" target="_blank">'+t+'</a>';
			s = s.replace(url, a);
		}
	}
	return s;
}

function calculateDistancesFrom(p) {
	$.each(tweets, function(i, tweet) {
		if (tweet.located) {
			tweet.distance = tweet.location.distanceFrom(p, 3963).toFixed(1); // miles
		}
	});
}

function findNearestTweet() {
	calculateDistancesFrom(focus);
	sortTweetsByDistance();
	if (tweets[0].located) {
		map.setCenter(tweets[0].location, 12);
		google.maps.Event.trigger(tweets[0].marker, 'click');
	}
}

function latestId() {
	sortTweetsById();
	if (tweets.length > 0) {
		return tweets[0].id;
	}
	return 0; 
}

function updatePhotos() {
	sortTweetsById();	
	$.each(tweets, function(i, tweet) {
		if (tweet.picLinkUrl && tweet.picThumbUrl && ($('#photos li a img[src='+tweet.picThumbUrl+']').length == 0)) {
			$('#photos').prepend('<li><a href="'+tweet.picLinkUrl+'" target="_blank"><img alt="" src="'+tweet.picThumbUrl+'" /></a></li>');
		}
	});
}

function updateList() {
	sortTweetsById();
	$('#list').empty();
	$.each(tweets, function(i, tweet) {
		if (i < updates) {			
			var li = '<li><a class="profile-pic" href="http://twitter.com/'+tweet.from_user+'" target="_blank"><img alt="'+tweet.from_user+'" src="'+tweet.profile_image_url+'"  /></a><div class="tweet"><h3><a href="http://twitter.com/'+tweet.from_user+'" target="_blank">'+tweet.from_user+'</a></h3>'+tweet.text+'';
			if (tweet.location != null) li += ' <a class="location" href="#">Show location</a>';
			li += '</div></li>';
			$('#list').append(li);
			$('#list li:last a.location').click(function() { 
				$('body').scrollTo('#search-bar', 500);
				map.setCenter(tweet.location, 16);
				google.maps.Event.trigger(tweet.marker, 'click');
				return false; 
			});
		}
	});
}

function loadTweets(firstLoad) {
	setStatus('Loading tweets...');
	$.getJSON('/app/json.php?method=tweets&latest='+latestId(), function(data) {
		if (data.tweets) {
			$.each(data.tweets, function(i, tweet) {			
				tweet.text = linkify(tweet.text);
								
				var twitpic = tweet.text.match('http://twitpic.com/([A-Za-z0-9]{5})');
				if (twitpic) {
					tweet.picLinkUrl = twitpic[0];
					tweet.picThumbUrl = 'http://twitpic.com/show/thumb/'+twitpic[1];
				}
				
				var yfrog = tweet.text.match('http://(www.)?yfrog.(com|us)/[A-Za-z0-9]{6,8}');
				if (yfrog) {
					tweet.picLinkUrl = yfrog[0];
					tweet.picThumbUrl = yfrog[0]+'.th.jpg';
				}			
				
				var popUpHtml = '<div class="popup"><div class="images"><a alt="'+tweet.from_user+'" class="profile-pic" href="http://twitter.com/'+tweet.from_user+'" target="_blank"><img alt="'+tweet.from_user+'" src="'+tweet.profile_image_url+'" width="48" /></a></div><div class="text"><h3><a href="http://twitter.com/'+tweet.from_user+'" target="_blank">'+tweet.from_user+'</a></h3><span>'+tweet.text+'</span></div><div class="clear"></div></div>';
				
				if (tweet.located > 0) {
					tweet.location = new google.maps.LatLng(tweet.latitude, tweet.longitude);
					
					if (/claw/i.test(tweet.text)) icon.image = '/images/icon.ClawMoney64.png';
					if (/mcmillan/i.test(tweet.text)) icon.image = '/images/icon.JeffMcMillan64.png';
					if (/cabrera/i.test(tweet.text)) icon.image = '/images/icon.NathanCabrera64.png';
					if (/pushead/i.test(tweet.text)) icon.image = '/images/icon.Pushead64.png';
					if (/bliss/i.test(tweet.text)) icon.image = '/images/icon.StephenBliss64.png';
					if (/upso/i.test(tweet.text)) icon.image = '/images/icon.UPSO64.png';
					
					tweet.marker = new google.maps.Marker(tweet.location, { icon: icon });			
					GEvent.addListener(tweet.marker, "click", function() {
						tweet.marker.openInfoWindowHtml(popUpHtml);
					});
					map.addOverlay(tweet.marker);
				}
				
				tweets.push(tweet);
				updatePhotos(tweet);
			});
			setStatus(data.tweets.length+' new tweet'+(data.tweets.length === 1 ? '' : 's')+' loaded', 3);
			//if (firstLoad) findNearestTweet();
			updateList();
			updatePhotos();			
		}
		else {
			setStatus('Tweets could not be loaded.', 3);
		}		
	});
}

function setStatus(text, hold) {
	if (text) {
		$('#status').html(text).fadeIn(30);
	}
	if (hold) {	
		$('#status').oneTime(hold+'s', function() { hideStatus(); });	
	}
}

function hideStatus() {
	$('#status').fadeOut(500); 
}