jQuery.noConflict();
// ===== TWITTER plug-in =====
jQuery(function($){
	$.fn.singleTwitter = function(options){
		var opts = $.extend({}, $.fn.singleTwitter.defaults, options);
		$this = $(this);
		
		$this.find('li').addClass('loading');
		$.getJSON("http://twitter.com/status/user_timeline/"+opts.userName+".json?count="+opts.numTweets+"&callback=?",
			function(data){
				// reset container;
				$this.empty();
				if(!opts.user.showProfile) $(opts.profile).remove();
				// loop through x numTweets;
				$.each(data, function(i,item){
					// ===== PROFILE =====
					if(opts.user.showProfile && !opts.user.id){
						// set value to id to loop only once;
						opts.user.id = item.user.id;
						var profile = $(opts.profile);
						if(opts.user.id && profile){
							if(opts.user.showAvatar){
								profile.find('.photo').html('<img src="'+item.user.profile_image_url+'" width="48" height="48" alt="" />');
							} else { profile.find('.photo').remove() };
							
							var aProfile = [];
							profile.find('.info').html('<h2>'+item.user.screen_name+'</h2><ul></ul>');
							var info = profile.find('.info ul');
							if(opts.user.showRealName) aProfile[aProfile.length] = ('<li><b>'+item.user.name+'</b></li>');
							if(opts.user.showLocation) aProfile[aProfile.length] = ('<li>'+item.user.location+'</li>');
							if(opts.user.showWebsite) aProfile[aProfile.length] = ('<li>'+item.user.url.linkify()+'</li>');
							if(opts.user.showDescription) aProfile[aProfile.length] = ('<li>'+item.user.description.fixWidows()+'</li>');
							info.append(aProfile.join(''));
						};
					};
					
					// ===== TWEETS =====
					var text = item.text.linkify().atify().tagify();
					var date = (opts.meta.showPublishDate)? item.created_at.relativeTime(opts.meta.showRelativeDate).linkToPost(item, opts.meta.linkPublishDate) : '';
					var source = (opts.meta.showInputSource)? 'via '+item.source : '';
					var meta = (date != '' || source != '')? '<span class="meta">'+date+' '+source+'</span>' : '';
					$this.append('<li>'+text+meta+'</li>');
				});
				$this.find('li:first').addClass('first');
				// find all twitter links > open new page > spiders shouldn't follow;
				$this.find('a').attr('target','_blank').filter('[rel=""]').attr('rel','nofollow');
			}
		);
		return $this;
	};
	
	$.fn.singleTwitter.defaults = {
		userName: null,
		numTweets: 5,
		user: {
			profile: {},
			showProfile:true,
			showAvatar:true,
			showRealName:true,
			showLocation:true,
			showWebsite:true,
			showDescription:true
		},
		meta: {
			showPublishDate:true,
			linkPublishDate:true,
			showRelativeDate:true,
			showInputSource:true,
			linkInputSource:true
		},
		profile:'#twitterProfile'
	}
	
	// ===== Twitter-Specific String Prototypes =========================
	addString("atify", function(){
		return this.replace(/@[\w]+/g, function(at) {
			return "@<a href='http://twitter.com/"+at.replace('@','')+"'>"+at.replace('@','')+"</a>";
		});
	});
	
	addString("tagify", function(){
		return this.replace(/[#]+[A-Za-z0-9-_]+/g, function(tag) {
			return "#<a href='http://search.twitter.com/search?q="+tag.replace("#","%23")+"'>"+tag.replace("#","")+"</a>";
		});
	});
	
	addString("linkToPost", function(item,active){
		return (active)? "<a href='http://twitter.com/"+item.user.screen_name+"/status/"+item.id+"' rel='bookmark'>"+this+"</a>" : this;
	});
	
	/* ===== Required Global String Prototypes =========================
		trim(), linkify(), relativeTime(), fixWidows()
	*/
});


function addString(name, method){
	if(!String.prototype[name]){
		String.prototype[name] = method;
	};
};

// ===== Global String Functions =========================
addString("trim", function(){
	return this.replace( /^\s+|\s+$/g, "");					   
});

addString("linkify", function(){
	var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
	return this.replace(regexp, "<a href='$1'>$1</a>")
});

addString("fixWidows", function(){
	return this.trim().replace(/^([\W\w]*)\s([\W\w]*)$/gm, "$1&nbsp;$2");
});

addString("relativeTime", function(bRelative){
	// Mon May 25 23:15:48 +0000 2009
	var values = this.split(" "); // Sat May 02 09:30:47 +0000 2009
	if(!bRelative) return values[1] + " " + values[2] + ", " + values[5];
	
	var format = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
	var relative_to = (arguments.length > 1) ? new Date(arguments[1]) : new Date();
	var delta = parseInt((relative_to.getTime() - Date.parse(format)) / 1000);
	delta = parseInt(delta + (relative_to.getTimezoneOffset() * 60));
	
	var time = '';
	if(delta < 60){ time = 'a minute ago' }
	else if(delta < 120){ time = 'couple of minutes ago' }
	else if(delta < (45*60)){ time = ''+(parseInt(delta/60)).toString()+' minutes ago' }
	else if(delta < (90*60)){ time = 'an hour ago' }
	else if(delta < (24*60*60)){ time = ''+((parseInt(delta/3600)).toString())+' hour'+(parseInt(delta/3600)===1?'':'s')+' ago' }
	else if(delta < (48*60*60)){ time = '1 day ago' }
	else { time = (parseInt(delta / 86400)).toString() + ' days ago'; }
	return time;
});

