// This file was generated by Dashcode from Apple Computer, Inc.
// You may edit this file to customize your Dashboard widget.

var feed = clean_feed_url(attributes.podcastURL);		// The podcast feed, as obtained from attributes.js
var refreshInterval = attributes.refreshInterval;		// How often the feed should refresh, from attributes.js

var last_updated = 0;				// Keeps track of the last update, so that the widget knows when to update
var xml_request = null;				// The current XMLHttpRequest
var loading_animation_timer;		// Tracks the "Loading..." animation
var results = new Array;			// The saved, parsed results of the request, used to store the episodes
var podcast_description = null;		// The podcast description, used on the widget's back
var isPlaying = false;				// Tracks whether the widget is currently playing


//---------------------------------------------------------------------------------------------
//	clean_feed_url()
//	XMLHttpRequest needs feed URLs to start with 'http'; if another handler is provided, replace it.
//---------------------------------------------------------------------------------------------
function clean_feed_url(feed)
{
	feed = feed.replace(/itpc/i,"http");
	feed = feed.replace(/pcast/i,"http");
	feed = feed.replace(/feed/i,"http");
	return feed;
}

//---------------------------------------------------------------------------------------------
//	podcast_load()
//	Called when the widget loads.  Clears out placeholder text on the widget.  Adds an
//  invisible <select> used to populate the episode name menu
//---------------------------------------------------------------------------------------------
function podcast_load()
{
	document.getElementById("episode_name").object.textElement.style.textOverflow = "ellipsis";
	document.getElementById("episode_name").object.textElement.innerText = "";
	document.getElementById("episode_date").innerText = "";
	document.getElementById("episode_description").innerText = "";
	document.getElementById("episode_information").innerText = "";

	var episode_popup = document.createElement("select");
	episode_popup.setAttribute("id","popup");
	episode_popup.setAttribute("onchange","change_episode(this);");
	episode_popup.style.height = document.defaultView.getComputedStyle(document.getElementById("episode_name"), null).getPropertyValue("height");
	episode_popup.style.width = document.defaultView.getComputedStyle(document.getElementById("episode_name"), null).getPropertyValue("width");
	episode_popup.style.top = document.defaultView.getComputedStyle(document.getElementById("episode_name"), null).getPropertyValue("top");
	episode_popup.style.left = document.defaultView.getComputedStyle(document.getElementById("episode_name"), null).getPropertyValue("left");
	document.getElementById("front").appendChild(episode_popup);
}

//---------------------------------------------------------------------------------------------
//	podcast_show()
//	Posts a request for the podcast RSS feed when the widget is shown.  Requests are spaced out
//	by the requestInterval to ease server load and prevent unnecessary load time.
//---------------------------------------------------------------------------------------------
function podcast_show()
{

	if(attributes.podcastURL == "") {
		document.getElementById("episode_name").object.textElement.innerText = "No Podcast specified";
	}
	else {
		
		var now = (new Date).getTime();
		
		// only check if referesh interval has passed
		if (((now - last_updated) > (refreshInterval * 60000)) && (isPlaying == false))	// Interval in minutes; 60000 is one minute
		{
			if (xml_request != null)
			{
				xml_request.abort();
				xml_request = null;
			}
			xml_request = new XMLHttpRequest();

			xml_request.onload = function(e) {xml_loaded(e, xml_request);}
			xml_request.overrideMimeType("text/xml");
			xml_request.open("GET", feed);
			xml_request.setRequestHeader("Cache-Control", "no-cache");
			xml_request.send(null);
			
			startLoadingAnimation();	// Begins the "Loading..." animation
		}
	}
}

//---------------------------------------------------------------------------------------------
//	findChild()
//	Scans the children of a given DOM element for a node matching nodeName.
//---------------------------------------------------------------------------------------------
function findChild (element, nodeName)
{
	var child;
	
	for (child = element.firstChild; child != null; child = child.nextSibling)
	{
		if (child.nodeName == nodeName)
			return child;
	}
	
	return null;
}

//---------------------------------------------------------------------------------------------
//	xml_loaded()
//	Extract the content of the podcast RSS feed and store the data in a results array.
//---------------------------------------------------------------------------------------------
function xml_loaded (e, request) 
{

	xml_request = null;
	if (request.responseXML)
	{		
		// Clear the results array
		while(results.length > 0)
		{
			results.pop();
		}
		
		// Get the top level <rss> element 
		var rss = findChild(request.responseXML, 'rss');
		if (!rss) return;
		
		// Get single subordinate channel element
		var channel = findChild( rss, 'channel');
		if (!channel) return;
		
		// Store the podcast description for use on the widget back
		podcast_description = findChild(channel, 'description');
		if( (podcast_description == null) || (podcast_description.firstChild == null) ) 
		{ 
			podcast_description = "No podcast description provided"; 
		}
		else {
			podcast_description = podcast_description.firstChild.data;
		}
							
		// Get all item elements subordinate to the channel element.
		// For each element, get title, pubDate, subtitle, description, and episode URL. 
		for( var item = channel.firstChild; item != null; item = item.nextSibling)
		{
			if( item.nodeName == 'item' ) 
			{
				var title = findChild (item, 'title');
			
				// we have to have the title to include the item in the list 
				if( title != null ) 
				{
					var title = findChild(item, 'title');
					if( (title == null) || (title.firstChild == null) ) 
					{ 
						title = "No episode title provided"; 
					}
					else {
						title = title.firstChild.data;
					}

					var date = findChild(item, 'pubDate');
					var dateString = null;
					if( (date == null) || (date.firstChild == null) )
					{
						dateString = null;
						date = null;
					}
					else {
						dateString = date.firstChild.data;
						date = new Date(Date.parse(date.firstChild.data));
					}
					
					var description = findChild(item, 'description');
					if( (description == null) || (description.firstChild == null) ) 
					{ 
						description = "No episode description provided"; 
					}
					else {
						description = description.firstChild.data;
					}

					var subtitle = findChild(item, 'itunes:subtitle');
					if( (subtitle == null)  || (subtitle.firstChild == null) ) 
					{
						subtitle = description;
					}
					else {
						subtitle = subtitle.firstChild.data;
					}

					var link = findChild (item, 'link');
					if(link == null) 
					{ 
						link = null; 
					}
					else {
						link = link.firstChild.data;
					}

					var enclosure = findChild(item, 'enclosure')
					if(enclosure == null) 
					{
						// if there's no enclosure, there's no episode to play; ignore the entry and move on.
						continue;
					}
					else {
						enclosure = enclosure.getAttribute('url');
					}
									
					results[results.length] = {
						title:title,
						date:date,
						dateString:dateString,
						subtitle:subtitle,
						description:description,
						link:link,
						track:enclosure
					};
				}
			}
		}
		
		// Sort by date
		results.sort(compFunc);
		
		// Since we have results, pause the loading animation
		stopLoadingAnimation();
		
		// Copy titles into the pop-up menu
		populate_menu(results);
		
		// Place the most recent episode's information on the widget
		update_episode(results[0]);
		
		// Reset the last updated value track how often the widget refreshes
		last_updated = (new Date).getTime();
	}
}

//---------------------------------------------------------------------------------------------
//	compFunc()
//	The compare function, used for sorting the results by date.  Sorts from newest to oldest.
//---------------------------------------------------------------------------------------------
function compFunc(a, b)
{
	if (a.date < b.date)
		return 1;
	else if (a.date > b.date)
		return -1;
	else
		return 0;
}

//---------------------------------------------------------------------------------------------
//	createDateStr()
//	Creates a readable date string from the provided Date object.
//---------------------------------------------------------------------------------------------
function createDateStr(date)
{
	if (date == null) { return "No or improper date provided"; }
	
	var day;
	switch (date.getDay())
	{
		case 0: day = getLocalizedString("Sunday"); break;
		case 1: day = getLocalizedString("Monday"); break;
		case 2: day = getLocalizedString("Tuesday"); break;
		case 3: day = getLocalizedString("Wednesday"); break;
		case 4: day = getLocalizedString("Thursday"); break;
		case 5: day = getLocalizedString("Friday"); break;
		case 6: day = getLocalizedString("Saturday"); break;
		default: day = "";
	}

	var month;
	switch (date.getMonth())
	{
		case 0: month = getLocalizedString("January"); break;
		case 1: month = getLocalizedString("February"); break;
		case 2: month = getLocalizedString("March"); break;
		case 3: month = getLocalizedString("April"); break;
		case 4: month = getLocalizedString("May"); break;
		case 5: month = getLocalizedString("June"); break;
		case 6: month = getLocalizedString("July"); break;
		case 7: month = getLocalizedString("August"); break;
		case 8: month = getLocalizedString("September"); break;
		case 9: month = getLocalizedString("October"); break;
		case 10: month = getLocalizedString("November"); break;
		case 11: month = getLocalizedString("December"); break;
		default: month = "";
	}
	
	if (day == "" && month == "")
	{
		return null;
	}
	else {
		return day + ", " + month + " " + date.getDate() + ", " + date.getFullYear();
	}
}


//---------------------------------------------------------------------------------------------
//	populate_menu()
//	Called whenever there's a need to change the elements shown in the episode popup menu.  It
//	empties the menu and replaces its items with the titles found in a results-structured array.
//---------------------------------------------------------------------------------------------
function populate_menu(results)
{
	var menu = document.getElementById("popup");

	while(menu.length > 0)
	{
		menu.options[menu.length-1] = null;
	}

	for (var i = 0; i < results.length; ++i)
	{
		var item = results[i];			
		var episodeName = new Option(item.title, item.title, 0);
		menu.options[menu.length] = episodeName;
	}
	menu.options[0].selected = true;	// set the first item in the menu as selected
}

//---------------------------------------------------------------------------------------------
//	change_episode()
//	Called when a new item is selected in the menu; swaps out the episode info and track with
//	the selected episode's.
//---------------------------------------------------------------------------------------------
function change_episode(elem) 
{
	var chosen = elem.options[elem.selectedIndex].value;
	for(var i=0; chosen != results[i].title; ++i) { }	
	update_episode(results[i]);
}

//---------------------------------------------------------------------------------------------
//	update_episode()
//	Updates all of the various strings on the widget with the supplied episode's information.
//	Also preps the episode track to play and pauses it
//---------------------------------------------------------------------------------------------
function update_episode(elem)
{

	if(isPlaying) { document.getElementById("episode_track").Stop(); }

	document.getElementById("episode_name").object.textElement.innerText = strip_tags(elem.title);
	
	var date = createDateStr(elem.date);
	if (date == null)
	{
		if (elem.dateString != null) { document.getElementById("episode_date").innerText = elem.dateString; }
	}
	else {
		document.getElementById("episode_date").innerText = date;
	}
	
	document.getElementById("episode_description").innerText = strip_tags(elem.subtitle);		
	document.getElementById("episode_information").innerHTML = (elem.title + "<br>" + elem.description + "<br><br>About this Podcast:<br>" +  podcast_description).replace(/\r?\n/g,"<br>");		

	var episode = document.createElement('embed');
	episode.setAttribute("id","episode_track");
	episode.setAttribute("controller","false");
	if(isPlaying) {
		episode.setAttribute("autoplay","true");
	}
	else {
		episode.setAttribute("autoplay","false");	
	}
	episode.setAttribute("qtnext1","javascript: load_next();");
	episode.setAttribute("enablejavascript","true");
	episode.setAttribute("src",elem.track);
	
	if (document.getElementById("episode_track") != null)
	{
		document.getElementById("body").removeChild(document.getElementById("episode_track"));	
	}
	document.getElementById("body").appendChild(episode);
}

//---------------------------------------------------------------------------------------------
//	load_next()
//  Called when a track finishes playing.  Pauses playback, loads next track.
//---------------------------------------------------------------------------------------------
function load_next()
{
	playpause();
	var menu = document.getElementById("popup");
	var chosen = menu.options[menu.selectedIndex].value;
	for(var i=0; chosen != results[i].title; ++i) { }	
	if ( i == (menu.length-1) )
	{
		i = 0;
	}
	else {
		i = i+1;
	}	
	menu.options[i].selected = true;	// set the first item in the menu as selected
	update_episode(results[i]); 	
}

//---------------------------------------------------------------------------------------------
//	strip_tags()
//	Removes any extra HTML tags that may be strewn about the response XML.
//---------------------------------------------------------------------------------------------
function strip_tags(aString)
{
	return aString.replace(/<[^>]*>/g,"");
}

//---------------------------------------------------------------------------------------------
//	subscribe()
//  Caleld when the subscribe button is clicked on the widget's back; hands off the podcast
//	URL to iTunes.
//---------------------------------------------------------------------------------------------
function subscribe(event) 
{
	widget.openURL(feed.replace(/http/,"itpc"));
}

//---------------------------------------------------------------------------------------------
//	startLoadingAnimation() & stopLoadingAnimation()
//	Places animated "Loading..." text on the widget while the feed loads.
//---------------------------------------------------------------------------------------------
function startLoadingAnimation()
{
	var dots = 0;
	var animate_loading_dots = function ()
	{
		var loading = "Loading";
		for (var i = 0; i < dots; i++) {
			loading = loading + ".";
		}
		document.getElementById("episode_name").object.textElement.innerText = loading;
		
		if (++dots > 3) {
			dots = 0;
		}
	};
	
	loading_animation_timer = setInterval(animate_loading_dots, 500);
}

function stopLoadingAnimation()
{
	if (loading_animation_timer != null) {
		clearInterval(loading_animation_timer);
		loading_animation_timer = null;
	}
}

//---------------------------------------------------------------------------------------------
//	playpause()
//	Toggles whether the widget is playing or not
//---------------------------------------------------------------------------------------------
function playpause(event)
{
	if(document.getElementById("episode_track") == null) return;
	
	if(!isPlaying)
	{
		document.getElementById("play_button").src = "Images/pause.png";
		document.getElementById("episode_track").Play();
	}
	else {
		document.getElementById("play_button").src = "Images/play.png";
		document.getElementById("episode_track").Stop();
	}
	isPlaying = !isPlaying;
}