/*

Fat Media Twitter feed script
© Fat Media 2011

*/

(function($){
	
	var TwitterFeed = function(elm,config){
		Prv.elm = $(elm);
		this.init(config);
	},
	Pbl = TwitterFeed.prototype = {},
	Prv = {};
	addError = function(group,error) {
		var errName = "error" + new Date().getTime();
		window[group] = window[group] || {};
		window[group][errName] = error;
	};
	
	// -- public config/init
	Pbl.config;
	Pbl.init;
	
	// -- private properties/methods
	Prv.singleFeed;
	Prv.ajaxURI;
	Prv.tweetSet;
	Prv.tweetList;
	Prv.doDate;
	Prv.setAjaxUri;
	Prv.bindData;
	Prv.makeRequest;
	Prv.backup;
		
	Pbl.config = {
		date: 'date', //  date or difference
		display: "list", // box or list
		errorHtml: "<ul><liTwitter feed currently unavailable</li></ul>",
		hashTags: "",
		loadingHtml: "Loading twitter feed...",
		nextLinkText: "&raquo;",
		prevLinkText: "&laquo;",
		screenNames: "",
		shoutOuts: "",
		tweetCount: 10
	};
	
	Prv.singleFeed = false; // used for the different date formats twitter gives you
	Prv.ajaxURI = "";
	
	// -- "box" display
	Prv.tweetSet = function(tweets){
		var config = Pbl.config,
		curTweet = 0,
		tweetCount = tweets.length,
		nextBtn = document.createElement("a"),
		prevBtn = document.createElement("a"),
		dateSpan = document.createElement("span"),
		authorSpan = document.createElement("span"),
		tweet = document.createElement("span"),
		showTweet = function(i) {
			if(i < 0 || i > tweetCount-1) { return false };
			var username = tweets[i].from_user || tweets[i].user.screen_name;
			tweet.innerHTML = Fat.parseTweet(tweets[i].text);
			dateSpan.innerHTML = Prv.doDate(tweets[i].created_at) + " ";
			authorSpan.innerHTML = Fat.parseTweet("@" + username);
			curTweet = i;
		};
		
		nextBtn.innerHTML = config.nextLinkText;
		prevBtn.innerHTML = config.prevLinkText;
		
		nextBtn.setAttribute(Fat.classAttribute,"twitterNext");
		prevBtn.setAttribute(Fat.classAttribute,"twitterPrev");
		dateSpan.setAttribute(Fat.classAttribute,"twitterDate");
		authorSpan.setAttribute(Fat.classAttribute,"twitterAuth");
		tweet.setAttribute(Fat.classAttribute,"twitterText");
		
		nextBtn.onclick = function(){
			showTweet(curTweet+1);
		};
		
		prevBtn.onclick = function(){
			showTweet(curTweet-1);
		};
		
		showTweet(0);
		
		Prv.elm.append(nextBtn, prevBtn, tweet, dateSpan, authorSpan);
	};
	
	// -- "list" display
	Prv.tweetList = function(tweets){
		var alt = false,
		isFirst = true,
		list = document.createElement("ul"),
		createTweet = function(tweet){
			var username = tweet.from_user || tweet.user.screen_name,
			
			wrap = document.createElement("li"),
			date = document.createElement("span"),
			author = document.createElement("span"),
			text = document.createElement("span");
			
			date.setAttribute(Fat.classAttribute,"tweet_time");
			author.setAttribute(Fat.classAttribute,"tweet_auth");
			text.setAttribute(Fat.classAttribute,"tweet_text");
			if(isFirst) {
				wrap.setAttribute(Fat.classAttribute, "tweet_first tweet_odd")
			} else {
				wrap.setAttribute(Fat.classAttribute, alt ? "tweet_even" : "tweet_odd")
			};
			
			text.innerHTML = Fat.parseTweet(tweet.text);
			date.innerHTML = Prv.doDate(tweet.created_at) + " ";
			author.innerHTML = Fat.parseTweet("@" + username);
			
			$(wrap).append(author,text,date);
			list.appendChild(wrap);
		};
		for(var x in tweets) {
			try {
				createTweet(tweets[x]);
				alt = !alt;
				isFirst = false;
			} catch(e) {
				window.twitterError = e;
			};
		};
		list.setAttribute(Fat.classAttribute,"tweet_list");
		Prv.elm.append(list);
	};	
	
	// -- make a useable date from twitter's date
	Prv.doDate = function(rawDate) {
		var config = Pbl.config,
		$return = false;
		if(config.date == 'date') { return rawDate.split(" +")[0] };
		if(config.date == 'difference') {
			if(singleFeed) {
				theArray = rawDate.split(" ")
				theArray[0] += ",";				
				theArray.splice(3,0,theArray.pop());				
				theArray.splice(2,0, theArray.splice(1,1));				
				rawDate = theArray.join(" ");
			};
			var today = new Date(),
			tDate = new Date(rawDate),
			oneSec = 1000,
			oneMin = oneSec * 60,
			oneHour = oneMin * 60,
			oneDay = oneHour * 24,
			oneWeek = oneDay * 7,
			oneMonth = oneWeek * 4,
			msDiff = today.getTime()-tDate.getTime();
			if(msDiff >= oneMonth) $return = Math.round(msDiff/oneMonth) + " month";
			else if(msDiff >= oneWeek) $return = Math.round(msDiff/oneWeek) + " week";
			else if(msDiff >= oneDay) $return = Math.round(msDiff/oneDay) + " day";
			else if(msDiff >= oneHour) $return = Math.round(msDiff/oneHour) + " hour";
			else if(msDiff >= oneMin) $return = Math.round(msDiff/oneMin) + " minute";
			else if(msDiff >= oneSec) $return = Math.round(msDiff/oneSec) + " second";
			if(parseInt($return) > 1) $return = $return + "s";
			if($return) return ($return + " ago");
			return "less than 1 second ago";
		};
	};
	// -- set URI for ajax request dependent on config
	Prv.setAjaxUri = function(){
		var config = Pbl.config,
		tmpURI = "",
		rex = /^(@|#)/i,
		scArr = config.screenNames.split(","),
		hashArr = config.hashTags.split(","),
		shoutArr = config.shoutOuts.split(","),
		searchTerms = scArr.concat(hashArr).concat(shoutArr);
		
		if(config.hashTags == "" && config.shoutOuts == "" && config.screenNames.split(",").length === 1) {
			singleFeed = true;
			tmpURI = "http://api.twitter.com/1/statuses/user_timeline.json?count="+config.tweetCount+"&include_rts=true&screen_name="+config.screenNames+"&callback=?";
		} else {
			for(var x in searchTerms) {
				var word = searchTerms[x];
				if(word !== "") {
					searchTerms[x] = encodeURIComponent(rex.test(word) ? word : "from:" + word);
					tmpURI += searchTerms[x] + "+OR+";
				};
			};
			tmpURI = "http://search.twitter.com/search.json?q=" + tmpURI.substring(0,tmpURI.length-4) + "&rpp="+config.tweetCount+"&callback=?";
		};
		Prv.ajaxURI = tmpURI;
	};
	// -- pass data to relevant display function after successful ajax
	Prv.bindData = function(data) {
		var config = Pbl.config;
		Prv.elm.removeClass("ajaxLoading");
		Prv.elm.each(function(){
			var feedData = data.results || data;
			tweets = config.display == "list" ? Prv.tweetList(feedData) : Prv.tweetSet(feedData,this);
			$(this).addClass("twitter" + config.display);
		});
	};
	// -- ajax request function
	Prv.makeRequest = function(url,data,failfn){
		var x = $.ajax({
			type: 'GET',
			url: url,
			dataType: 'json',
			data: data || "",
			success: function(o) {
				Prv.bindData(o)
			},
			error: function(e) {
				var errorName = "error" + new Date().getTime();
				window.ajaxErrors = window.ajaxErrors || {};
				window.ajaxErrors[errorName] = e;
				failfn && failfn(e);
			}
		});
	};
	// -- fallback in case direct ajax to twitter fails
	Prv.backup = function(){
		var backupUrl = "/twitter/twitter.asp",
			backupData = "url=" + escape(Prv.ajaxURI.replace("callback=?",""));
			
		Prv.makeRequest(backupUrl,backupData,function(e){
			Prv.elm.removeClass("ajaxLoading").html(Pbl.config.errorHtml);
			var errorName = "error" + new Date().getTime();
			window.ajaxErrors = window.ajaxErrors || {};
			window.ajaxErrors[errorName] = e;
		})
	};	
	// -- begin
	Pbl.init = function(config) {
		Prv.elm.addClass("ajaxLoading");
		
		if(typeof config == 'object') { Pbl.config = $.extend(Pbl.config, config); }
		else {Pbl.config.screenNames = config};
		
		Prv.setAjaxUri();
		Prv.makeRequest(Prv.ajaxURI,"",Prv.backup);
	};
	// -- expose TwitterFeed class to global scope to preserve your privates
	window.TwitterFeed = TwitterFeed;
	
})(window.jQuery);
