/* 
Desired feeds:
* most recent tweet
* most recent Tumblr post
* 5 most recent Flickr pictures
* most recently liked video (Vimeo or YouTube or both?)
* 3 most recent Delicious bookmarks
* most recent song scrobbled on Last.fm
* most recent Foursquare location
*/

// regexp to linkify URLs, which twitter annoyingly does not do automatically
var linkexp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;

// Twitter passes in a weird date format; rearrange it so Date() can parse it
function fudgeTwitterDate(date) {
	var dsplit = date.split(' ');
	return Date.parse(dsplit[1]+" "+dsplit[2]+", "+dsplit[5]+" "+dsplit[3]+" UTC");
}

var FeedLoader = function() {
	// not much needs to happen to instantiate this guy
}

// generic data fetcher
FeedLoader.prototype.getData = function() {
	var call = this.parent.call;
	if(typeof(this.args) != undefined) {
		jQuery.extend(true, call, this.args);
	}
	this.load = jQuery.ajax({
			dataType: "jsonp",
			crossDomain: true,
			url: this.parent.f,
			data: call,
			success: this.parseData
		}
	);
}

// generic article builder - simplifies individual parseData functions
FeedLoader.prototype.buildArticle = function(data, nodebuilder) {
	// first, the article container
	var article = $(document.createElement('div'))
		.attr('id', this.parent.id+"-feed")
		.addClass('article');
	// then, the article description (icon & site link)
	var description = $(document.createElement('p'))
		.addClass('description')
		.appendTo(article);
	var sitelink = $(document.createElement('a'))
		.attr('href', this.parent.u)
		.appendTo(description);
	var siteicon = $(document.createElement('img'))
		.addClass('icon')
		.attr('src', this.parent.i)
		.attr('alt', this.parent.name)
		.attr('title', this.parent.name)
		.appendTo(sitelink);
	// then the article body container
	var articleBody = $(document.createElement('div')).addClass('article-body')
		.appendTo(article);
	// iterate over child objects
	data.forEach( function(item, key) {
		// call in the instance's custom article builder
		var content = nodebuilder(key, item);
		content.appendTo(articleBody);
	});
	this.article = article;
	// give the injector a hash with the data it needs 
	this.injectArticle({
		"date": this.timestamp,
		"article": this.article,
		"loader": this
	}); 
}

// sort articles by date and insert into DOM
FeedLoader.prototype.injectArticle = function(newarticle) {
	var articlename = newarticle.loader.parent.name;
	var articledate = newarticle.date;
	// console.log('injecting '+articlename+'; original Feed.articles length is '+Feed.articles.length);
	if(Feed.articles.length === 0) {
		// console.log(articlename+' is first article ('+articledate+')');
		Feed.articles.push(newarticle);
		$('#articles').append(newarticle.article);		
	} else {
		var key = 0;
		var matched = false;
		do {
			if(key == Feed.articles.length) {
				// console.log(articlename+' is oldest article ('+articledate+'), pushing to end');
				$('#articles').append(newarticle.article);
				Feed.articles.push(newarticle);
				matched = true;
			} else if(articledate.compare(Feed.articles[key].date) > 0) {
				// console.log(Feed.articles[key].date+' ('+Feed.articles[key].loader.parent.name+') is older than '+articledate+' ('+articlename+'), splicing in at key '+key);
				Feed.articles[key].article.before(newarticle.article);
				Feed.articles.splice(key, 0, newarticle);
				matched = true;
			}			
			key++;
		} while(!matched && key <= Feed.articles.length);
	}
	newarticle.article.hide().slideDown(1000, "swing");
	// console.log('new Feed.articles.length is '+Feed.articles.length);
}

// Twitter
var TwitterLoader = new FeedLoader();

TwitterLoader.parseData = function(data) {
	// set a general timestamp from the most recent item for sorting purposes
	TwitterLoader.timestamp = new Date(fudgeTwitterDate(data[0].created_at));
	// call article builder and give it our data and custom build function
	TwitterLoader.buildArticle(data, function(key, item) {
		var timestamp = prettyDate(new Date(fudgeTwitterDate(item.created_at)));
		var container = $(document.createElement('p')) // the tweet
			.html(item.text.replace(linkexp,"<a href='$1'>$1</a>")+" ");
		var link = $(document.createElement('a')) // the permalink
			.addClass('timestamp')
			.attr("href", 'http://twitter.com/'+item.user.screen_name+'/status/'+item.id)
			.text(' '+timestamp+' ')
			.appendTo(container);
		return container;
	});
}

// Flickr
var FlickrLoader = new FeedLoader();

FlickrLoader.args = {
	"method": "flickr.people.getPublicPhotos",
	"format": "json",
	"jsoncallback": "FlickrLoader.parseData",
	"extras": "url_sq, date_upload"
}

FlickrLoader.parseData = function(data) {
	// set a general timestamp from the most recent item for sorting purposes
	FlickrLoader.timestamp = new Date(data.photos.photo[0].dateupload*1000);
	// call article builder and give it our data and custom build function
	FlickrLoader.buildArticle(data.photos.photo, function(key, item) {
		var link = $(document.createElement('a')) // the link
			.attr('href', 'http://www.flickr.com/photos/'+item.owner+'/'+item.id+'/');
		var image = $(document.createElement('img')) // the thumbnail
			.attr('src', item.url_sq)
			.attr('alt', item.title)
			.attr('title', item.title)
			.attr('width', '75')
			.attr('height', '75')
			.appendTo(link);
		return link;
	});
}

// Tumblr
var TumblrLoader = new FeedLoader();

TumblrLoader.args = {
	"jsonp": "TumblrLoader.parseData"
}

TumblrLoader.parseData = function(data) {
	// set a general timestamp from the most recent item for sorting purposes
	TumblrLoader.timestamp = new Date(data.response.posts[0].timestamp*1000);
	// call article builder and give it our data and custom build function
	TumblrLoader.buildArticle(data.response.posts, function(key, item) {
		var timestamp = prettyDate(new Date(item.timestamp*1000));
		var container = $(document.createElement('div'));
		// tumblr has lots of different post types, hence many article builders
		switch (item.type) {
			case "text":
				// title, body
				container.html(item.body);
				var title = $(document.createElement('h4'))
					.html(item.title)
					.prependTo(container);
			break;
			case "photo":
				// photos[].alt_sizes[3].url, photos[].caption OR caption
				container.html(item.caption);
				var photoset = $(document.createElement('div'))
					.prependTo(container);
				item.photos.forEach( function(item, key) {
					var photo = $(document.createElement('img'))
						.attr('src', item.alt_sizes[1].url)
						.attr('width', item.alt_sizes[1].width)
						.attr('height', item.alt_sizes[1].height)
						.appendTo(photoset);
					if(item.caption) var caption = $(document.createElement('p'))
						.text(item.caption)
						.appendTo(photoset);
				});
			break;
			case "link":
				// title, url, description
				var link = $(document.createElement('a'))
					.attr('href', item.url)
					.text(item.title)
					.appendTo(container);
				var description = $(document.createElement('p'))
					.text(item.description)
					.appendTo(container);
			break;
			case "quote":
				// text, source
				var quotetext = $(document.createElement('blockquote'))
					.html(item.text)
					.appendTo(container);
				var quotesource = $(document.createElement('p'))
					.addClass('quote-source')
					.html(item.source)
					.appendTo(container);
			break;
			case "video":
				// player, caption
				container.html(item.player[2].embed_code);
				var caption = $(document.createElement('p'))
					.html(item.caption)
					.appendTo(container);
			break;
			case "audio":
				// player, caption
				container.html(item.player.embed_code);
				var caption = $(document.createElement('p'))
					.html(item.caption)
					.appendTo(container);				
			break;
			case "answer":
				// question, answer
				container.html(post.answer);
				var title = $(document.createElement('p'))
					.addClass('post-title')
					.html(item.question)
					.prependTo(container);
			break;
			case "chat":
				// title, body
				container.html(item.player);
				var title = $(document.createElement('p'))
					.addClass('post-title')
					.html(item.title)
					.prependTo(container);
			break;
			default:
				var fallbacklink = $(document.createElement('a'))
					.attr('href', item.post_url)
					.text('A Tumblr post of a type which this site has yet to accommodate')
					.appendTo(container);
				// post_url
			break;
		}
		var postlink = $(document.createElement('a')) // the permalink
			.addClass('timestamp')
			.attr('href', item.post_url)
			.text(' '+timestamp+' ')
			.appendTo(container);
		return container;
	});
}

// Last.fm
var LastFMLoader = new FeedLoader();

LastFMLoader.args = {
	"method": "user.getRecentTracks",
	"format": "json",
	"callback": "LastFMLoader.parseData"
}

LastFMLoader.parseData = function(data) {
	// normalize last.fm's weird JSON – it only passes an array if there's more than one item
	tracks = (typeof(data.recenttracks.track.length) != "undefined") ? data.recenttracks.track : new Array(data.recenttracks.track);
	// set a general timestamp (note: if there's a currently playing track, it doesn't have a timestamp, so use now())
	LastFMLoader.timestamp = (tracks[0].date) ? (new Date(tracks[0].date.uts*1000)) : new Date();
	// call article builder and give it our data and custom build function
	LastFMLoader.buildArticle(tracks, function(key, item) {
		var timestamp = item.date ? prettyDate(new Date(item.date.uts*1000)) : prettyDate(new Date());
		var container = $(document.createElement('div')) // the track info
			.html('<strong>'+item.artist['#text']+"</strong>\n<br/>&ldquo;"+item.name+"&rdquo;<br/><em>"+item.album['#text']+"</em><br/>");
		var link = $(document.createElement('a')) // the permalink
			.addClass('timestamp')
			.attr("href", item.url)
			.text(" "+timestamp+" ")
			.appendTo(container);
		if(item.image[1]['#text'] != '') {
			var image = $(document.createElement('img')) // the album art
				.attr('src', item.image[1]['#text'])
				.attr('width', '64')
				.attr('height', '64')
				.addClass('album-art')
				.prependTo(container);
		} else {
			var image = $(document.createElement('div')) // album art placeholder
				.addClass('no-album-art')
				.text('no art')
				.prependTo(container);
		}
		return container;
	});
}

// Delicious
var DeliciousLoader = new FeedLoader();

DeliciousLoader.args = {
	"callback": "DeliciousLoader.parseData"
}

DeliciousLoader.parseData = function(data) {
	// set a general timestamp from the most recent item for sorting purposes 
	DeliciousLoader.timestamp = Date.parseIso8601(data[0].dt); // Delicious' date format is weird
	// call article builder and give it our data and custom build function
	DeliciousLoader.buildArticle(data, function(key, item) {
		var timestamp = prettyDate(Date.parseIso8601(data[0].dt));
		var container = $(document.createElement('div'));
		var link = $(document.createElement('a')) // the bookmark link & title
			.attr("href", item.u)
			.text(item.d)
			.appendTo(container);
		var notes = $(document.createElement('p')) // the bookmark notes
			.html(item.n)
			.appendTo(container);
		var permalink = $(document.createElement('a')) // in lieu of permalink, link to profile page
			.addClass('timestamp')
			.attr("href", 'http://delicious.com/'+item.a)
			.text(' '+timestamp+' ')
			.appendTo(container);
		return container;
	});	
}

// collect the custom feed data loaders so they can be found later
FeedLoader.APIs = {
	'Twitter': TwitterLoader,
	'Flickr': FlickrLoader,
	'Tumblr': TumblrLoader,
	'Last.fm': LastFMLoader,
	'Delicious': DeliciousLoader
}//	'Vimeo': '',
//	'YouTube': '',


