(function()
{

JSTwitter = {

    "USER_TIMELINE" : "http://api.twitter.com/1/statuses/user_timeline/",

    "Timeline" : function(obj)
    {
	var _timeline = obj.timeline;
	var _status = obj.status;
	var _last_row = undefined;
	var _limit = obj.limit;
	var _loader = obj.loader;

	var _replace = function( row )
	{
	    if( $("li" , _timeline).length >= _limit )
	    {
		$($("li" , _timeline)[_limit -1]).fadeOut();
	    }
	    _last_row.before( row );
	}

	var _display = function( d )
	{
	    var data = d.slice( d.length - _limit , d.length );
	    _loader.fadeOut("fast");
	    for( var i= 0 ; i < data.length ; i++)
	    {
		if( !_last_row)
		{
		    _timeline.append( data[i].li );
		}else
		{
		    _replace( data[i].li );
		}
		_last_row = data[i].li;
	    }
	}

	this.change_status = function( status )
	{
	    _status.text( status );
	}


	this.refresh = function( obj )
	{
	    if( obj.data.length > 0 )
	    {
		_display( obj.data );
	    }
	    if( obj.callback ) obj.callback();
	}


    },

    "ClientStatus" : {
	"INITIALIZED" : 0 ,
	"CREATE_LOOP" : 1 ,
	"CONNECTION" : 2,
	"CONNECTING" : 3,
	"SUCCESS" : 4,
	"COMPLETE" : 5 ,
	"TIMELINE_DISPLAYED" : 6,
	"API_ERROR" : 98,
	"AJAX_ERROR" : 99
    } ,

    "Tweet" : function(obj)
    {
	this.created_at = obj.created_at;
	this.text = obj.text;
	var text = this.text;
	var link = text.match("https?://[a-zA-Z0-9.-]{2,}(:[0-9]+)?(/[_.!~*a-zA-Z0-9;/?:@&=+$,%#-]+)?/?");
	if( link )
	{
	    var linkstr = link[0];
	    var regexp = new RegExp( linkstr.replaceAll("?","\\?")  , "gi" );
	    link = '<a href="' + link[0] + '">' + link[0].split("").splice(0,20).join("") + '..</a>';
	    text =  text.replace( regexp , link ) ;
	}
	
	this.user = obj.user;

	this.li = $("<li/>");
	this.li.html( text + "<br /><span class='date'>" + this.created_at + '</span>'  );
    },

    "Client" : function(obj)
    {
	var _user_id = obj.user_id;
	var _callback_name = obj.callback_name;
	var _timeline = obj.timeline;
	var _request_url = JSTwitter.USER_TIMELINE + _user_id + ".json";
	var _status = JSTwitter.ClientStatus.INITIALIZED;
	var _timer = undefined;
	var _timer_sec = obj.timer_sec ? obj.timer_sec : 30000;
	var _loaded_tweets = [];
	var _update_tweets = [];
	var _loaded_tweets_index = [];
	var _complete_callback = undefined;

	var _change_status = function( status )
	{
	    _status = status;
	    _timeline.change_status( _status );
	}

	var _read = function(data)
	{
	    _update_tweets = [];
	    for( var i = 0 ; i < data.length ; i ++)
	    {
		if( _loaded_tweets_index.indexOf(data[i].id) < 0 )
		{
		    _loaded_tweets_index.push( data[i].id );
		    var tweet = new JSTwitter.Tweet(data[i]);
		    _loaded_tweets.push( tweet );
		    _update_tweets.unshift( tweet );
		}
	    };
	}


	var _connect = function()
	{
	    if( _status == JSTwitter.ClientStatus.CONNECTION ||
		_status == JSTwitter.ClientStatus.TIMELINE_DISPLAYED ) {

		_change_status( JSTwitter.ClientStatus.CONNECTING );

		$.ajax({ type : "GET" , url :  _request_url , dataType : "jsonp" , jsonp : 'callback' , cache : false ,
			 complete: function()
			 {
			     
			     _change_status( JSTwitter.ClientStatus.COMPLETE );
			     _timeline.refresh({ data :  _update_tweets , 
						      callback : function(){ _change_status( JSTwitter.ClientStatus.TIMELINE_DISPLAYED) }  });
			 },
			 success : function(res)
			 {
			     _read(res);
			     _change_status( JSTwitter.ClientStatus.SUCCESS );
			 },
			 error: function()
			 {
			     _change_status( JSTwitter.ClientStatus.AJAX_ERROR );
			 }
		       }
		      );
	    }
	}

	this.connection = function()
	{

	    _change_status( JSTwitter.ClientStatus.CREATE_LOOP );
	    _timer = setInterval( _connect , _timer_sec );
	    _change_status( JSTwitter.ClientStatus.CONNECTION );

	    _connect();
	}

	this.get_status = function(){ return _status }

    }

}

if(!Array.indexOf){
    Array.prototype.indexOf = function(object){
	for(var i = 0; i < this.length; i++){
	    if(this[i] == object){ 
		return i;
	    }
	}
	return -1;
    }
}


String.prototype.replaceAll = function (org, dest){
  return this.split(org).join(dest);
}


})();


