/**
 * TwitterSearch
 * A convenient connection manager for interacting with the Twitter Search API.
 * 
 * REQUIRES: jQuery 1.3.2
 * REQUIRES: jQuery JSONP 1.1.0
 * REQUIRES: CanoeUtils 1.0    
 * 
 * @author      Robert Arkwright <robert.arkwright@canoe.ca>
 * @since 		December 10th 2009
 * @version		1.0
 * 
 *  
 * @param	object	options		An object containing set-up options/configuration parameters. Object parameters include:
 * 								autoAbort		: (bool) When true, polling the Twitter API for fresh tweets will cease after several fruitless responses. Default is true.
 *								error			: (function) A callback function to be executed in the event of an error when connecting to the Twitter API.
 *								lang			: (string) (optional) An ISO 639-1 language code. Only tweets matching this language will be displayed. Default is 'en'.
 *								minQueueSize	: (int) (optional) The minimum number of tweets to keep cached in case of a Twitter API failure. Default is 300.
 *								query			: (string) The query search terms to be matched by the Twitter API.
 *								success			: (function) A callback function to be executed every time an update is successfully received from the Twitter API.
 *								updateSpeed		: (int) The frequency at which the Twitter API is polled for fresh tweets. In milliseconds. Default is 60000.
 */
function TwitterSearch(options){this.API_URL="http://tw-proxy.canoe.ca/search.json?";this.BATCH_SIZE=100;this.MAX_FAILED_ATTEMPTS=3;this.autoUpdateInterval=null;this.destroyed=false;this.failedAttempts=0;this.firstResponseReceived=false;this.maxID=0;this.nextTweet=0;this.options={};this.tweets=[];this.options=options;this.validateOptions();if(this.options.updateSpeed>0){this.autoUpdateInterval=setInterval(CanoeUtils.scope(this,this.autoUpdate),this.options.updateSpeed)}this.update()}TwitterSearch.prototype.apiErrorCallback=function(xOptions,textStatus){this.registeredCallback("error")};TwitterSearch.prototype.apiSuccessCallback=function(data,textStatus){if(!this.destroyed){if(data.results!=undefined){if(data.results.length===0){this.failedAttempts++;if(this.failedAttempts>=this.MAX_FAILED_ATTEMPTS){clearInterval(this.autoUpdateInterval)}if(this.firstResponseReceived===false){this.registeredCallback("error");this.destroy()}}else{this.firstResponseReceived=true;this.failedAttempts=0;for(var i=data.results.length-1;i>=0;i--){this.tweets.push(data.results[i])}this.maxID=data["max_id"];this.registeredCallback("success")}}else{registeredCallback("error");this.destroy()}}};TwitterSearch.prototype.autoUpdate=function(){if(this.tweets.length-this.nextTweet<this.options.minQueueSize){this.update()}};TwitterSearch.prototype.destroy=function(){clearInterval(this.autoUpdateInterval);this.destroyed=true};TwitterSearch.prototype.getAllTweets=function(){return this.tweets};TwitterSearch.prototype.getTweet=function(){if(this.nextTweet>=this.tweets.length){return false}else{this.nextTweet++;return this.tweets[this.nextTweet-1]}};TwitterSearch.prototype.registeredCallback=function(type){var func=null;switch(type){case"error":func=this.options.error;break;case"success":func=this.options.success;break}if(func!=undefined&&func!=null){if(typeof func==="function"){func()}}};TwitterSearch.prototype.update=function(){var request={};var sinceIDParam="";if(this.maxID>0){sinceIDParam="since_id="+this.maxID+"&"}request.url=this.API_URL+sinceIDParam+"q="+this.options.query+"&rpp="+this.BATCH_SIZE+"&lang="+this.options.lang+"&callback=?";request.error=CanoeUtils.scope(this,this.apiErrorCallback);request.success=CanoeUtils.scope(this,this.apiSuccessCallback);jQuery.jsonp(request)};TwitterSearch.prototype.validateOptions=function(){if(this.options.query!=null){this.options.query=encodeURIComponent(this.options.query)}if(typeof this.options.autoAbort!=="boolean"){this.options.autoAbort=true}if(typeof this.options.updateSpeed!=="number"||this.options.updateSpeed<0){this.options.updateSpeed=60000}if(typeof this.options.minQueueSize!=="number"||this.options.minQueueSize<0){this.options.minQueueSize=300}if(typeof this.options.lang!=="string"||this.options.lang===""){this.options.lang="en"}};
