Retweet = {};
Retweet.Button = Class.create({
	initialize: function(element, options){
		if(!window.BitlyClient){
			if(console && console.error){
				console.error('this widget needs the bitly javascript client!');
			}
		}
	
		this.element = $(element);
		this.options = Object.extend({
			showStats: true,
			getShortenUrl: function(){ return window.location.href;},
			updateButton: function(context, data){
				if(context.element.down('h2 a')){
					var text = context.element.down('h2 a').title;
				}else{
					var text = context.element.down('h2').innerHTML;
				}
				context.element.down('span.retweet-button').update("<a href=\"http://twitter.com/home/?status=RT+%40mangrove "+ escape(text) + ' ' + data['shortUrl'] + "\" class=\"btn-retweet\">retweet</a>");
			},			
			updateStatsInfo: function(context, data){
				if(data.clicks > 0){
					context.element.down('span.retweet-button a').update(context.element.down('span.retweet-button a').innerHTML + ' (' + data.clicks + ' clicks)');
				}
			}
		}, options || {});
		this.onReady();
	},
	shortenUrl: function(){
		BitlyClient.shorten(this.options.getShortenUrl(this), 'Retweet.CallBacks.onShortenUrl');
	},
	onReady: function(){
		/**
		 * Cache the callback functions, so that you can stop the observing
		 */
		this.callBackShortenUrl = this.onShortenUrl.bindAsEventListener(this);
		this.callBackOnStatsReceived = this.onStatsReceived.bindAsEventListener(this);
		this.waitForShortenUrl(this.callBackShortenUrl);
		if(this.options.showStats){			
			this.waitForStats(this.callBackOnStatsReceived);
		}
		
		this.shortenUrl();
	},
	waitForShortenUrl: function(callback){
		Retweet.CallbackPool.add('shorten', this.options.getShortenUrl(this), callback);
	},
	waitForStats: function(callback){
		Retweet.CallbackPool.add('stats', this.options.getShortenUrl(this), callback);
	},
	onStatsReceived: function(data){
		this.options.updateStatsInfo(this, data.results);
	},
	getStatsForUrl: function(){
		BitlyClient.stats(this.bitlyUrl, 'Retweet.CallBacks.onStats');
	},
	onShortenUrl: function(data){
		this.bitlyUrl = data.shortUrl;
		this.bitlyHash = data.hash;
		this.element.writeAttribute('id', 'b' + data.hash);
		this.options.updateButton(this, data);
		if(this.options.showStats){
			this.getStatsForUrl();
		}
	}
});

/**
 * CallbackPool, assigns callbacks to bitly responses.
 * this method replaces the old version with events because IE runs out of memory calling those events.
 * @var _pool: objects of callbacks defined with their id (longurl)
 * @var _mapping: object of bitly hashes who correspondents with the long url (needed because stats event doesn't show longurl, only bitlyhash
 */
Retweet.CallbackPool = {
	/**
	 * the pool of callbacks
	 */
	_pool: {
		shorten: {},
		stats: {}
	},
	/**
	 * used for bitly to long url mapping
	 */
	_mapping: {},
	/**
	 * adds a callback to the pool
	 * @var string method, the method for the callback (shorten or stats)
	 * @var string hash, the longurl for identifying callbacks
	 * @var function callback, the callback for the retweet button
	 */
	add: function(method, hash, callback){
		if(!this._pool[method][hash]){
			this._pool[method][hash] = callback;
		}
	},
	/**
	 * calls the callback in the pool with the provided method and id
	 * @var string method, the method for the callback (shorten or stats)
	 * @var object data, the data received from bit.ly
	 */
	call: function(method, data){
		if(method == 'shorten'){
			var id = Object.keys(data.results)[0];
			if(this._pool.shorten[id]){
				this._mapping[data.results[id].hash] = id;
				this._pool.shorten[id](data.results[id]);
			}
		}else if(method == 'stats'){
			if(this._mapping[data.results.hash]){
				this._pool.stats[this._mapping[data.results.hash]](data);
			}
		}
	}
};

/**
 * global functions for the jsonp call from bitly, the functions forward the data to the correct callback
 */
Retweet.CallBacks = {
	onShortenUrl: function(data){
		Retweet.CallbackPool.call('shorten', data);
	},
	onStats: function(data){
		Retweet.CallbackPool.call('stats', data);
	}
};

