/** This class makes it possible to display videos sorted by date in a tabed interface organized by special tags.
  * @param aParentId The id of a container for the menu.
  * @param aSeriesKey The unique tag key identifier of a series.
  */
function VideoMenu ( aParentId , aSeriesKey, aType )
{

	this.myCurrentVideoId = null; 

	// stupid gloabl variable
	videoMenuObject 		= this;

	this.myCurrentVideoId 	= 0;
	this.mySeriesKey		= aSeriesKey;
	this.myParentTag		= $( "#" + aParentId );
	this.myDeck				= new Array();
	this.mySeasons			= new Array();
	this.myVideos			= new Array();
	this.myPlaylists 		= new Array();

	this.myType				= aType;	
	this.foundVideoToCue	= false;

	// If it's a call with arguments, do it, otherwise (if it's being initialized), don't 
	if (aParentId && aSeriesKey && aType)
	{
		// Get the entire list of videos with this seriesKey as a tag
		$.ajax({
			url:    "lib/json.php?getVideosFromSeries=" + this.mySeriesKey,
			success: function( data ) 
			{
				videoMenuObject.addVideos (data );
	        },
			async:   false
	    });

	
		// Get list of seasons with this seriesKey
		$.ajax({
			url:    "lib/json.php?getSeasonsFor=" + this.mySeriesKey,
			success: function( data ) 
			{
				videoMenuObject.addSeasons (data );
	        },
			async:   false
	    });	
	
		// go through videos group into composites where necessary
		this.makeDeck();
	
		// execute
		this.draw();
	}	

} // End of VideoMenu


/*
 * Mutators
 */

/**
 * Change the video menu to a different show.
 * Basically just wraps the constructor.
 */
VideoMenu.prototype.change = function ( aParentId , aSeriesKey, aType )
{
	this.constructor( aParentId , aSeriesKey, aType );
}


/**
 * Adds seasons from database array. 
 */
VideoMenu.prototype.addSeasons = function ( jsonData )
{
	var mySeasonData = eval ("(" + jsonData + ")");
	var html = "";

	
	for ( var i in mySeasonData )
	{
		oneSeason = mySeasonData[i];
		//mySeasonData.mySeriesKey;
		
		this.mySeasons.push( new Season ( oneSeason ) );
		
	}
		
	// Did we actually add any seasons?
	if ( this.mySeasons.length > 0 )
	{
		$("#playlistsTitle").empty();
		$("#playlistsTitle").append("Playlists: ");
		
		for ( var i in this.mySeasons )
		{
			html += "<a href=\"#\" onclick=\"setMenuFocus('seasonHeader-" + this.mySeasons[i].mySeasonKey + "'); return false;\">" + this.mySeasons[i].mySeasonName + "</a>, ";
		}

		html = html.substr(0, html.length - 2);

		$("#playlistList").empty();
		$("#playlistList").append(html);
		
	} else
	{
		$("#playlistsTitle").empty();
		$("#playlistList").empty();
	}
	
	ensureTruncates();
} // END of addSeasons


VideoMenu.prototype.addVideos = function ( jsonData )
{
	
	var videoHash;
	var newVideoItem;
		
	// If there's a video in the hash, hashNavigation will take care of it. Make sure not to load another one.
	videoHash = myHash.get().getValue("v");
	if ( videoHash )
	{
		this.foundVideoToCue = true;
	}
	
	var myVideoData = eval ("(" + jsonData + ")");
	
	
	for ( var i in myVideoData )
	{


		oneVideo = myVideoData[i];

		newVideoItem = new VideoItem(oneVideo);

		this.myVideos.push( newVideoItem );

		// load featured video if found. If not, do nothing. makeDeck will play newest one.
		if ( !this.foundVideoToCue && this.myVideos[i].hasTag("featured") )
		{

			this.loadById(oneVideo.getId());
			this.myCurrentVideoId = oneVideo.getId();
			this.foundVideoToCue = true;

		}
		
	}
	
} // END of addVideos


/**
 * Creates a jagged array of VideoItems and Playlists.
 */
VideoMenu.prototype.makeDeck = function ()
{

	var foundExistingPlaylist;

	var onePlaylist;

	var oneVideo;

	// go through all videos
	for ( var i in this.myVideos )
	{

		oneVideo = this.myVideos[i];
		
		// if video belongs to playlist
		if ( oneVideo.getSeason() && !this.isTheme() )
		{

			foundExistingPlaylist = false;

			// see if playlist already exists
			for ( var i in this.myPlaylists )
			{

				// yes it does. Add video to playlist.
				onePlaylist = this.myPlaylists[i];
				if ( oneVideo.getSeason() == onePlaylist.getSeasonKey() )
				{

					onePlaylist.add (oneVideo);
					foundExistingPlaylist = true;
				}

			} // END of add it

			// if it wasn't found, make a new playlist
			if (!foundExistingPlaylist)
			{

				// go through known seasons
				for ( var i in this.mySeasons )
				{

					// When we find it. Create a new playlist with season information.
					oneSeason = this.mySeasons[i];
					if ( oneSeason.getKey() == oneVideo.getSeason())
					{

						// new playlist
						onePlaylist = new Playlist ( oneSeason );

						// add video to it
						onePlaylist.add ( oneVideo );

						// add to our array of playlists
						this.myPlaylists.push ( onePlaylist );

					}

				}

			} // END of make new

		} else
		// add solitary video to the deck
		{
			this.myDeck.push ( oneVideo );
		}
	
	}
		
	// Sort the individual playlists and add the playlists to the deck
	for ( var i in this.myPlaylists )
	{

		// Sort the array by date
		this.myPlaylists[i].sort(this.videosByDate);

		// Now sort them by episode number. If none are found then it will leave them by date.
		this.myPlaylists[i].sort(this.byEpisodeNumber);		
		
		// add to the deck
		this.myDeck.push(this.myPlaylists[i]);
		
	}
	
	// sort the whole deck
	this.myDeck.sort(this.videosByDate);
	
	// sort the whole deck by episode number
	this.myDeck.sort(this.byEpisodeNumber);		
	
	
	// If no video has been loaded, load the first one.
	if (!this.foundVideoToCue)
	{
		// make sure there's a first video
		if ( this.myDeck.length > 0 )
		{

			this.myDeck[0].load();
		} else
		// if theres no first video, then display pitiful message
		{
			// do nothing			
			$("#tab").empty();
			$("#selector > tab").append("<div>No videos.</div>");
			
		}

	}

} // END of makeDeck


/*
 * Accessors
 */


/**
 * Returns VideoItem containing specified ID.
 */
VideoMenu.prototype.getById = function ( aVideoId )
{


	for (var i in this.myVideos)
	{

		oneVideo = this.myVideos[i];

		if (oneVideo.getId() == aVideoId)
		{
			return oneVideo;
		}

	}

	return false;

} // END of getById()


/**
 * Returns the ID of the video currently loaded
 */
VideoMenu.prototype.getCurrentVideoId = function ()
{	
	return this.myCurrentVideoId;
}


/**
 * Returns true if the current series is a theme.
 */
VideoMenu.prototype.isTheme = function()
{
	return ( this.myType != "S" && this.myType != "F" );
}


/*
 * Sorts
 */


/** 
  * This is a sort function passed to Array.sort()
  */
VideoMenu.prototype.videosByDate = function(a, b)
{
	dA = a.getDate();
	dB = b.getDate();

	if (dA < dB)
	{
		result =  1;
	} else if (dA > dB)
	{
		result =  -1;
	} else
	{
		result = 0;
	}

	if (this.myType == "T")
	{ 
		result *= -1;
	}

	return result;
} // END of videosByDate


/** 
 * This is a sort function passed to Array.sort()
 */
VideoMenu.prototype.byEpisodeNumber = function(a, b)
{

	dA = parseInt(a.restOfTagStartingWith("e-"));
	dB = parseInt(b.restOfTagStartingWith("e-"));


	if (dA < dB)
	{
		result =  1;
	} else if (dA > dB)
	{
		result =  -1;
	} else
	{
		result = 0;
	}

	if (this.myType != "T")
	{ 
		result *= -1;
	}

	return result;

} // END of byEpisodeNumber


/*
 * Draws
 */


VideoMenu.prototype.draw = function()
{

	// remove whats there first
	this.myParentTag.empty();
	this.myParentTag.append("<div id=\"selectorTop\"></div>");

	// show the series of the episode for themes and on the homepage
	var showSeries = ( this.isTheme() || this.mySeriesKey == homePage );

	// go through whole deck and write them all to the video menu.	
	for ( var i in this.myDeck )
	{
		this.myParentTag.append ( this.myDeck[i].getHTML( showSeries ) );
	}

	ensureTruncates();

}


/**
 * Updates the episode title and description. 
 * Called by addPlayer in playercontrols.js
 * @param aVideoId a video id
 */
VideoMenu.prototype.updatePlayerTitleDescription = function ( aVideoItem )
{
	var title, description, showPage;

	title		= aVideoItem.getTitle();
	description = aVideoItem.getDescription();
	showPage	= (currentPage != homePage) ? currentPage : "New Videos";

	$("#episodeTitle").html(title);
	$("#episodeDescription").html(description);

	document.title = showPage + " | After Ed - New videos on education";

} // END of updatePlayerTitleDescription


/*
 * Player control
 */


/**
 * Searches the videos loaded in the menu and plays the one that matches the id specified. 
 * Will not play videos that aren't in the menu.
 */
VideoMenu.prototype.playById = function ( aVideoId )
{

	for (var i in this.myVideos)
	{

		oneVideo = this.myVideos[i];

		if (oneVideo.getId() == aVideoId)
		{
			this.myCurrentVideoId = aVideoId;
			oneVideo.play();
			this.myCurrentVideoId = oneVideo.getId();
		}

	}

} // END of playById()


/**
 * Searches the videos loaded in the menu and loads the one that matches the id specified. 
 * Will not load videos that aren't in the menu.
 */
VideoMenu.prototype.loadById = function ( aVideoId )
{

	for (var i in this.myVideos)
	{

		oneVideo = this.myVideos[i];

		if (oneVideo.getId() == aVideoId)
		{
			this.myCurrentVideoId = aVideoId;
			oneVideo.load();
			this.myCurrentVideoId = oneVideo.getId();

		}

	}

} // END of loadById()

