(function($) {
 
	$.fn.twitter = function(options){
		var config = {
			username: ["username"],	// [string | array] toon alleen tweets van deze user(s) max:7; maak voor >7 in Twitter een list aan en gebruik listname
			listname: null,				// [string]		naam van Twitterlist horend bij (1e) username; slechts 1 list mogelijk. om bijv list http://twitter.com/humortv/cabaretiers te tonen: username: humortv; listname: cabaretiers. Als listname is gedefinieerd, wordt van user alleen die list getoond.
			searchterm: null,				// [string | array] can be an array (7 items max!), just do ["searchterm1","searchterm2","etc"]
			hashtag: null,  // string hashtag zonder #
			user_header: true,			// [boolean]	toont header met avatar + username; bij meerdere usernames worden alleen avatars getoond
			refresh_rate: 60,			// [integer] 	refresh rate in secondes; houd bij instellen rekening met Twitter's rate-limiting
			avatar_size: 48,			// [integer]	height and width in px of avatar (48px max - dat is img size)
			header_avatar_size: 32,			// [integer]	height and width in px of avatar in user_header (48px max - dat is img size)
			count: 4,					// [integer]	how many tweets to display?
			intro_text: null,			// [string]		do you want text BEFORE your tweets?
			outro_text: null,			// [string]		text to show after your tweets
			loading_text: "Tweets laden...",	// [string]		optional loading text, displayed while tweets load
			since_id: null				// [integer] 	toon alleen tweets nieuwer dan since_id (wordt automatisch gevuld bij refresh)
		};
		if(options) $.extend(config, options);
		
		var set = this;//current set of selected objects; define here to pass to timeout function

		$.fn.extend({
			linkUrl: function() {
				var returning = [];
				var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
				this.each(function() {
					returning.push(this.replace(regexp,"<a href=\"$1\">$1</a>"))
				});
				return $(returning);
			},
			linkUser: function() {
				var returning = [];
				var regexp = /[\@]+([A-Za-z0-9-_]+)/gi;
				this.each(function() {
					returning.push(this.replace(regexp,"<a href=\"http://twitter.com/$1\" class='tweet_user'>@$1</a>"))
				});
				return $(returning);
			},
			linkHash: function() {
				var returning = [];
				var regexp = / [\#]+([A-Za-z0-9-_]+)/gi;
				this.each(function() {
					returning.push(this.replace(regexp, ' <a href="http://search.twitter.com/search?q=&tag=$1&lang=all&from='+config.username.join("%2BOR%2B")+'" class="tweet_searchterm">#$1</a>'))
				});
				return $(returning);
			}
		});

		function relative_time(time_value) {
			var parsed_date = Date.parse(time_value);
			var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
			var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
			if(delta < 60) {
				return 'minder dan een minuut geleden';
			} else if(delta < 120) {
				return 'ongeveer een minuut geleden';
			} else if(delta < (45*60)) {
				return (parseInt(delta / 60)).toString() + ' minuten geleden';
			} else if(delta < (90*60)) {
				return 'ongeveer een uur geleden';
			} else if(delta < (24*60*60)) {
				return 'ongeveer ' + (parseInt(delta / 3600)).toString() + ' uur geleden';
			} else if(delta < (48*60*60)) {
				return '1 dag geleden';
			} else {
				return (parseInt(delta / 86400)).toString() + ' dagen geleden';
			}
		}
		
		function getTweetInfo(item) {
			//bundelt alle tweet info in 1 object (api's geven elementen in andere structuur terug)
			var tweetInfo;//object voor tweetinfo
			if (config.listname && config.listname != "") {
				//list api gebruikt
				tweetInfo = {
					id: item.id,
					from_user: item.user.name,
					profile_image_url: item.user.profile_image_url,
					created_at: item.created_at,
					text: item.text
				};
			} else {
				//search api gebruikt
				tweetInfo = {
					id: item.id,
					from_user: item.from_user,
					profile_image_url: item.profile_image_url,
					created_at: item.created_at,
					text: item.text
				};
			}
			return tweetInfo;
		}
		
		function refresh(set) {
			$(set).each(function(i){
				getTweets($(this), i);
			});
		}
		
		function addUserHeader(list) {
			//voeg user_header toe before list
			var users = toSearchableArray(config.username);
			if (users.length > 0) {
				users.sort();
				//add div
				var user_header = $('<div class="user_header"></div>');
				$(list).before(user_header);
				for (var i=0; i<users.length; i++) {
					//de api call voor meerdere users tegelijk is beperkt tot ingelogde users. we moeten dus per user een api call doen
					var url = "http://api.twitter.com/1/users/show.json?screen_name="+users[i]+"&callback=?";
					//*
					$.getJSON(url, function(data) {
						var username = data.screen_name;
						var image_url = data.profile_image_url;
						var html = createAvatarHtml(username, image_url, config.header_avatar_size);
						if (config.listname) {
							var l = username+'/'+config.listname;
							html += '<a href="http://twitter.com/'+l+'" title="Bekijk list '+l+'">'+l+'</a>';
						} else {
							if (users.length == 1) {//dan ook username erbij
								html += createAuthorHtml(username);
							}
						}
						$(user_header).append(html);
					});
					//*/
					if (config.listname) break;//stop na 1e username als er list is
				}
			}
		}
		
		function createAvatarHtml(username, image_url, size) {
			var avatarHtml = '<div class="photo"><a class="tweet_avatar" href="http://twitter.com/'+ username+'" title="bekijk '+username+'\'s tweets">';
			avatarHtml += '<img src="'+image_url+'" height="'+size+'" width="'+size+'" alt="'+username+'\'s avatar" border="0"/>';
			avatarHtml += '</a></div>';
			return avatarHtml;
		}
		
		function createAuthorHtml(username) {
			var usernameHtml = '<a class="tweet_author" href="http://twitter.com/'+username+'" title="bekijk '+username+'\'s tweets">';
			usernameHtml += username;
			usernameHtml += '</a>';
			return usernameHtml;
		}
		
		function getTweets(currObj, i) {
			//zet tweets in list
			var list;
			var l = $("ul.tweet_list");
			if (l.length == 0) {
				//dan 1e iteratie; ul etc toevoegen
				
				list = $('<ul class="tweet_list">').appendTo(currObj);
        list.before('<h2 class="normalHead">Twitter</h2>');
				if (config.intro_text != null && config.intro_text != "") {
					list.before('<p class="tweet_intro">'+config.intro_text+'</p>');
				}
				if (config.loading_text) {
					$(currObj).append('<p class="loading">'+config.loading_text+'</p>');
				}
				if (config.outro_text != null && config.outro_text != "") {
					$(currObj).append('<p class="tweet_outro">'+config.outro_text+'</p>');
				}
				
				//evt user_header toevoegen
				if (config.user_header) {
					addUserHeader(list);
				}
				
			} else {
				list = l[0];
				list = $(list);//wrap in jQuery object to be able to use stuff like append
			}
			
			// call Twitter api and process results
			var jsonUrl = url;
			/* dit deel gebruiken als we tweets er 1 voor 1 in willen laten lopen
			if (config.since_id) {
				jsonUrl += "&since_id="+config.since_id;
			}
			*/
			//*
			$.getJSON(jsonUrl, function(data){
				if (config.loading_text) {
					$(".loading", currObj).each(function(){$(this).remove();});
				}
				list.html("");
				
				
				//get the array with results (depending on api call) and loop through them
				var results;
				if (config.listname && config.listname != "") {
					results = data;
				} else {
					results = data.results;
				}
				$.each(results, function(i,item){
					//put relevant info in new object, independent of returned json structure
					var tItem = getTweetInfo(item);
					if (i == 0) {
						config.since_id = tItem.id;//store id of newest tweet in config
					}
					
					//create avatar html
					var avatar = '';
					if (config.avatar_size) {
						avatar = createAvatarHtml(tItem.from_user, tItem.profile_image_url, config.avatar_size);
					}
					var date = '<span class="tweet_date">'+relative_time(tItem.created_at)+'</span>';
					var username = tItem.from_user;
					var user = createAuthorHtml(username);
					var text = '<span class="tweet_text">';
						text += $([tItem.text]).linkUrl().linkUser().linkHash()[0];
						text += '</span>';
					
					//nu alles in tweet samenvoegen
					var tweet = avatar;
					tweet += '<div class="info"><span class="tweet_text_box">';
					if (config.username == "" || config.username.length > 1 || config.listname) {
						tweet += user;
					}
					tweet += text + date;
					tweet += '</span></div>';
					
					list.append('<li>' + tweet + '</li>');
				});//each results
				list.children('li:first').addClass('tweet_first');
				list.children('li:odd').addClass('tweet_even');
				list.children('li:even').addClass('tweet_odd');
			
				if (i == 0 && config.refresh_rate && config.refresh_rate > 0) {
					//check for i==0 to use setInterval only once each time
					setTimeout(function(){refresh(set);}, 1000*config.refresh_rate);
				}
			});//json callback
			//*/
		}
		
		function toSearchableArray(obj) {
			//maakt van obj array als het dat nog niet is; beperkt arrays tot 7 elementen (max voor zoek)
			if(typeof(obj) == "string"){
				obj = [obj];
			} else {
				if ($.isArray(obj) && obj.length > 7) {
					obj = obj.splice(0,7);
				}
			}
			return obj;
		}
		
		//api call definieren
		//username en searchterm omzetten zodat we altijd array hebben
		config.username = toSearchableArray(config.username);
		config.searchterm = toSearchableArray(config.searchterm);
		
		if (config.listname && config.listname != "") {
			var url = "http://api.twitter.com/1/"+config.username[0]+"/lists/"+config.listname+"/statuses.json?per_page="+config.count+"&callback=?";
		} else {
			//maak query als http://search.twitter.com/search.json?q=+hij+OR+studio+from%3Agiel3fm+OR+from%3Apauldeleeuw
			var query = 'q=';
			if(config.searchterm && config.searchterm != "") {
				query += '+'+config.searchterm.join("+OR+");
			}
      if(config.hashtag && config.hashtag != "") {
        query += '&tag='+config.hashtag;
      }
			if (config.username && config.username != "") {
				query += "+from%3A"+config.username.join("+from%3A");
			}
			
			var url = 'http://search.twitter.com/search.json?'+query+'&rpp='+config.count+'&callback=?';
		}
		
		//now loop through all matched elements
		return this.each(function(i){
			var currObj = this;
			getTweets(currObj, i);
		});//return this.each
	};
})(jQuery);
