
var MagnifyTwitterObject = Class.create({

	initialize: function(obj) {	
		this.id = obj.id;
		
		var text = obj.text;
		text = text.gsub(/http:\/\/\S+/, function(match) { return '<a href="' + match[0].strip() + '" target="_blank">' + match[0].strip() + '</a>'; });
		
		text = text.gsub(/@\w+/, function(match) { var name = match[0].sub('@',''); return '<a href="http://www.twitter.com/' + name.strip() + '" target="_blank">' + match[0].strip() + '</a>'; });
		
		this.to_user = obj.to_user;
		
		this.text = text;		
		this.img = obj.profile_image_url;		
		this.posted = this.twitterTime( new Date().getTime() - this.parseDate( obj.created_at ) );;
		this.from_user = obj.from_user;
		this.source = obj.source.unescapeHTML();
	},
	
	parseDate: function(createdOn) {
		var parts = createdOn.split(" ");
		return ( new Date( parts[2] + " " + parts[1] + ", " + parts[3] + " " + parts[4] + " GMT" ) ).getTime();
	},
	
	twitterTime: function(ms) {
		var seconds = ms/1000;
		if ( seconds < 1 )
			seconds = 1;
		
		if ( seconds < 60 ) {
			return "less than " + Math.floor(seconds) + " second" + ( seconds == 1 ? '' : 's' ) + " ago";
		} else if ( seconds < 3600 ) {
			var minutes = Math.floor(seconds/60);
			return (minutes + " minute" + ( minutes == 1 ? '' : 's' ) + " ago");
		} else if( seconds < 86400 ) {
			var hours = Math.floor(seconds/3600);
			return ("about " + hours + " hour" + ( hours == 1 ? '' : 's' ) + " ago");
		} else {
			var days = Math.floor(seconds/86400);
			return (days + " day" + ( days == 1 ? '' : 's' ) + " ago");
		}
	},
	
	format: function(formats) {			
		var entryContainer = document.createElement('div');
		entryContainer.className = 'magnify-twitter-entry';
		
		var div = document.createElement('div');
		div.id = 'magnify_twitter_container_' + this.id;
		div.className = 'magnify-twitter-container clearfix';
		entryContainer.appendChild(div);
		
		if ( formats.images ) {
			var imgSpan = document.createElement('span');
			imgSpan.className = 'magnify-twitter-image-container';
			
			var imgLink = document.createElement('a');
			imgLink.href = "http://www.twitter.com/" + this.from_user;
			imgLink.target = "_blank";
				
			var img = document.createElement('img');
			img.className = 'magnify-twitter-image';
			img.src = this.img;
			img.width = 48;
			img.height = 48;
			img.border = 0;
			
			imgLink.appendChild(img);
			imgSpan.appendChild(imgLink);		
			div.appendChild(imgSpan);
		}
			
		var text = document.createElement('span');
		text.className = 'magnify-twitter-text-container';
		text.innerHTML = '<span class="magnify-twitter-main-content"><span class="magnify-twitter-from-user"><a href="http://www.twitter.com/' + this.from_user + '">' + this.from_user + '</a>:</span> <span class="magnify-twitter-text">' + this.text + '</span></span> <span class="magnify-twitter-tag-content"><span class="magnify-twitter-posted">' + this.posted + '</span> <span class="magnify-twitter-source">from ' + this.source + '</span></span>';
		div.appendChild(text);
		
		return entryContainer;
	}
});

var MagnifyTwitterFeed = Class.create({
	initialize:  function( config ) {
		this.config = config;
		this.callback = this.config.callback;
		this.search = this.config.search.gsub(',','');
		
		this.filter = this.createFilter(this.config.addFilter, 'add');
		this.results = this.config.results,
		this.userFilter = this.createFilter(this.config.userFilter, 'user');
		
		this.speed = this.config.speed || 5;
		this.request = this.config.limit || 25;
		this.limit = this.config.limit || 25;
		
		if ( this.config.debug ) {
			var debug = document.createElement('textarea');
			debug.id = "debug" + this.config.varName;
			debug.style.width = "500px";
			debug.style.height = "200px";
			document.body.appendChild(debug);
		}
		
		this.uniqueId = 0;
		this.loadData();		
		this.setUpPoller();
	},
	
	loadData: function() {
		try {
			var container = this.getContainer(this.config.container);
			this.container = container;
			var queryString = "q=" + encodeURIComponent(this.search) + ( "&rpp=" + this.request ) + ( this.sinceId ? '&since_id=' + this.sinceId : '' );	
			
			var apiRequest = this;
			if ( document.getElementById("MagnifyDynamicScript" + this.config.varName) ) {
				this.removeScript("MagnifyDynamicScript" + this.config.varName);
			}
			this.addScript(this.createMethodURL() + "?" + queryString + "&callback=" + this.callback );
		} catch(e) {
			if ( this.poller ) {
				this.poller.stop();
			}
			this.processError(e);	
		}
	},
	
	createMethodURL: function() {	
		return "http://search.twitter.com/search.json"
	},
	
	processResponse: function(responseText) {	
		try {
			if ( !responseText ) 
				return "No results";
			
			var feedData = responseText;		
			var entries = feedData.results;		
			if ( entries && !entries.length )
				return this.debug("No results.");
				
			if ( $('mvp_tweet_error') ) 
				this.container.removeChild( $('mvp_tweet_error') );
				
			if ( feedData.error != undefined ) {
				Element.insert(this.container, { top: '<div id="mvp_tweet_error" style="padding: 10px 0px;">Contacting Twitter, one moment...</div>' });
			}
				
			if ( entries != undefined ) {
				this.entries = entries;	
				this.getContent();
			}
		} catch(e) {
			this.processError(e);
		}
	},

	getContent: function() {
		try {
			if ( !this.entries )
				throw ( new Error("No results") );

			var output = document.createElement('div');	
			output.id = "magnify_twitter_out_" + this.config.varName + "_" + this.uniqueId;
			this.uniqueId++;
			var contentItems = new Array();
			
			for ( var i=0; i < this.entries.length; i++ ) {
				var entry = this.entries[i];
				if ( i == 0 )
					this.sinceId = entry.id;
					
				var text = entry.from_user + ' ' + entry.text;
				var user = entry.from_user;
				var regex, matches, userRegex, userMatches;
				
				if ( this.filter ) {
					regex = new RegExp(this.filter, "gi");
					matches = text.match(regex);
				}
								
				if ( this.userFilter ) {
					userRegex = new RegExp(this.userFilter, "gi");
					userMatches = user.match(userRegex);
				}
				
				if ( matches )
					this.debug("matches: " + matches);
				
				if ( userMatches )
					this.debug("matches: " + userMatches);
					
				if ( !matches && !userMatches ) {
					var contentObj = new MagnifyTwitterObject(entry);
					contentItems.push(contentObj);
					var container = this.config.formatter ? this.config.formatter(contentObj, i) : contentObj.format(this.results);
					container.id = "magnify_twitter_entry_" + entry.id;
					if ( this.uniqueId > 1 ) {
						container.style.display = "none";
					}
					output.appendChild(container);
				} else {
					this.debug("dropped update: " + text);
				}
			}
			this.contentItems = contentItems;
			
			if ( !output.innerHTML && (this.uniqueId == 0) ) 
				output.innerHTML = "No results for " + this.search + "...";
			
			Element.insert(this.container, { top: output });
			this.currentOutput = output;
			if ( this.uniqueId > 1 ) {
				this.showAndPrune();
			}		
		} catch(e) {
			this.processError(e);
		}
	},
	
	setUpPoller: function() {
		try {
			var apiRequest = this;
			this.poller = new PeriodicalExecuter(function() { apiRequest.request = 1; apiRequest.loadData(); }, this.speed);			
		} catch(e) {
			this.processError(e);
		}
	},
	
	showElement: function(el) {
		Effect.Appear(el);	
	},
	
	hideElement: function(el) {
		Effect.Fade(el);	
	},
	
	showAndPrune: function() {
		try {
			var apiRequest = this;
			
			var currentOutput = $("magnify_twitter_out_" + this.config.varName + "_" + (this.uniqueId-1));
			var newTargets = currentOutput.immediateDescendants();
			
			newTargets.reverse();
			newTargets.each( function(el, index) {
				var interval = 500*index;
				setTimeout(function() { apiRequest.showElement(el); }, interval);
			});
			
			
			var removeIndex = 0;
			$$('#' + this.container.id + ' .magnify-twitter-entry').each(function(el, index) {
				if ( index >= apiRequest.limit ) {
					
					var interval = 500*removeIndex;
					setTimeout(function() { apiRequest.hideElement(el); Element.remove(el) }, interval);
					removeIndex++
				}
			});		
		} catch(e) {
			this.processError(e);
		}
	},
		
	createFilter: function(addFilter, type) {
		var regex;
		var regFilter = "(\\bdamn\s?|fart|fuck(ed|er|ing|me|s)\\b)|(\\b(hell|horny|j(ac|er)k-off|ji(sm|z(m)?))\\b)|(\\b(motha|mother)?fuck(er(s)?|in(g)?)?\\b)|(\\b(shit(ty|s)?|slut(s)?|spunk|twat)\\b)|(ass(es)?\s?hole(s)?\s?)|(\\bbitch(es|in|ing)?\s?hole(s))|(\\bblow\s?(job|jobs))|(\\bcock\s?(s|suck|sucker|sucking|sucks)\\b)|(\\bsuck(s)\\b)|(\\b(phonesex|pissoff|prick(s)?|puss(ies|y)(s)?)\\b)|(\\b(cum(s)?|cunt(s)?)\\b)";

			regex = "";
			if ( this.config.useFilter && type == 'add' ) {
				regex += regFilter;
			}
			if ( addFilter) {
				regex += ( this.config.useFilter && type == 'add' ? '|' : '' ) + '(\\b' + addFilter.join("\\b|\\b") + '\\b)';
			}
		return regex;
	},
	
	getContainer: function(id) {
		if ( !document.getElementById(id) )
			throw ( new Error("cannot locate container '" + id + "'") );
		
		return document.getElementById(id)
	},
	
	addScript: function(url) {
		try {
			var script = document.createElement('script');
			script.src = url;
			script.id = "MagnifyDynamicScript" + this.config.varName;
			document.body.appendChild(script);
		} catch(e) {
			this.processError(e);
		}
	},

	removeScript: function(id) {
		try {
			document.body.removeChild(document.getElementById(id));
		} catch(e) {
			this.processError(e);
		}
	},
	
	processError: function(e) {
		if ( e == "ContainerException" ) {
			alert("Could not load data into page.");
		} else {
			this.debug('ERROR: ' + e.message + ' ' + e.description + ' ' + e.toString());
		}
	},
	
	debug: function(message) {
		if ( $('debug' + this.config.varName) ) {
			var logText = $('debug' + this.config.varName).innerHTML
			 $('debug' + this.config.varName).innerHTML =  message + "\n\n" + logText;
		}
	}
});