jQuery.getScript("http://www.barackobama.com/js/jquery.dates.js");
var Fetcher = function(url, htmlElement)
{
	this._url         	= url;
	this._htmlElement 	= htmlElement;
	this._spinner	 	= jQuery(this._htmlElement).find('img')[0];
	
	this.postsPerPage = 5;
	this.pageLimit 	  = 10;
	
	this._EMAIL_THIS_HREF = 'http://my.barackobama.com/page/sendtofriend?referer=';
};

Fetcher.prototype.fetch = function(page)
{	
	var me = this;
	jQuery.ajax({ type: "GET",
				  url: me._urlForPage(page || 0),
				  success: function(rawData) { me._handleSuccess(rawData); }
				});
				
	this.currentPage = page || 0;
};

Fetcher.prototype._urlForPage = function(page) 
{
	return this._url + '?limit=' + this.postsPerPage + '&offset=' + (page * this.postsPerPage);
}

Fetcher.prototype._handleSuccess = function(rawData) 
{ 
	jQuery(this._htmlElement).empty();
	
	this._loadData(rawData);
	jQuery(this._htmlElement).append(this._getNavigation());

	jQuery(this._spinner).hide();
	
	window.scrollTo(0,0);
};

Fetcher.prototype._loadData = function(rawData)
{	
	var rawItems  = rawData.getElementsByTagName('item');	
	for(var i = 0; i < rawItems.length; i++)
		jQuery(this._htmlElement).append(this._getItemHTML(rawItems[i]));
		
	this.numPosts = parseFloat(new this._xml(rawData).val('ysrv:total_item_count'));
	this.numPages = Math.ceil(this.numPosts / this.postsPerPage);
};

// Returns the html element generated from the xml for a blog item
Fetcher.prototype._getItemHTML = function(rawItem)
{
	var xml       = new this._xml(rawItem);
	var blogHref  = xml.val('guid');
	var title	  = xml.val('title');
	
	// Blog title
	var item = 
	
	jQuery('<div></div>').addClass(this._CSS.itemClass).
		// <h4> title
		append(jQuery('<h4></h4>').addClass(this._CSS.titleClass).
			// <a> title link
			append(jQuery('<a></a>').attr({href: blogHref}).html(title)
		) //</h4> 
	);
	
	// Byline
	item.append(
		// <div> byline
		jQuery('<div></div>').addClass(this._CSS.bylineClass).append(
			// <span> by
			jQuery('<span></span>').addClass(this._CSS.byClass).html('by ').append(
				// <span> creator
				jQuery('<span></span>').addClass(this._CSS.feedCreator).html(xml.val('dc:creator'))
				) // </span>
			).append(
			// <span> Pub date
			jQuery('<span></span>').addClass(this._CSS.pubDateClass).html(this._getDate(xml.val('pubDate')))
		) // </div>
	);
	
	// <div> Blog text
	item.append(jQuery('<div></div>').addClass(this._CSS.descriptionClass).html(xml.val('description')));
	
	var titleEnc = encodeURIComponent(title);
	
	// Footer
	item.append(
		// <div> footer 
		jQuery('<div></div>').addClass(this._CSS.footerClass).append(
			// <div> comment line
			jQuery('<div></div>').addClass(this._CSS.commentLineClass).append(
				// <span> comment count
				jQuery('<span></span>').addClass(this._CSS.commentCountClass).append(
					// <a> comment link
					jQuery('<a></a>').text(xml.val('db:comment_count') + ' Comment(s)').attr('href', xml.val('comments'))
				) // </span>
			).append(
				// <a> Permalink
				jQuery('<a></a>').addClass(this._CSS.permalinkClass).text('Permalink').attr('href', blogHref)
			).append(
				// <a> Email this
				jQuery('<a></a>').addClass(this._CSS.emailThisClass).text('Email to a friend').attr('href', this._EMAIL_THIS_HREF + blogHref)
			)
		).append(
			// <div> Share line
			jQuery('<div></div>').addClass(this._CSS.shareLineClass).html('Share:&nbsp;').append(
				// <a> Submit to digg
				jQuery('<a></a>').addClass(this._CSS.diggClass).text('Digg').
							  attr('href', 'http://digg.com/remote-submit?phase=2&url=' + blogHref + '&title=' + titleEnc)
			).append(
				// <a> Submit to Facebook
				jQuery('<a></a>').addClass(this._CSS.facebookClass).text('Facebook').
							  attr('href', 'http://www.facebook.com/share.php?u=' + blogHref + '&t=' + titleEnc)
			).append(
				// <a> Submit to Newsvine
				jQuery('<a></a>').addClass(this._CSS.newsvineClass).text('Newsvine').
							  attr('href', 'http://www.newsvine.com/_tools/seed&save?u=' + blogHref + '&h=' + titleEnc)
			).append(
				// <a> Submit to stumbleupon
				jQuery('<a></a>').addClass(this._CSS.stumbleClass).text('Stumble').
							  attr('href', 'http://www.stumbleupon.com/submit?url=' + blogHref + '&title=' + titleEnc)
			).append(
				// <a> Submit to del.icio.us
				jQuery('<a></a>').addClass(this._CSS.deliciousClass).text('del.icio.us').
							  attr('href', 'http://del.icio.us/post?v=4&noui&jump=close&url=' + blogHref + '&title' + titleEnc)
			) // </div>
		) // </div>
	);
	
	return item;
};

// Tries to format with the jQuery date plugin and returns the built in format if the plugin didn't load
Fetcher.prototype._getDate = function(rawDate)
{
	return typeof(o2s) != "undefined" ? 
		   o2s.format(new Date(Date.parse(rawDate)), "dddd mmmm d yyyy hh:ii:ss A") :
		   new Date(Date.parse(rawDate)).toLocaleString();
}
Fetcher.prototype._getShortDescription = function(rawDesc) { return this._stripTags(rawDesc); };

Fetcher.prototype._stripTags = function(text) { return text.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi, ' '); };

// XML Helper class
Fetcher.prototype._xml = function(xml)
{
	var me = this;
	me.val = function(name) 
	{ 
		var elements = xml.getElementsByTagName(name);
		var firstElement; 
		if (elements.length > 0)
			firstElement = elements[0]; 
							
		// If the browser doesn't support a namespace in the tag name, use the tag after the colon
		else if (name.match(/:/))
		{
			name = name.split(':')[1];
			firstElement = xml.getElementsByTagName(name)[0];
		}
		
		// Multiple childnodes need to be combined
		if (firstElement.childNodes.length > 1)
			return me._combineChildren(firstElement.childNodes);
		else
			return firstElement.firstChild.nodeValue;
	};
	
	// Combines multiple childnode values into one string 
	// See https://bugzilla.mozilla.org/show_bug.cgi?id=452675 for the
	// reason this is needed
	me._combineChildren = function(children)
	{
		var combined = "";
		for(var i = 0; i < children.length; i++)
			combined += children[i].nodeValue;

	 	return combined;
	}
};

Fetcher.prototype._getNavigation = function()
{	
	var navArea = jQuery('<div></div>').addClass(this._CSS.navigationClass).addClass(this._CSS.pagesClass);
	var pages 	= jQuery('<span></span>');
	
	pages.append(this._getNavItem("Today", this.currentPage === 0, 0, true));
	
	var i = 0;
	while(i < this.pageLimit)
	{
		pages.append(this._getNavItem(i + 1, this.currentPage === i, i));
		i++;
	}
			
	navArea.append(pages);
	
	if (i < this.numPages)
		navArea.append(this._getMoreButton(pages));

	return navArea;
}

// Returns a button that adds more pages to the navigation list until the total number of pages has been reached
Fetcher.prototype._getMoreButton = function(pageList)
{
	var me = this;
	return jQuery('<a href="#">More...</a>').click(function(e)
	{
		if (me.pageLimit < me.numPages)
			for (var pagesAdded = 0; pagesAdded < 20 && me.pageLimit < me.numPages; pagesAdded++, me.pageLimit++)
				if (me.pageLimit < me.numPages)
					pageList.append(me._getNavItem(me.pageLimit + 1, me.currentPage === me.pageLimit, me.pageLimit));						
					
		if (me.pageLimit >= me.numPages)
			jQuery(this).hide();
			
		e.preventDefault();
	});
}

Fetcher.prototype._getNavItem = function(text, isCurrent, page, isFirst)
{
	var me = this;
	var item = jQuery('<a></a>').addClass(me._CSS.pageLinkClass).text(text).attr({href: '#'}).click(function(e) 
	{ 
		e.preventDefault();
		me.fetch(page);
	});
	
	if (isCurrent)
		item.addClass(me._CSS.pageLinkCurrentClass);
		
	if (isFirst)
		item.addClass(me._CSS.pageLinkFirstClass);
		
	return item;
}

Fetcher.prototype._CSS = 
{
	itemClass: 			'feedItem',
	titleClass: 		'feedTitle',
	descriptionClass: 	'feedDescription',
	bylineClass: 		'feedByline',
	byClass: 			'feedBy',
	creatorClass: 		'feedCreator',
	pubDateClass: 		'feedPubDate',
	commentCountClass: 	'feedCommentCount',
	commentLineClass: 	'feedCommentLine',
	permalinkClass: 	'feedPermalink',
	emailThisClass: 	'feedEmailThis',
	shareLineClass: 	'feedShareLine',
	diggClass: 			'feedDigg',
	facebookClass: 		'feedFacebook',
	newsvineClass: 		'feedNewsvine',
	stumbleClass: 		'feedStumble',
	deliciousClass: 	'feedDelicious',
	footerClass: 		'feedFooter',
	navigationClass: 	'feedNavigation',
	pagesClass: 		'feedPages',
	crumbClass: 		'feedCrumb',
	pageLinkClass: 		'feedPageLink',
	pageLinkFirstClass: 'feedPageLinkFirst',
	pageLinkCurrentClass: 'feedPageLinkCurrent',
	topNavClass: 		'feedTopNav'
};