(function($) {
	
	$.fn.ahah = function() {
		
		__debug = function( a ) { ( window.console && window.console.log && $.fn.ahah().defaults.debug ) ? console.log( a ) : ( a ) ; }
		
		__ahah = {
			namespace : 'ahah',
			page : 1,
			limit : 5,
			offset : 0
		}
	
		this.defaults = {
			debug: true,
			/* http://vimeo.com/api/docs/simple-api */
			vimeo : {
				namespace : 'ahah-vimeo',
				limit: 20,
				offset: __ahah.offset,
				page: __ahah.page,
				width: 400,
				height: 230,
				showTitle : true,
				showByLine : true,
				showPortrait : true,
				fullscreen : true
			},
			/* http://apiwiki.twitter.com/Twitter-Search-API-Method%3A-search */
			twitter : {
				namespace : 'ahah-twitter',
				limit: __ahah.limit,
				offset: __ahah.offset,
				page: __ahah.page,
				lang: 'en',
				max_id : null,
				rpp : 15,
				since: null,
				since_id : null,
				geocode : null,
				show_user : true,
				until : null,
				result_type : 'mixed',
				at : true,
				link : true,
				hashtag : true
			},
			/* http://www.flickr.com/services/api/ */
			flickr : {
				extras : 'description, license,date_upload,date_taken,owner_name,icon_server,original_format,last_update,geo,tags,machine_tags,o_dims,views,media,path_alias,url_sq,url_t,url_s,url_m,url_o',
				page: __ahah.page,
				per_page: 8,
				key : null
			},
			/* http://code.google.com/intl/it-IT/apis/picasaweb/docs/2.0/reference.html */
			picasa : {
				visibility : 'visible', // all|private|public|visible
				projection : 'api'      // api|base
			},
			lastfm : {
				
			},
			/* http://code.google.com/intl/it-IT/apis/youtube/2.0/developers_guide_jsonc.html */
			youtube : {
				
			},
			/* http://www.tumblr.com/docs/en/api */
			tumblr : {
				
			},
			/* http://status.net/wiki/TwitterCompatibleAPI */
			identica : {
				
			},
			/* http://code.google.com/intl/it-IT/apis/ajaxfeeds/documentation/#Introduction */
			feed : {
				apiUrl : 'http://www.google.com/jsapi',
				limit : 3
			}
		}
		
		/*if ( document.location.hostname == '' || document.location.hostname == 'localhost' || document.location.protocol == 'file:' ) {
			try {
				// firefox!
				netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
			} catch (error){}
		}*/
		
		/* vimeo */
		this.vimeo = function( o  , callback ) {
			var $this = $(this);
			var d = $.extend( true , $.fn.ahah().defaults.vimeo , o ) ;
			var params = {} ;
			params.callback = '?' ;
			params.page = d.page ;
			var request = o.request ;
			var r = 'videos' ;
			if( o.username ) {
				section = o.username ;
				request = ( request ? request : r );
			} else if( o.videoId ) {
				section = 'video' ;
				request = o.videoId ;
			} else if( o.groupId ) {
				section = 'group/' + o.groupId ;
				request = ( request ? request : r );
			} else if( o.channelId ) {
				section = 'channel/' + o.channelId ;
				request = ( request ? request : r );
			} else if( o.albumId ) {
				section = 'album/' + o.albumId ;
				request = ( request ? request : r );
			}
			var url = 'http://vimeo.com/api/v2/'+section +'/' +request+'.json';
			__proxy( url , params , function(data) {
				var original = data ;
				if( data.length > d.limit ) {
					data = data.slice( d.offset , d.limit + 1 );	
				}
				for( i in data ) {
					data[i].embed = function() { return __embedVimeo( this.id , d );  }
				}
				$this.data( d.namespace , data );
				( typeof callback == 'function' ) ? callback( $this , data ) : __vimeo( $this , data , d ) ;
			} )
			return $this;
		}
		
		__vimeo = function( $target , data , options ) {
			
			var tag = $target.get(0).tagName.toLowerCase();
			$target.empty();
			if( tag == 'ul' ) {
				$target.addClass( options.namespace );
			} else if( tag == 'div' || tag == 'p' || tag == 'td' || tag == 'li' ) {
				$target.append('<ul class="'+options.namespace+'">');
				$target = $target.find('ul.'+options.namespace);
			}
			$(data).each(function(i) {
				var t = data[i] ;
				$target.append('<li><a href="'+t.url+'" title="'+t.title+'"><img src="'+t.thumbnail_small+'" alt="'+t.title+'" /></a></li>');
			});
		
		}
		
		/* twitter */
		this.twitter = function( o , callback ) {
			var $this = $(this);
			var defaults = $.extend( true , $.fn.ahah().defaults.twitter , o ) ;
			var params = {} ;
			if( o.username ) {
				params.count = defaults.limit ;
				params.callback = '?'
				var url = 'http://twitter.com/status/user_timeline/'+o.username+'.json' ;
			} else {
				if( o.q ) {
					request = o.q ;
				} else if( o.from ) {
					request = 'from:' + o.from ;
				} else if( o.to ) {
					request = 'to:' + o.to ;
				} else if( o.mention ) {
					request = '@' + o.mention ;
				} else if( o.hashtag ) {
					request = '#' + o.hashtag ;	
				} else if( o.source ) {
					request = 'source:' + o.source ;	
				}
				var params = {}
				if( o.since ) {
					params.since = o.since;
				}
				params.callback = '?' ;
				params.rpp = 15 ;
				params.q = escape( request ) ;
				var url = 'http://search.twitter.com/search.json';
			}
			__proxy( url , params , function(data) {
				$this.data( defaults.namespace , data );
				( typeof callback == 'function' ) ? callback( $this , data ) : __twitter( $this , data , defaults ) ;
			});
			return $;
		}
		
		__twitter = function( $target , data , options ) {
			
			var tag = $target.get(0).tagName.toLowerCase();
			$target.empty();
			if( tag == 'ul' ) {
				$target.addClass( options.namespace );
			} else if( tag == 'div' || tag == 'p' || tag == 'td' || tag == 'li' ) {
				$target.append('<ul class="'+options.namespace+'">');
				$target = $target.find('ul.'+options.namespace);
			}
			$(data).each(function(i) {
				var t = data[i] ;
				$target.append('<li>'+__tweetify( t.text , options.at , options.link , options.hashtag )+'</li>');
			});
		
		}
		
		this.flickr = function( o , callback ) {
			var $this = $(this);
			var defaults = $.extend( true , $.fn.ahah().defaults.flickr , o ) ;
			var params = {} ;
			if( defaults.key != null ) {
				params.api_key = defaults.key ;
				params.format = 'json' ;
				params.extras = defaults.extras ;
				params.jsoncallback = '?' ;
				if( defaults.photosetId ) {
					params.photoset_id = defaults.photosetId ;
					params.method = 'flickr.photosets.getPhotos' ;
				} else if( defaults.groupId ) {
					params.group_id = defaults.groupId ;
					params.method = 'flickr.groups.pools.getPhotos';
				} else if( defaults.userId ) {
					params.user_id = defaults.userId;
					params.method = 'flickr.people.getPublicPhotos';
				}
				var url = 'http://api.flickr.com/services/rest/' ;
				__proxy( url , params , function(data) {
					$this.data( defaults.namespace , data );
					( typeof callback == 'function' ) ? callback( $this , data ) : __flickr( $this , data , defaults ) ;
				})
			}
			return $;
		}
		
		__flickr = function( $target , data , options ) {
			
			var tag = $target.get(0).tagName.toLowerCase();
			$target.empty();
			if( tag == 'ul' ) {
				$target.addClass( options.namespace );
			} else if( tag == 'div' || tag == 'p' || tag == 'td' || tag == 'li' ) {
				$target.append('<ul class="'+options.namespace+'">');
				$target = $target.find('ul.'+options.namespace);
			}
			var images = [] ;
			if( data.photoset ) {
				images = data.photoset.photo;
			}
			$(images).each(function(i) {
				var t = images[i] ;
				$target.append('<li><a href="http://www.flickr.com/photos/'+t.pathalias+'/'+t.id+'" title="'+t.title+'"><img src="'+t.url_sq+'" alt="'+t.title+'" /></li>');
			});
		
		}
		
		this.picasa = function( o , callback ) {
			var $this = $(this);
			var defaults = $.extend( true , $.fn.ahah().defaults.picasa , o.defaults ) ;
			var params = {} ;
			params.alt = 'json-in-script' ;
			params.kind = o.kind ;
			params.callback = '?' ;
			// thumbsize : 32, 48, 64, 72, 104, 144, 150, 160
			params.thumbsize = o.thumbsize ;
			var path = '' ;
			if( o.user ) {
				path += '/user/' + o.user ;
			}
			if( o.albumId ) {
				path += '/albumid/' + o.albumId ;
			} else if( o.album ) {
				path += '/album/' + o.album ;
			}
			url = 'http://picasaweb.google.com/data/feed/' + defaults.projection + path ;
			__proxy( url , params , function( data ) {
				$this.data( __ahah.namespace , data );
				( typeof callback == 'function' ) ? callback( $this , data ) : __picasa( $this , data , defaults ) ;
			});
			return $;
		}
		
		__picasa = function( $target , data , options ) {
			
			var tag = $target.get(0).tagName.toLowerCase();
			$target.empty();
			if( tag == 'ul' ) {
				$target.addClass( options.namespace );
			} else if( tag == 'div' || tag == 'p' || tag == 'td' || tag == 'li' ) {
				$target.append('<ul class="'+options.namespace+'">');
				$target = $target.find('ul.'+options.namespace);
			}
			var images = data.feed.entry ;
			$(images).each(function(i) {
				var t = images[i] ;
				$target.append('<li><a href="'+t.link[1].href+'" title="'+t.title.$t+'"><img src="'+t.media$group.media$thumbnail[0].url+'" alt="'+t.title.$t+'" /></a></li>');
			});
		
		}
		
		this.lastfm = function( o, callback ) {
			var $this = $(this);
			var defaults = $.extend( true , $.fn.ahah().defaults.lastfm , o ) ;
			var params = {} ;
			if( o.key ) {
				params.method = 'user.getartisttracks' ;
				params.user = o.username ;
				params.api_key = o.key ;
				params.artist = 'burzum' ;
				params.format = 'json';
				params.callback = '?';
				url = 'http://ws.audioscrobbler.com/2.0/' ;
				__proxy( url , params , function(data) {
					$this.data( __ahah.namespace , data );
					( typeof callback == 'function' ) ? callback( $this , data ) : __lastfm( $this , data , defaults ) ;
				});
			}
			return $this;
		}
		
		__lastfm = function( $target , data , options ) {
			
			var tag = $target.get(0).tagName.toLowerCase();
			$target.empty();
			if( tag == 'ul' ) {
				$target.addClass( options.namespace );
			} else if( tag == 'div' || tag == 'p' || tag == 'td' || tag == 'li' ) {
				$target.append('<ul class="'+options.namespace+'">');
				$target = $target.find('ul.'+options.namespace);
			}
			var tracks = [] ;
			if( data.artisttracks.track ) {
				tracks = data.artisttracks.track ;
			}
			$(tracks).each(function(i) {
				var t = tracks[i] ;
				$target.append('<li><a href="'+t.url+'" title="'+t.name+'"><img src="'+t.image[1]['#text']+'" alt="'+t.name+'" /></a></li>');
			});
		
		}
		
		this.youtube = function( o, callback ) {
			var $this = $(this);
			var defaults = $.extend( true , $.fn.ahah().defaults.youtube , o ) ;
			var params = {} ;
			params.v = 2 ;
			params.alt = 'jsonc' ;
			params.callback = '?' ;
			params.q = o.q ;
			url = 'http://gdata.youtube.com/feeds/api/videos' ;
			__proxy( url , params , function(data) {
				$this.data( __ahah.namespace , data );
				( typeof callback == 'function' ) ? callback( $this , data ) : __youtube( $this , data , defaults ) ;
			});
			return $this;
		}
		
		__youtube = function( $target , data , options ) {
			
			$target.empty();
			$target = __target( $target , options ) ;
			var videos = [] ;
			if( data.data.items ) {
				videos = data.data.items ;
			}
			$(videos).each(function(i) {
				var t = videos[i] ;
				$target.append('<li><a href="'+t.player['default']+'" title="'+t.title+'"><img src="'+t.thumbnail.sqDefault+'" alt="'+t.title+'" /></a></li>');
			});
		
		}
		
		this.tumblr = function( o , callback ) {
			var $this = $(this);
			var defaults = $.extend( true , $.fn.ahah().defaults.tumblr , o.defaults ) ;
			var params = {} ;
			params.callback = '?' ;
			if( o.username ) {
				url = 'http://'+o.username+'.tumblr.com/api/read/json' ;
				__proxy( url , params , function( data ) {
					$this.data( __ahah.namespace , data );
					( typeof callback == 'function' ) ? callback( $this , data ) : __tumblr( $this , data , defaults ) ;
				})
			}
			return $this;
		}
		
		__tumblr = function( $target , data , options ) {
			
			var tag = $target.get(0).tagName.toLowerCase();
			$target.empty();
			if( tag == 'ul' ) {
				$target.addClass( options.namespace );
			} else if( tag == 'div' || tag == 'p' || tag == 'td' || tag == 'li' ) {
				$target.append('<ul class="'+options.namespace+'">');
				$target = $target.find('ul.'+options.namespace);
			}
			/*$(videos).each(function(i) {
				var t = videos[i] ;
				$target.append('<li><a href="'+t.player.default+'" title="'+t.title+'"><img src="'+t.thumbnail.sqDefault+'" alt="'+t.title+'" /></a></li>');
			});
		*/
		}

		this.identica = function( o , callback ) {
			var $this = $(this);
			var defaults = $.extend( true , $.fn.ahah().defaults.twitter , o.defaults ) ;
			if( o.username ) {
				url = 'http://identi.ca/api/statuses/user_timeline/'+o.username+'.json?count=' + defaults.limit + '&callback=?' ;
			} else {

			}
			__proxy( url , null , function(data) {
				$this.data( __ahah.namespace , data );
				( typeof callback == 'function' ) ? callback( $this , data ) : __identica( $this , data , defaults ) ;
			});
			return $this;
		}
		
		__identica = function( $target , data , options ) {
			
			var tag = $target.get(0).tagName.toLowerCase();
			$target.empty();
			if( tag == 'ul' ) {
				$target.addClass( options.namespace );
			} else if( tag == 'div' || tag == 'p' || tag == 'td' || tag == 'li' ) {
				$target.append('<ul class="'+options.namespace+'">');
				$target = $target.find('ul.'+options.namespace);
			}
			$(data).each(function(i) {
				var t = data[i] ;
				$target.append('<li>'+t['statusnet:html']+'</li>');
			});
		}
		
		this.feed = function( o , callback ) {
			if( !window.google || !google.feeds ) {
				alert('You must include Google API library!');
			} else {
				var $this = $(this);
				var defaults = $.extend( true , $.fn.ahah().defaults.feed , o ) ;
				__debug(defaults);
				var now = new Date();
				if( defaults.url.indexOf('?') == -1 ) {
					defaults.url = defaults.url + '_____=' + now.getTime();
				} else {
					defaults.url = defaults.url + '&_____=' + now.getTime();
				}
				var feed = new google.feeds.Feed(defaults.url);
				feed.setNumEntries(defaults.limit);
				feed.load(function(result) {
					if (!result.error) {
						var e = result.feed.entries ;
						$this.data( defaults.namespace , result );
						( typeof callback == 'function' ) ? callback( $this , data ) : __feed( $this , result , defaults ) ;
				  	} else {
					  
				  	}
				  	__debug(result);
				});
			}
		}
		
		__feed = function( $target , data , options ) {
			$target.empty();
			$target = __target( $target , options ) ;
			$(data.feed.entries).each(function(i) {
				var t = data.feed.entries[i] ;
				__debug(t);
				var p = new Date(t.publishedDate);
				$target.append('<li><a href="'+t.link+'" title="'+t.title+'">'+t.title+'</a></li>');
			});
		}
		
		__target = function( $target , options ) {
			var tag = $target.get(0).tagName.toLowerCase();
			if( tag == 'ul' ) {
				$target.addClass( options.namespace );
			} else if( tag == 'div' || tag == 'p' || tag == 'td' || tag == 'li' ) {
				$target.append('<ul class="'+options.namespace+'">');
				$target = $target.find('ul.'+options.namespace);
			}
			return $target;
		}
		
		__at = function( t ) { return t.replace( /@([A-Za-z0-9_]+)/gi , '<a href="http://twitter.com/$1">@$1</a>'); }
		
		__link = function( t ) {
			/* http://snippets.dzone.com/posts/show/452 */
			return t.replace(/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ , '<a href="$1://$2$3">$1://$2$3</a>' );
		}
		
		__hashtag = function( t ) { return t.replace( /#([A-Za-z0-9_-]+)/gi , ' <a href="http://twitter.com/search?q=%22$1%22">#$1</a>'); }
		
		__tweetify = function( text , at , link , hashtag ) {
			text = ( link ? __link( text ) : text );	
			text = ( at ? __at( text ) : text );	
			text = ( hashtag ? __hashtag( text ) : text );	
			return text ;
		}
		
		__serialize = function( params ) {
			var p = [] ;
			for(i in params ) {
				p.push( i + '=' + params[i] ) ;
			}
			return p.join('&') ;
			//return $(params).serialize(); 
		}
		
		__proxy = function( url , params , callback ) {
			var url = ( params != null ? url + '?' + __serialize( params ) : url ) ;
			__debug(url);
			$.getJSON( url , function( data ) { if($.fn.ahah().defaults.debug) { /*__debug( data );*/ } callback( data ) } );
		}
				
		__embedVimeo = function( id , options ) {
			var src = 'http://vimeo.com/moogaloop.swf?clip_id='+id+'&amp;server=vimeo.com&amp;show_title='+ (options.showTitle ? 1:0 ) +'&amp;show_byline='+ (options.showByLine ? 1:0 ) +'&amp;show_portrait='+ (options.showPortrait ? 1:0 ) +'&amp;fullscreen='+ (options.fullscreen ? 1:0 );
			var d = ' width="'+options.width+'" height="'+options.height+'" ';
			return '<object '+d+'>' + (options.fullscreen ? '<param name="allowfullscreen" value="true" />' : '' ) +'<param name="allowscriptaccess" value="always" /><param name="movie" value="'+src+'" /><embed src="'+src+'" type="application/x-shockwave-flash" ' + (options.fullscreen ? 'allowfullscreen="true"' : '' ) +' allowscriptaccess="always" '+d+'></embed></object>';
		}
		
		return this ;
		
	}
	
})(jQuery);
