/**
 * 
 * TwiConvEn (Twitter Conversation Engine)
 * 
 * @author kchevalier@suntouchdesign.com
 *  july, 2009
 */


// Twitter Conversation Engine
var TwiConvEn = {
	
	interval: 10000,
	scrollSpeed: 2000,
	conversationBoxId: 'twitterConversation',
	conversationURL: 'http://bigbizshow.com/wp-content/themes/bigbizshow/twitter/',
	tweetCharLenth: 128,
	
	conversationBox: '',
	scrollBox: '',
	contentBox: '',
	statusBox: '',
	
	username: '',
	userid: '',
	
	fullApp: true,
	tweetRequest: '',
	tweets: [],
	tweetsMaxLength: 20,
	scrollOffset: 0,
	loggedIn: false,
	rePx: /(-?\d+)px/,
	reUserinfo: /^id=(.*?)&screen_name=(.*)$/,
	reCreatedAt: /\w+, (\d+) (\w+) (\d+) (\d{2}:\d{2}:\d{2}) \+(\d{4})/,
	
	// initialize app
	init: function( fullApp ) {
		
		// initialize environment
		TwiConvEn.fullApp = fullApp;
		TwiConvEn.tweetRequest = TwiConvEn.conversationURL + 'tweetSearchJSON.php';
		//TwiConvEn.tweetRequest = TwiConvEn.conversationURL + 'twitter.json';
		TwiConvEn.conversationBox = $( '#' + TwiConvEn.conversationBoxId );
		TwiConvEn.conversationBox.append( "<div id='statusBox'></div><div id='scrollBox'><div id='contentBox'></div></div>" );
		TwiConvEn.scrollBox = $('#scrollBox');
		TwiConvEn.contentBox = $('#contentBox');
		TwiConvEn.statusBox = $('#statusBox');
		TwiConvEn.contentBox.css( { padding: "10px 10px 10px 20px" } );
		var offsetMatch = TwiConvEn.rePx.exec( TwiConvEn.contentBox.css( "padding-top" ) );
		TwiConvEn.scrollOffset = TwiConvEn.scrollBox.height() - parseInt( offsetMatch[1] );
		
		// initialize authorized session
		if ( TwiConvEn.cookie( 'oauth_access' ) == 'true' ) {
			TwiConvEn.loggedIn = true;
		}
		
		// add login link/status update form for full application
		if ( TwiConvEn.fullApp ) {
			
			if ( TwiConvEn.loggedIn ) {
				
				// initialize user info
				var userInfoMatches = [];
				if ( userInfoMatches = TwiConvEn.reUserinfo.exec( TwiConvEn.cookie( 'twitter_user_info' ) ) ) {
					TwiConvEn.userid = userInfoMatches[1];
					TwiConvEn.username = userInfoMatches[2];
				}
				
				// add update status form html
				TwiConvEn.statusBox.append( "<p class='greeting'>Hello, " + TwiConvEn.username + ". <a href='" + TwiConvEn.conversationURL + "twiLogout.php'>logout</a></p>" );
				TwiConvEn.statusBox.append( "<div id='message'></div>" );
				TwiConvEn.statusBox.append( "<div id='twitterForm'><form method='post' action='./twiAccess.php'><input type='hidden' class='hidden' name='update' value='true' /><label></label><textarea name='text' id='text' class='count' maxlength='" + TwiConvEn.tweetCharLenth + "'></textarea><br /><input type='submit' name='submit' id='submit' value='Update Status' /></form><p class='note'>('@bigbizshow' will be prepended to your tweet automatically.)</p></div>" );
				var count = new TwiConvEn.Count();
				count.init();
				
				// make update status form ajaxified
				$('#submit').bind( 'click', function(e) {
					e.preventDefault();
					
					$.ajax({
						type: 'POST',
						url: TwiConvEn.conversationURL + "twiAccessAJAX.php",
						dataType: 'xml',
						data: { update: 'true', text: $('#text').val() },
						success: function(data){
							var success = $(data).find("success").text();
							var message = $(data).find("message").text();
							$('#message').html( '<p>' + message + '</p>' );
							$('#text').val( '' );
							$('span.counter').text( TwiConvEn.tweetCharLenth );
							setTimeout( "TwiConvEn.removeMessage()", 30000 );
						}
					});
				} );
			}
			
			else {
				TwiConvEn.statusBox.append( "<p class='twitterLoginLink'><a href='" + TwiConvEn.conversationURL + "twiAccess.php'>Add Your Comments</a></p>" );
			}
		}
		
		// initial json request
		$.getJSON( 
			TwiConvEn.tweetRequest,
			function(data){
				$.each( data.results, function( i, result ) {
					if ( i <= TwiConvEn.tweetsMaxLength-1 ) {
						TwiConvEn.tweets.push( new TwiConvEn.Tweet( TwiConvEn.contentBox, result.id, result.text, result.from_user_id, result.from_user, result.to_user_id, result.to_user, result.iso_language_code, result.source, result.profile_image_url, result.created_at ) );
					}
				} );
				TwiConvEn.addStartingTweets();
				setTimeout( "TwiConvEn.run()", TwiConvEn.interval );
			});
			
	},
	
	// add initial tweets to conversation
	addStartingTweets: function() {
		for( i=TwiConvEn.tweets.length-1; i>=0; i-- ) {
			TwiConvEn.tweets[i].add();
		}
		TwiConvEn.scrollBox.scrollTop( 0 );
	},
	
	// checks for new tweets at a regular interval
	run: function() {
		
		var scroll = false;
		var pushTweets = [];
		
		$.getJSON(
			TwiConvEn.tweetRequest,
			function(data) {
				$.each( data.results, function( i, result) {
					var add = true;
					for( j=0; j<TwiConvEn.tweets.length; j++ ) {
						if ( result.id == TwiConvEn.tweets[j].id ) {
							add = false;
							break;
						}
					}
					if ( add ) {
						scroll = true;
						pushTweets.unshift( new TwiConvEn.Tweet( TwiConvEn.contentBox, result.id, result.text, result.from_user_id, result.from_user, result.to_user_id, result.to_user, result.iso_language_code, result.source, result.profile_image_url, result.created_at ) );
					}
				});
				if ( scroll ) {
					TwiConvEn.addTweets( pushTweets );
				}
			} );
		setTimeout( "TwiConvEn.run()", TwiConvEn.interval );
	},
	
	addTweets: function( pushTweets ) {
		var tweetHeight = 0;
		for ( i=0; i<pushTweets.length; i++ ) {
			TwiConvEn.tweets.unshift( pushTweets[i] );
			TwiConvEn.tweets[0].add();
			tweetHeight += TwiConvEn.tweets[0].height();
			TwiConvEn.scrollBox.scrollTop( tweetHeight );
			if ( TwiConvEn.tweets[20] != null ) {
				TwiConvEn.tweets[20].remove();
				TwiConvEn.tweets.pop();
			}
		}
		TwiConvEn.scroll();
	},
	
	scroll: function() {
		var scrollHeight = TwiConvEn.contentBox.height() - TwiConvEn.scrollOffset;
		TwiConvEn.scrollBox.animate( { scrollTop: 0 }, TwiConvEn.scrollSpeed, 'swing' );
	},
	
	cookie: function (c_name) {
		if (document.cookie.length>0) {
			c_start=document.cookie.indexOf(c_name + "=");
			if (c_start!=-1) {
				c_start=c_start + c_name.length+1;
				c_end=document.cookie.indexOf(";",c_start);
				if (c_end==-1) c_end=document.cookie.length;
				return unescape(document.cookie.substring(c_start,c_end));
			}
		}
		return "";
	},
	
	removeMessage: function() {
		$('#message').fadeOut( 1000 );
	},
	
	// individual Twitter Status Update Object
	Tweet: function ( contentBox, id, text, from_user_id, from_user, to_user_id, to_user, iso_language_code, source, profile_image_url, created_at ) {
		
		// initialize properties
		this.contentBox = contentBox;
		this.id = id;
		this.text = text;
		this.from_user_id = from_user_id;
		this.from_user = from_user;
		this.to_user_id = to_user_id;
		this.to_user = to_user;
		this.iso_language_code = iso_language_code;
		this.source = source;
		this.profile_image_url = profile_image_url;
		this.created_at = created_at;
		this.div = null;
		
		this.timeAgo = '';
		
		// add tweet div to document body
		this.add = function() {
			this.timeAgo = this.makeTime( this.created_at );
			var tweetDiv = '<div id="' + this.id + '" class="tweet"><p class="tweetContent">' + this.text + '</p><div class="tweetBottom"></div><img src="' + this.profile_image_url + '" width="48" height="48" /><div class="creds"><strong>' + this.from_user + ':</strong> <em>' + this.timeAgo + '</em></div></div>';
			this.contentBox.prepend( tweetDiv );
			this.div = $('#' + this.id);
		}
		
		// remove tweet div from document body
		this.remove = function() {
			this.div.remove();
		}
		
		// return tweet div height
		this.height = function() {
			return this.div.height();
		}
		
		// create relative time from creation time
		this.makeTime = function( created_at ) {
			if ( TwiConvEn.reCreatedAt.test( created_at ) ) {
				
				// date math
				var now = new Date();
				var times = TwiConvEn.reCreatedAt.exec( created_at );
				var created_timestamp = Date.parse( times[2] + ' ' + times[1] + ', ' + times[3] + ' ' + times[4] );
				var now_timestamp = now.getTime() + ( now.getTimezoneOffset() * 60 * 1000 );
				var dif_minutes = ( now_timestamp - created_timestamp ) / 60 / 1000;
				
				// return nice time
				if ( dif_minutes < 1.5 ) { return '1 minute ago'; }
				else if ( dif_minutes < 60 ) { 
					return Math.round( dif_minutes ) + ' minutes ago'; 
				}
				else if ( dif_minutes < 1440 ) {
					var dif_hours = Math.round( dif_minutes / 60 );
					if (dif_hours == 1) { return '1 hour ago'; }
					else { return dif_hours + ' hours ago'; }
				}
				else if ( dif_minutes < 44640 ) {
					var dif_days = Math.round( dif_minutes / 1440 );
					if (dif_days == 1) { return '1 day ago'; }
					else { return dif_days + ' days ago'; }
				}
				else if ( dif_minutes < 535680 ) {
					var dif_months = Math.round( dif_minutes / 44640 );
					if (dif_months == 1) { return '1 month ago'; }
					else { return dif_months + ' months ago'; }
				}
				else { return 'years ago'; }
			}
			else {
				return created_at;
			}
		}
	},
	
	// object to count characters in a textarea
	Count: function() {
		
		var count = this;
		
		this.init = function() {
			jQuery.each( $('textarea.count'), function() {
				$(this).prev().append( '<span class="counter">' + ( $(this).attr('maxlength') - $(this).val().length ) + '</span>' );
				$(this).bind( 'keydown', function( e ) {
					count.noType( e, $(this) );
				} );
				$(this).bind( 'keyup', function( e ) {
					count.find( e, $(this) );
				} );
			} );
		}
		
		this.find = function( e, obj ) {
			var charsLeft = $(obj).attr('maxlength') - $(obj).val().length;
			$(obj).parent().children('label').children('span.counter').text( charsLeft );
		}
		
		this.noType = function( e, obj ) {
			var editKeys = /^(?:8|9|13|16|17|18|19|20|27|33|34|35|36|37|38|39|40|45|46|112|113|114|115|116|117|118|119|120|121|122|123|144|145)$/;
			var charsLeft = $(obj).attr('maxlength') - $(obj).val().length;
			if ( charsLeft < 1 ) {
				if ( !editKeys.test( e.keyCode ) ) {
					e.preventDefault();
				}
			}
		}
	}
};
