/* 
 * some of the following is taken and/or modified from:
 * http://developer.apple.com/internet/webcontent/xmlhttpreq.html
 *
 *  aaron evans:  (aarone at aarone.org)
 */

var isIE = false; 

/* each kind of request has its own producer */
var sourceProducer = null;
var artistProducer = null;
var albumProducer = null;
var tracksProducer = null;
var artworkProducer = null;
var allAlbumsProducer = null;

var activeProducers = [];

/* create a producer and aynschonously notify that the producers content has been loaded via callback */
function ContentProducer(pathToXML, callback)
{
	if(pathToXML == null)
		return;

	try {
		if (window.XMLHttpRequest) {
			this.request = new XMLHttpRequest();
			this.request.onreadystatechange = callback;
			this.request.open("GET", pathToXML, true);
			this.request.send(null);
		}
		else if (window.ActiveXObject) {
			isIE = true;
			this.request = new ActiveXObject("Microsoft.XMLHTTP");
			if (this.request) {
				this.request.onreadystatechange = callback;
				this.request.open("GET", pathToXML, true);
				this.request.send();
			}
		}
	}
	catch(e) {}

	/* producer instance variables */
	this.xmlPath = pathToXML;
	this.contentHasBeenDisplayed = false;
	this.displayContentIfReady = displayContentIfReady;
	this.setContentHasBeenDisplayed = setContentHasBeenDisplayed;
	this.shouldDisplayContent = shouldDisplayContent;
}

/* called when it2w page loads */
function init()
{
	loadArtwork();
	displayEmptyTracksTable();
	loadSources();
}

function setContentHasBeenDisplayed(v)
{
	this.contentHasBeenDisplayed = v;
}

function shouldDisplayContent()
{
	return 	this.request != null &&
			this.request.readyState == 4 &&
			!this.contentHasBeenDisplayed;
}

/* called when the page is loaded */ 
function loadSources()
{
	var pathToSources = "db/sources.xml";
	if(sourceProducer == null) {
		sourceProducer = new ContentProducer(pathToSources, sourcesDidLoad);
		sourceProducer.activeSource = "Library";
		sourceProducer.displayContent = displaySources;
		sourceProducer.isFirstDisplay = true;
	}
	else {
		sourceProducer.displayContent();
	}
}

/* return an image for a source name */
function getImageForSource(sourceName, isSmartPlaylist)
{
	if(sourceName == "Library")
        return "images/library.gif";
	else if(sourceName == "Party Shuffle")
		return "images/partyMix.gif"; 
    else if(sourceName == "Podcasts")
        return "images/podcasts.gif";
    else if(sourceName == "Videos")
        return "images/videos.gif";
    if(isSmartPlaylist != null && isSmartPlaylist)
        return "images/smartPlaylist.gif";

    return "images/playlist.gif";
}

/* return an entry in the sources list */
function getSourceLink(isSelected, iconURL, sourceName, sourceURL)
{   
    var selectClass = (isSelected) ? "selectedSource" : "unselectedSource";
    return "<a href=\"#\" onClick=\"setActiveSource('" + sourceName + "')\"><div class=\"" + selectClass + "\"<img src=\"" + iconURL + "\" \>" + sourceName + "</div></a>";
}

function displayContentIfReady()
{
	if(this.shouldDisplayContent())
	{
		this.displayContent();
		this.setContentHasBeenDisplayed(true);
	}	
}

function sourcesDidLoad()
{
	if(sourceProducer != null)
		sourceProducer.displayContentIfReady();
}

function artworkDidLoad()
{
	if(artworkProducer != null)
		artworkProducer.displayContentIfReady();
}

function artistsDidLoad()
{
	if(artistProducer != null)
		artistProducer.displayContentIfReady();	
}

function albumsDidLoad()
{
	if(albumProducer != null)
		albumProducer.displayContentIfReady();
}

function tracksDidLoad()
{
	if(tracksProducer != null)
		tracksProducer.displayContentIfReady();
}

/* each dependent producer of the allAlbumsProducer loads here */
function multiAlbumProducerDidLoad()
{
	var i;
	for(i=0;i<allAlbumsProducer.dependentProducers.length;i++) {
		var thisProducer = allAlbumsProducer.dependentProducers[i];
		if(thisProducer.shouldDisplayContent())
		{
			thisProducer.setContentHasBeenDisplayed(true);
			allAlbumsProducer.albumsLoaded++;
		}
	}

	/* after we've loaded all xml for all albums, turn the xml into html */
	if(allAlbumsProducer.albumsLoaded == allAlbumsProducer.numberOfAlbumsToLoad)
		allAlbumsProducer.displayContent();
}



/* assumes that a sourceProducer exists and is ready */
function displaySources()
{
	if(!sourceProducer.shouldDisplayContent())
		return;

	/* get the XML from the sources document */
	var sourcesXML = this.request.responseXML;
	var sourceElements = this.request.responseXML.getElementsByTagName("source");
	var sourceNames = []; /* a list of all known names for sources */
	var sourceLocationHash = []; /* a hash keyed on source name with locations to the source */
	var i;
	for(i=0;i<sourceElements.length;i++) {
		var sourceName = getElementTextNS("", "val", sourceElements[i], 0);
		var sourceURL = getElementTextNS("", "key", sourceElements[i], 0);
		sourceNames = sourceNames.concat(sourceName);
		sourceLocationHash[sourceName] = sourceURL;
	}

	var sourcesHTMLContent = "";
	/* we have a special order for writing sources to the page; these sources precede any user-defined playlists */
	var specialPlaylists = ["Library", "Podcasts", "Videos", "Party Shuffle", "Purchased"];
	for(i=0;i<specialPlaylists.length;i++) {
		var thisSource = specialPlaylists[i];
		var imageLocation = getImageForSource(thisSource);
		var thisSourceURL = sourceLocationHash[thisSource];

		if(thisSourceURL != null) {
			sourcesHTMLContent += getSourceLink(sourceProducer.selectedSource == thisSource, imageLocation, thisSource, thisSourceURL); // add the source to the list of sources
		}
	}

	/* add the non-standard playlists to the list */
	for(i=0;i<sourceNames.length;i++) {
		var aSource = sourceNames[i];
		var aSourceLoc = sourceLocationHash[aSource];
		if(!arrayContainsElement(specialPlaylists, aSource)) {
			sourcesHTMLContent += getSourceLink(sourceProducer.selectedSource == aSource, getImageForSource(aSource), aSource, sourceLocationHash[aSource]);
		}
	}

	sourceProducer.sourcesHash = sourceLocationHash;

	sourcesDiv = document.getElementById("sources");
	/* put the content we just created in the doc */
	sourcesDiv.innerHTML = sourcesHTMLContent;

	if(sourceProducer.isFirstDisplay != null && sourceProducer.isFirstDisplay) {
		sourceProducer.isFirstDisplay = false;
		setActiveSource("Library");
	}
	
		
}

/* creates a cache for paths to cover art files */
function loadArtwork()
{
	var pathToArtList = "db/Covers/allAlbums.xml";
	if(artworkProducer == null) { /* only load it once */
		artworkProducer = new ContentProducer(pathToArtList, artworkDidLoad);
		artworkProducer.displayContent = createArtworkCache;
	}
}

/* we construct a cache of valid paths to artwork for albums.  The cache is an associative hash where the keys are given by the last two components of the path to the xml file defining other content fot the album.  When displaying album content, we can create the key from the known path to album content and get a path to the associated cover art if it exists */
function createArtworkCache()
{
	var xmlList = artworkProducer.request.responseXML;
	var items = xmlList.getElementsByTagName("album");
	
	var i;
	artworkProducer.cache = [];
	for(i=0;i<items.length;i++) {
		var key = getElementTextNS("","key", items[i],0);
		var val = getElementTextNS("","val", items[i],0);
		artworkProducer.cache[key] = val;
	}
}

/* called when you click on a source in the sources pane */
function setActiveSource(nameOfSource)
{
	var previousActiveSource = sourceProducer.activeSource;
	sourceProducer.selectedSource = nameOfSource;
	var pathToArtistsList = sourceProducer.sourcesHash[nameOfSource];

	if(pathToArtistsList == null)
		return;

	// each playlist has a unique album producer
	if(	artistProducer == null ||  
		(artistProducer.source != null && artistProducer.source != previousActiveSource)
		 ) {

		artistProducer = null;
		artistProducer = new ContentProducer(pathToArtistsList, artistsDidLoad);
		artistProducer.displayContent = displayArtists;
		artistProducer.source = pathToArtistsList;
	}
	else {
		artistProducer.displayContent();
	}

	// redisplay the sources so the correct selected source is highlighted
	sourceProducer.setContentHasBeenDisplayed(false);
	sourceProducer.displayContent();
}

/*
 * The album producer has a list of all albums for a given artist and displays them in the select list.
 * This method takes the list of albums for the given album producer and loads all of the songs for all
 * of the albums by generating a distinct request for each album's content.
 */
function loadAllSongsForAllAlbums()
{
	allAlbumsProducer = new ContentProducer(); // xml is defined by multi doc load
	allAlbumsProducer.displayContent = displayAllSongsInAllAlbums;
	/* prevent this producer from calling displayContent, we want to wait until all dependent producers have been loaded */
	var items = this.request.responseXML.getElementsByTagName("album");
	allAlbumsProducer.albumsLoaded = 0;
	allAlbumsProducer.numberOfAlbumsToLoad = items.length;
	allAlbumsProducer.dependentProducers = [];
	var i;
	for(i=0;i<items.length;i++) {
		pathToAnAlbumToLoad = getElementTextNS("","key", items[i],0);
		 /* load songs for this album */
		var tempProducer = new ContentProducer(pathToAnAlbumToLoad, multiAlbumProducerDidLoad);
		allAlbumsProducer.dependentProducers = allAlbumsProducer.dependentProducers.concat(tempProducer);
	}
}

/* called when our allAlbumsProducer has loaded all content for all of the albums that need to be displayed */
function displayAllSongsInAllAlbums()
{
	var tableGenerator = new TracksTableGenerator(LinkStyle);
	/* for each dependent request,  we add the songs for that request to the table */
	var i;
	for(i=0;i<allAlbumsProducer.dependentProducers.length;i++) {
		var thisProducer = allAlbumsProducer.dependentProducers[i];
		var songs = thisProducer.request.responseXML.getElementsByTagName("song");
		tableGenerator.addSongsToTable(songs);
	}

	/* set the created content in the html */
	var songsDiv = document.getElementById("songs");
	songsDiv.innerHTML = tableGenerator.getHTMLContent(); /* set the content */
}

/* method of an artist producer to display its content */
function displayArtists()
{
	var select = document.getElementById("artists");
	select.innerHTML = "";
	var items = this.request.responseXML.getElementsByTagName("artist");

	for(var i=0; i<items.length; i++)
		appendToSelect(select, getElementTextNS("","key", items[i],0), document.createTextNode(getElementTextNS("", "val", items[i], 0)));

	loadAlbumsFromXML(getElementTextNS("", "key", items[0],0));
}

/* called when a user clicks an artist, we create an album producer for that artist */
function loadAlbums(evt) 
{
	var albumsListLocation = null;
	if(evt == null) {
		albumsListLocation = "db/Library/allAlbums.xml";
	}
	else {
		var elem = (evt.target) ? evt.target: ((evt.srcElement)? evt.srcElement : null);
		var indx = getIndexForEvent(evt);
		albumsListLocation = elem.options[indx].value;
	}

	loadAlbumsFromXML(albumsListLocation);
}

function loadAlbumsFromXML(pathToXML) {
	albumProducer = null;
	albumProducer = new ContentProducer(pathToXML, albumsDidLoad);
	albumProducer.displayContent = displayAlbums;
	albumProducer.loadAllSongsForAllAlbums = loadAllSongsForAllAlbums;
}

/* method for an album producer to display its content */
function displayAlbums()
{
	if(artistProducer == null)
		return;

	var albumCount = 0;
	var select = document.getElementById("albums");
	var albums = this.request.responseXML.getElementsByTagName("album");
	clearSelectList("albums");

	for(var i=0;i<albums.length;i++)
		appendToSelect(select, getElementTextNS("", "key", albums[i], 0), document.createTextNode(getElementTextNS("", "val", albums[i], 0)));

	if(albums.length==1) {
		insertHeadToSelect(select, artistProducer.xmlPath, document.createTextNode("All (" + albums.length+ " Album)"));
	} else {
		insertHeadToSelect(select, artistProducer.xmlPath, document.createTextNode("All (" + albums.length+ " Albums)"));
	}
	
//	albumProducer.loadAllSongsForAllAlbums();
}

function displayEmptyTracksTable()
{
	var generator = new TracksTableGenerator(LinkStyle);
	var songsDiv = document.getElementById("songs");
	songsDiv.innerHTML = generator.getHTMLContent();	
}

/*
 * when an album is clicked this is called.  It is load the songs for that album at the specified path  
 */
function loadSongs(loadSongsEvent)
{
	var elem = (loadSongsEvent.target) ? loadSongsEvent.target: ((loadSongsEvent.srcElement)? loadSongsEvent.srcElement : null);
	var indx = getIndexForEvent(loadSongsEvent);

	var loadingAllAlbumsForAllArtist = 	indx == 0 &&
										albumProducer.xmlPath.match("allAlbums.xml") == "allAlbums.xml";


	if(loadingAllAlbumsForAllArtist && 
		(ForceLoadAllArtistsAllAlbums != null && !ForceLoadAllArtistsAllAlbums)) {
		displayEmptyTracksTable();
		return;
	}
	else if(indx==0) { // load all songs for this artist
		albumProducer.loadAllSongsForAllAlbums();
	} else {
		tracksProducer = new ContentProducer(elem.options[indx].value, tracksDidLoad);
		tracksProducer.displayContent = displayTracks;
	}
}

/* for a path a/b/c/d.xml, return c/d.xml
*/
function getShortPathForAlbumXMLPath(xmlPath)
{
	var pathComponents = xmlPath.split('/');
	if(pathComponents == null || pathComponents.length < 3)
		return null;
	
	return pathComponents[pathComponents.length-2] + '/' + pathComponents[pathComponents.length-1];
}

function displayTracks()
{
	var songs = this.request.responseXML.getElementsByTagName("song");
	var generator = new TracksTableGenerator(LinkStyle);
	
	generator.addSongsToTable(songs);
	var songsDiv = document.getElementById("songs");
	songsDiv.innerHTML = generator.getHTMLContent(); /* set the content */

	/* load the artwork here */
	var artDiv = document.getElementById("artwork");
	artDiv.innerHTML="";
	var artworkKey = getShortPathForAlbumXMLPath(tracksProducer.xmlPath)

	var pathToArtwork = null;
	if(artworkProducer != null && artworkProducer.cache != null)
		pathToArtwork = artworkProducer.cache[artworkKey];

	if(pathToArtwork != null) 
		artDiv.innerHTML += "<img src=\"" + pathToArtwork + "\"\\>";
}

