var FeedManager = {};

// for blogs -- URL should be to RSS2.0 feed
FeedManager.getLatestBlogEntries = function(url,numEntries,options)
{
  if(numEntries == null || isNaN(numEntries))
  {
    numEntries = 5;
  }

  if(options.externalFeed != null && options.externalFeed == true)
  {
    // get feed with Google API -- NOTE: currently requires that feed API is already loaded.
    var feed = new google.feeds.Feed(url);
    feed.setResultFormat(google.feeds.Feed.XML_FORMAT);
    feed.setNumEntries(numEntries);
    feed.load(function(result) {
      if (!result.error) {
        FeedManager.showLatestBlogEntries($(result.xmlDocument), result.status, numEntries, options); 
        }
      });
  } // end block for external feeds
  else {
    $.ajax({
      type: 'GET',
      url: url,
      dataType: 'xml',
      success: function(data, textStatus) { FeedManager.showLatestBlogEntries(data, textStatus, numEntries, options); },
      error: function(XMLHttpRequest, textStatus, errorThrown) { FeedManager.showError(options); } 
    });
  } // end block for non-external feeds
}


// expects RSS2.0 feed
FeedManager.showLatestBlogEntries = function(data, textStatus, numEntries, options)
{
window.data = data;
	var defaults = {
		/* These options apply only if htmlTemplate is null */
		showTitle : true, // If true, shows the blog's title
		showMoreLink : true, // If true, shows a link at the bottom of the entries that links to the blog
		showDate : false, // If true, shows each entry's date with each entry
		showEntryBody : false, // If true, shows the text of each entry
		
		/* HTML Template Options */
		htmlTemplate: null, // If replaced with some HTML, the script will use this code to generate its output.
		htmlTemplateHeader: null, // HTML to go above the entry HTML -- applies if htmlTemplate option is used
		htmlTemplateFooter: null, // HTML to go below the entry HTML -- applies if htmlTemplate option is used

		/* Other */
		htmlFilter : false, // A function that takes one parameter (the generated HTML).  The script will render the HTML returned by this function.
		entryListEl : null // The element where the HTML will be prepended.  If not specified, the script will write to document.
	}

	options = $.extend(defaults,options);
	var html = '';

	if(typeof(options.htmlTemplate) == 'string' && options.htmlTemplate != '')
	{
		html = FeedManager.generateHtmlWithTemplate(data,numEntries,options);
	}
	else
	{
		html = FeedManager.generateHtml(data,numEntries,options);
	}

  if(typeof(options.htmlFilter) == 'function')
  {
    html = options.htmlFilter(html);
  }
	
	if(typeof(options.entryListEl) != null)
	{
		options.entryListEl.prepend($.trim(html));
	}
	else
	{
		document.write($.trim(html));
	}
}

FeedManager.showError = function(options)
{
	var html = '<h3>Error</h3>';
	html += '<ul><li>Sorry, but an error occurred when retrieving the latest blog entries.';
	html += '</li></ul>';
	
	if(options.entryListEl != null)
	{
		options.entryListEl.html(html);
	}
	else
	{
		document.write(html);
	}
}

FeedManager.generateHtml = function(data,numEntries,options)
{
  var html;

	if(options.showTitle == true)
	{
		var html = '<h3>' + $(data).find('channel > title').text() + '</h3>';
	}

	html += '<ul>';

  var entries = $(data).find('item');
  if(entries.length < numEntries)
  {
    numEntries = entries.length;
  }

	// add li class="first" to first li
  for(var i = 0; i < numEntries; i++)
  {
    var e = $(entries[i]);
		if(i == 0)
		{
			html += '<li class="first">';
		}
		else
		{
			html += '<li>';
		}
    html += '<a href="' + e.find('link').text() + '" target="_parent">' + $(entries[i]).find('title').text() + '</a>';
		
		if(options.showDate == true)
		{
			html += ' <span>' + FeedManager.getFeedDate(e.find('pubDate').text()) + '</span>';
		}
		
		if(options.showEntryBody == true)
		{
			html += '<div class="entry-body">' + e.find('description').text() + '</div>';
		}
		
		html += '</li>';
  }
  html += '</ul>';
	
	if(options.showMoreLink != false)
	{
		html += '<a class="more" target="_parent" href="' + $(data).find('channel > link').text() + '">More</a>';
	}

  return html;
};

FeedManager.generateHtmlWithTemplate = function(data,numEntries,options)
{
  var html = '';
  var template = options.htmlTemplate;
  var searches = [/__BLOG_TITLE__/g,/__ENTRY_TITLE__/g,/__ENTRY_TEXT__/g,/__ENTRY_BLURB__/g,/__ENTRY_URL__/g,/__ENTRY_DATE__/g,/__ENTRY_TIME__/g,/__BLOG_URL__/g];

  // determine date format - feedburner feed congress.org uses 2010-01-14T16:34:39
  // whereas others use Mon 18 Jan 2010 00:00:00 EST 
  var sampleDate = $(data).find('item:first').find('pubDate').text();
  var DATE_FORMAT;
  
  // test for ISO; otherwise assume RSS format
  if(sampleDate.length == 19 && sampleDate.indexOf('T') == '10') { DATE_FORMAT = 'ISO'; }
  else { DATE_FORMAT = 'RSS'; }


  var entries = $(data).find('item');
  if(entries.length < numEntries)
  {
    numEntries = entries.length;
  }

  var blogTitle = $(data).find('channel > title').text();
  var blogUrl = $(data).find('channel > link').text();
  var searchLen = searches.length;

  for(var i = 0; i < numEntries; i++)
  {
    var e = $(entries[i]);

    // blurb requires some work -- need to get CDATA parsed into HTML.  for now a hack:
    var el = document.createElement('div');
    $(el).html(e.find('description').text());

    var entryTitle = $(entries[i]).find('title').text();
    var entryText = e.find('description').text();
    var entryBlurb = '<p>' + $(el).find('p:first').html() + '</p>';
    var entryUrl = e.find('link').text();

    // handle atom time stamps
    var pubDate = e.find('pubDate').text();
    var entryDate;
    var entryTime;
    if(DATE_FORMAT == 'ISO')
    {
      entryDate = FeedManager.getApFeedDateFromIsoTimestamp(pubDate);
      entryTime = FeedManager.getApFeedTimeFromIsoTimestamp(pubDate);
    }
    else // RSS feed
    {
      entryDate = FeedManager.getApFeedDate(pubDate);
      entryTime = FeedManager.getApFeedTime(pubDate);
    }
    var replace = [blogTitle,entryTitle,entryText,entryBlurb,entryUrl,entryDate,entryTime,blogUrl];

    var t = '' + template;
    for(var j = 0; j < searchLen; j++)
    {
      t = t.replace(searches[j],replace[j]);
    }

    html += t;
  }

  /* Header and footer - search and replace for blog title and link only */
  if((typeof(options.htmlTemplateHeader) == 'string' && options.htmlTemplateHeader != '') || (typeof(options.htmlTemplateFooter) == 'string' && options.htmlTemplateFooter != ''))
  {
    var searches = [/__BLOG_TITLE__/g,/__BLOG_URL__/g];
    var replace = [blogTitle,blogUrl];
    var searchLen = searches.length;

    if(options.htmlTemplateHeader != null && options.htmlTemplateHeader != '')
    {
      var h = options.htmlTemplateHeader;
      for(var j = 0; j < searchLen; j++)
      {
        h = h.replace(searches[j],replace[j]);
      }
      html = h + html;
    }

    if(options.htmlTemplateFooter != null && options.htmlTemplateFooter != '')
    {
      var f = options.htmlTemplateFooter;
      for(var j = 0; j < searchLen; j++)
      {
        f = f.replace(searches[j],replace[j]);
      }
      html = html + f;
    }
  } // end header & footer

  return html;
};

// TODO: clean up and rewrite formatters

FeedManager.getFeedDate = function(rssDate)
{
	// e.g.
	// Tue, 28 Oct 2008 06:00:00 -0500
	// to 10/28/2008
	
	var d = rssDate.split(' ');
	var months =
	{
		'Jan' : '1',
		'Feb' : '2',
		'Mar' : '3',
		'Apr' : '4',
		'May' : '5',
		'Jun' : '6',
		'Jul' : '7',
		'Aug' : '8',
		'Sep' : '9',
		'Oct' : '10',
		'Nov' : '11',
		'Dec' : '12'
	}
	
	var numMonth = months[d[2]];
	var dt = numMonth + '/' + d[1] + '/' + d[3];
	
	return dt;	
};

// TODO: separate out formatting into separate classes; create single date object from different date formats; use separate formatters for different date formats
// for now, a hack:

FeedManager.getApFeedDateFromIsoTimestamp = function(atomDate)
{
// expects format 2010-01-19T16:28:07
	var ts = atomDate.split('T');
	var d = ts[0].split('-'); 

	var months =
	{
		'1' : 'Jan.',
		'2' : 'Feb.',
		'3' : 'March',
		'4' : 'April',
		'5' : 'May',
		'6' : 'June',
		'7' : 'July',
		'8' : 'Aug.',
		'9' : 'Sep.',
		'10' : 'Oct.',
		'11' : 'Nov.',
		'12' : 'Dec.'
	}
	
	var numMonth = months[("" + parseInt(d[1],10))];
	var dt = numMonth + ' ' + parseInt(d[2],10) + ', ' + d[1];
	
	return dt;
};

FeedManager.getApFeedTimeFromIsoTimestamp = function(atomDate)
{
	var ts = atomDate.split('T');
	var t = ts[1].split(':'); 
	var h = parseInt(t[0],10);
	var m = parseInt(t[1],10);
	var p = 'a.m.';
	
	if(h == 0)
	{
	  h = 12;
	}
	else if(h >= 12)
	{
		if(h > 12) { h = h - 12 };
		p = 'p.m.';
	}

	if(m < 10)
	{
		m = '0' + m;
	}

	return h + ':' + m + ' ' + p;
};

FeedManager.getApFeedDate = function(rssDate)
{
	var d = rssDate.split(' ');
	var months =
	{
		'Jan' : 'Jan.',
		'Feb' : 'Feb.',
		'Mar' : 'March',
		'Apr' : 'April',
		'May' : 'May',
		'Jun' : 'June',
		'Jul' : 'July',
		'Aug' : 'Aug.',
		'Sep' : 'Sep.',
		'Oct' : 'Oct.',
		'Nov' : 'Nov.',
		'Dec' : 'Dec.'
	}
	
	var numMonth = months[d[2]];
	var dt = numMonth + ' ' + parseInt(d[1],10) + ', ' + d[3];
	
	return dt;	
};

FeedManager.getApFeedTime = function(rssDate)
{
	var d = rssDate.split(' ');
	var t = d[4].split(':');
	var h = parseInt(t[0],10);
	var m = parseInt(t[1],10);
	var p = 'a.m.';
	
	if(h == 0)
	{
	  h = 12;
	}
	else if(h >= 12)
	{
		if(h > 12) { h = h - 12 };
		p = 'p.m.';
	}

	if(m < 10)
	{
		m = '0' + m;
	}

	return h + ':' + m + ' ' + p;
};