if (!Array.prototype.indexOf) {
	Array.prototype.indexOf = function( v, b, s ) {
		for( var i = +b || 0, l = this.length; i < l; i++ ) {
			if( this[i]===v || s && this[i]==v ) { return i; }
		}
	 return -1;
	};
}

if (!String.prototype.trim) {
	String.prototype.trim = function() {
		var	str = this.replace(/^\s\s*/, ''), ws = /\s/, i = str.length;
		while (ws.test(str.charAt(--i))) { }
		return str.slice(0, i + 1);
	};
}

(function() {
	
	/**
	 * a HashSet.
	 */
	var HashSet = function() {
		var _backingStore = []; var self = this; this.length = 0; 
		var _counts = []; var _orderedList = null; var dirty = false;

		var updateCount = function(el) {
			var f = false;
			for (var i = 0; i < _counts.length; i++) {
				if (_counts[i][1] == el) {
					_counts[i][0] = _counts[i][0] + 1;
					f = true; break;
				}
			}
			if (!f) _counts.push([1, el]);		
		};

		this.push = function(el) {
			dirty = true;
			updateCount(el);
			if (_backingStore.indexOf(el) == -1) {
				_backingStore.push(el);		
				self.length = _backingStore.length;
			}
		};

		this.pushAll = function(list) {
			if (list != null) {
				for (var i = 0; i < list.length; i++)
					this.push(list[i]);
			}
		};

		this.getData = function() { return _backingStore; }
		this.getCount = function(el) { return _counts[el]; }
		this.getDataInOrder = function() {
			if (!dirty && _orderedList) return _orderedList;
			var s = function(a, b) {
				if (a[0] < b[0]) return 1;
				if (a[0] > b[0]) return -1;
				return 0;	
			};
			_orderedList = _counts.sort(s);
			dirty = false;
			return _orderedList;
		};
	},

	
	/**
	 * a set of Tweets, with hash sets of all found tags and user refs.
	 */
	TweetSet = function() {
		this.tags = new HashSet(); this.users = new HashSet();
		var tweets = []; var self = this;
		this.addTweet = function(tweet) {
			tweets.push(tweet);
			var users = tweet.data.text.match(TweetPlumb.userPattern);
			tweet.tags = new HashSet(); tweet.users = new HashSet();
			self.users.pushAll(users); tweet.users.pushAll(users); self.users.getDataInOrder();
			var tags = tweet.data.text.match(TweetPlumb.tagPattern);
			if (tags != null) for (var i = 0; i < tags.length;i++) tags[i] = tags[i].toLowerCase();
			self.tags.pushAll(tags); tweet.tags.pushAll(tags); self.tags.getDataInOrder();
		};
		
		this.addAll = function(data) {
			$.each(data, function(index) {
				var t = createTweet(this, index);
				self.addTweet(t);
			});
		};
		
		this.getTweets = function() { return tweets; };
		/**
		 * returns the index of the found user in the hash set of users.
		 */
		this.getUserIndex = function(username) {
			var u = self.users.getDataInOrder();
			for (var i = 0; i < u.length; i++) {
				if (u[i][1] == username) return i;
			}
			return -1;
		}
	},
	
	/**
	 * makes a Tweet.
	 */
	createTweet = function(data, index) {		
		data.index = index;
		return { data:data };
	},
	
	/**
	 * how long between automatic refreshes
	 */
	refreshInterval = null,
	
	/**
	 * for the search again functionality
	 */
	lastSearch = null, lastHandler = null,
	
	_translateAutomatically = false,
	
	/**
	 * TweetPlumb engine.  UI independent.
	 */
 	TweetPlumb = window.TweetPlumb = {
			
		urlPattern : /([Hh]ttps?:\/\/[a-zA-Z0-9;_\-\/\?=\!%\+\'\&|\.#]+)/g,
		userPattern : /(@[a-zA-Z0-9_\-]+)/g,
		tagPattern : /(#[a-zA-Z0-9_\-]+)/g,
			
		refreshInterval : 120000,
					
		/** 
		 * gets a parameter from the page.
		 */
		getPageParam : function( name )
		{
		  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
		  var regexS = "[\\?&]"+name+"=([#]?[^&#]*)";
		  var regex = new RegExp( regexS );
		  var results = regex.exec( window.location.href );
		  if( results == null )
		    return "";
		  else
		    return decodeURIComponent(results[1]);
		},
		
		/** 
		 * execute a search.
		 */
		executeSearch : function(term, handler) {			
			var _handler = function(data) {
				var tweetSet = new TweetSet();
				tweetSet.addAll(data.results);
				if (handler) {
					try { 
						lastHandler = handler;
						handler(tweetSet); 
					}
					catch(e) { 
						//todo error handler?
						//alert(e);
					}
				}
			};
	
			lastSearch = term;
			$.getJSON("http://search.twitter.com/search.json?q=" + encodeURIComponent(term) + "&callback=?", _handler);
			$("#sc")[0].src = "c.html?s=" + encodeURIComponent(term);
		},
		
		/**
		 * executes the last search.
		 */
		searchAgain : function() {
			if (lastSearch != null && lastHandler != null) TweetPlumb.executeSearch(lastSearch, lastHandler);
		},

		getLastSearch : function() {
			return lastSearch || "";
		},
		
		/**
		 * sets/unsets automatic refresh.
		 */
	    setRefreshAutomatically : function(value) {			
	    	if (value) {
		    	refreshInterval = window.setInterval(function() {
		    		try {
		    			TweetPlumb.searchAgain();
		    		} catch(e) { window.clearInterval(refreshInterval); }}
		    		, TweetPlumb.refreshInterval);
	    	}
	    	else {
	    		window.clearInterval(refreshInterval);
	    	}	    	
	    },
	    
	    setTranslateAutomatically : function(value) {
	    	_translateAutomatically = value;
	    },
	    
	    isTranslateAutomatically : function() {
	    	return _translateAutomatically;
	    }
	};
})();

// 



