/*
	Note: this file was updated on June 19th 2011, to reflect
	changes in the Facebook API, so some lines differ from those
	in the tutorial.
*/

// Creating our plugin. You can optionally
// place it in a separate file.

(function($){
	
	$.fn.facebookWall = function(options,callbackFnk){
		
		options = options || {};
		
		// Default options of the plugin:
		
		options = $.extend({
			limit: 20,	// You can also pass a custom limit as a parameter. (default is 15 on show pages, and 20 on the home page)
			count:  6,   // default is 6 - raise both to 50 to test more than six posts at a time
			access_token:'185007668220785|xsCah084--1_hWMdr8ro_wu3U7w'
		},options);
		
		if(!options.id){
			throw new Error('You need to provide an user/page id!');
		}
		
		if(!options.access_token){
			throw new Error('You need to provide an access token!');
		}

		// Putting together the Facebook Graph API URLs:

		var graphUSER = 'https://graph.facebook.com/'+options.id+'/?fields=name,picture&access_token='+options.access_token+'&callback=?',
			graphPOSTS = 'https://graph.facebook.com/'+options.id+'/posts/?access_token='+options.access_token+'&callback=?&date_format=U&limit='+options.limit;
		
		var wall = this;
		
		// @RT 09-Nov-2011: Some posts have a link embedded in the copy, duplicating the link which is normally displayed below the post.
		// This regex can be used to detect this case and parse out the duplicate link. 
		var httpRegEx= new RegExp("http://");
		
		$.when($.getJSON(graphUSER),$.getJSON(graphPOSTS)).done(function(user,posts){
			
			// user[0] contains information about the user (name and picture);
			// posts[0].data is an array with wall posts;
			
			var fb = {
				user : user[0],
				posts : []
			};
			var count = 1;
			$.each(posts[0].data,function(){
				if(count <= options.count){
					// We only show links and statuses from the posts feed:
					// @RT 12-Oct-2011: Added music case
					// @RT 08-Nov-2011: Added video case
					// @RT 13-Nov-2011: Added photo case
					// @RT 14-Nov-2011: Added swf case (HootSuite you tube links)
					if(this.type != 'link' && this.type != 'status' && this.type != 'music' && this.type != 'video' && this.type != 'photo' && this.type != 'swf'){
						return true;
					}
					count += 1;
					
					// Copying the user avatar to each post, so it is
					// easier to generate the templates:
					this.from.picture = fb.user.picture;
					
					// Converting the created_time (a UNIX timestamp) to
					// a relative time offset (e.g. 5 minutes ago):
					this.created_time = relativeTime(this.created_time*1000);
					
					// Converting URL strings to actual hyperlinks:
					if(this.message != null){
						this.message = urlHyperlinks(this.message);
					}
					
					// @RT 12-Nov-2011: Add links to facebook people tagged in message.
					if(this.message_tags != null){
						tags = this.message_tags;
						for(var tag in tags){
							this.message = tagifyMessage(tags[tag][0].name, tags[tag][0].id, this.message);
						}
					}
					
					// @RT 10-Nov-2011: Hyperlinkify RSS Grafiti type=='link'
					if(this.description != null){
						this.description = urlHyperlinks(this.description);
					}
					
					fb.posts.push(this);
				}
			});

			// Rendering the templates:
			
			// Creating an unordered list for the posts:
			var ul = $('<ul>').appendTo(wall);
			
			// Generating the feed template and appending:
			//$('#feedTpl').tmpl(fb.posts).appendTo(ul);
			
			var done = -1;	// @RT 13-Nov-2011: Flag for a post successfully inserted. Also used to prevent double posting posts in if statments enclosed by try blocks.
			
			$.each(fb.posts,function(){			
				
				var obj = this;
				
				done = -1;
				
				var li = $('<li class="faceItem">');
				
				$('<a href="' + fbPostIdParser(obj.id, obj.from.id) + '" target="_blank" class="facebook-img"><img src="'+obj.from.picture+'" class="avatar" /></a>').appendTo(li);
				
				var status = $('<div class="status">').appendTo(li);

				//$('<h2><a href="http://www.facebook.com/profile.php?id='+obj.from.id+'" target="_blank">'+obj.from.name+'</a></h2>').appendTo(status);
				
				//if(obj.message){
				//	$('<p class="message">'+ obj.message +'</p>').appendTo(status);
				//}

				if(obj.type == "status"){
					if(obj.message){
						$('<p class="message">' + obj.message + '</p>').appendTo(status);
						done = 1;
					} 
				}
				

				if(obj.type == 'link'){
					try{
						if (obj.application.name == "RSS Graffiti" || obj.application.name == "HootSuite"){
							if(obj.description){
								$('<p class="message">'+obj.message+'<br><a href="'+obj.link+'" target="_blank">'+obj.name+'</a><br>'+obj.description+'</p>').appendTo(status);
								done = 1;
							} else {
								$('<p class="message">'+obj.message+'<br><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
								done = 1;
							}
						}
					} catch (error){} // @RT 08-Nov-2011: RSS Graffiti links sometimes throw an error
					
					if (done == -1){
						// @RT 09-Nov-2011: Old way of handling links (before 09-Nov-2011)
						if(obj.message){
							if (obj.link){
								if (obj.description){
									$('<p class="message">'+obj.message+'<br><a href="'+obj.link+'" target="_blank">'+obj.name+'</a><br>'+obj.description+'</p>').appendTo(status);
									done = 1;
								} else {
									$('<p class="message">'+obj.message+'<br><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
									done = 1;
								}
							} else {
								// @RT 09-Nov-2011: Believe it or not, some links don't have links. Stupid huh? This is what happens when a multi-billion dollar company is founded by a college dropout...
								// This case usually happens when a third party app posts the link, but the user hasn't given permission for that app to post links.
								// Solution? Just redirect to the facebook post directly and let the user give permission.
								$('<p class="message"><a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">' + obj.message + '</p>').appendTo(status);
								done = 1;
							}
						} else {
							// @RT 09-Nov-2011: New way of handling links. Also handles youtube.com links (as opposed to youtube type=='video' posts).
							// I hate the facebook api. Too many bloody cases, all with different bloody object properties!
							if(obj.name){
								$('<p class="message"><a href="'+obj.link+'" target="_blank">'+obj.name+'</a><br>'+obj.description+'</p>').appendTo(status);
								done = 1;
							}
						}
					}
				}
				

				try{
					// @RT 06-Nov-2011: Try block used because obj.caption may not exist
					if(obj.type == "music" && obj.caption == "f.cl.ly"){
						if(obj.message){
							if(httpRegEx.test(obj.message)){
								// @RT 09-Nov-2011: message has a link to f.cl.ly which doesn't diplay properly. Parse it out and link to the facebook post.
								$('<p class="message">'+obj.message.slice(0,obj.message.search('<a href'))+'<br><a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">' + obj.name + '</p>').appendTo(status);
								done = 1;
							} else {
								$('<p class="message"><a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">' + obj.message + '</a></p>').appendTo(status);
								done = 1;
							}
						}
						else if(obj.name){
							$('<p class="message"><a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">' + obj.name + '</a></p>').appendTo(status);
							done = 1;
						}
					}
				}
				catch(error){}
				
				
				try{
					// @RT 06-Nov-2011: Try block used because obj.application.name may not exist
					if(obj.type == "music" && obj.application.name == "RSS Graffiti"){
						// @RT 06-Nov-2011: 'obj.name' is the equavalent of message from RSS Graffiti
						// @RT 06-Nov-2011: fbPostIdParser() return the direct link to the facebook post.
						if(obj.message){
							$('<p class="message">'+obj.message+'<br><a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">'+obj.name+'</a><br>'+obj.description+'</p>').appendTo(status);
							done = 1;
						} else {
							$('<p class="message"><a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">'+obj.name+'</a><br>'+obj.description+'</p>').appendTo(status);
							done = 1;
						}
					}
				}
				catch(error){}
						
				
/*				// @RT: 09-Nov-2011: Not enabled, see code above.
				if (obj.type == "photo"){
					if(obj.description){
						$('<p class="message">' + obj.description + '</p>').appendTo(status);
					} else {
						if (obj.message){
							$('<p class="message">' + obj.message + '<br><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
						}
					}
				}*/

				// @RT: 13-Nov-2011
				if (obj.type == "photo"){
					if(obj.description){
						$('<p class="message">' + obj.description + '</p>').appendTo(status);
						done = 1;
					}
					else if (obj.message){
						$('<p class="message">' + obj.message + '<br><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
						done = 1;
					} 
					else {
						$('<p class="message"><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
						done = 1;
					}
				}
								
				// @RT 08-Nov-2011: YouTube case (caption == 'www.youtube.com') - may need another case for other sites, e.g. vimeo
				// @RT 09-Nov-2011: YouTube posts can also have a type == link
				if (obj.type == "video"){
					if(obj.message){
						//if(httpRegEx.test(obj.message)){
							// @RT 09-Nov-2011: Parse out double links to youtube videos. Link embedded in message. Bad form. Booo!!!
						//	$('<p class="message">' + obj.message.slice(0,obj.message.search('<a href')) + '<br><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
						//} else {
							$('<p class="message">'+obj.message+'<br><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
							done = 1;
						//}
					} else {
						// @RT 09-Nov-2011: What? You posted a youtube link and didn't add a pithy message for all your adoring fans? Get a life you link recycler!
						$('<p class="message"><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
						done = 1;
					}
				}
				
				// @RT 14-Nov-2011: HootSuite's swf case
				if (obj.type == "swf"){
					if(obj.message){
						$('<p class="message">'+obj.message+'<br><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
						done = 1;
					} else {
						$('<p class="message"><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(status);
						done = 1;
					}
				}
				
				// @RT: 09-Nov-2011: Not enabled, see code above.
				if (obj.type == "checkin"){
					if(obj.name){
						$('<p class="message">Checked in at ' + obj.name + " in " + location.city + '</p>').appendTo(status);
					}
				}
				
				// @RT: 09-Nov-2011: Not enabled, see code above.
				if (obj.type == "note"){
					if(obj.subject){
						$('<p class="message">' + obj.subject + "<br>" + obj.message + '</p>').appendTo(status);
					}
				}
				
				/*
				if(obj.type == 'link'){
					var attachment = $('<div class="attachment">').appendTo(status);
					
					if(obj.picture){$('<img class="picture" src="'+obj.picture+'" />').appendTo(attachment);}
					
					var attachmentData = $('<div class="attachment-data">').appendTo(attachment);
					if(obj.link){$('<p class="name"><a href="'+obj.link+'" target="_blank">'+obj.name+'</a></p>').appendTo(attachmentData);}
					if(obj.caption){$('<p class="caption">'+obj.caption+'</p>').appendTo(attachmentData);}
					//if(obj.description){$('<p class="description">'+obj.description+'</p>').appendTo(attachmentData);}
				}
				
				*/
				
				if (done == 1){
					li.appendTo(ul);
					// @RT: This section add timestamp, comments, and likes at the bottom of each post
					var meta = $('<p class="meta">').appendTo(li);
					
					$('<span><a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">'+obj.created_time+'</a></span>').appendTo(meta);
					
					if(obj.comments){
						var plural = '';
						if(obj.comments.count > 1 || obj.comments.count == 0){plural = 's';}
						$('<span> &bull; <a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">'+obj.comments.count+' Comment'+plural+'</a></span>').appendTo(meta);
					}
					else{
						$('<span> &bull; <a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">0 Comments</a></span>').appendTo(meta);
					}
					if(obj.likes){
						var plural = '';
						if(obj.likes.count > 1 || obj.likes.count == 0){plural = 's';}
						$('<span> &bull; <a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">'+obj.likes.count+' Like'+plural+'</a></span>').appendTo(meta);
					}
					else{
						$('<span> &bull; <a href="'+fbPostIdParser(obj.id, obj.from.id)+'" target="_blank">0 Likes</a></span>').appendTo(meta);
					}
				}
				
			});
			if(typeof callbackFnk == 'function'){
				callbackFnk.call(this);
			}
		});
		
		return this;
	};
	
	
	

	// Helper functions:
	
	// @RT 06-Nov-2011: Parse facebook post id
	function fbPostIdParser(id, from_id){
		return 'http://www.facebook.com/'+from_id+'/posts/'+id.slice(from_id.length+1);
	}

	function urlHyperlinks(str){
		return str.replace(/\b((http|https):\/\/\S+)/g,'<a href="$1" target="_blank">$1</a>');
	}
	
	// @RT 12-Nov-2011: Put the links to tagged people in the message
	function tagifyMessage(name, id, message){
		return message.replace(name, '<a href="http://www.facebook.com/'+ id +'" >' + name + '</a>');
	}

	function relativeTime(time){
		
		// Adapted from James Herdman's http://bit.ly/e5Jnxe
		
		var period = new Date(time);
		var delta = new Date() - period;

		if (delta <= 10000) {	// Less than 10 seconds ago
			return 'Just now';
		}
		
		var units = null;
		
		var conversions = {
			millisecond: 1,		// ms -> ms
			second: 1000,		// ms -> sec
			minute: 60,			// sec -> min
			hour: 60,			// min -> hour
			day: 24,			// hour -> day
			month: 30,			// day -> month (roughly)
			year: 12			// month -> year
		};
		
		for (var key in conversions) {
			if (delta < conversions[key]) {
				break;
			}
			else {
				units = key;
				delta = delta / conversions[key];
			}
		}
		
		// Pluralize if necessary:
		
		delta = Math.floor(delta);
		if (delta !== 1) { units += 's'; }
		return [delta, units, "ago"].join(' ');
		
	}
})(jQuery);
