ytdj.tube = {
	
	STATE_UNDEFINED : -1,
	STATE_ENDED : 0,
	STATE_PLAYING : 1,
	STATE_PAUSED : 2,
	STATE_BUFFERING : 3,
	STATE_CUED : 5,
	
	CLIENT : "ytapi-MisterSpeaker-Turntubelist-04lnghcu-0",
	KEY : "AI39si51ao4LsZkjuTIQYuqOBI5SwcEm9CsCGYamfWhGtsQ2jtH0WtyTUcHaVtRgmA5gcpkynR0-SWkclA-8vL4BYt7SZTaoTg",
	
	GdataApiUrl : "http://gdata.youtube.com/feeds/api/videos/",
	YouTubeApiUrl : "http://www.youtube.com/apiplayer?",
	PlaylistApiUrl : "http://gdata.youtube.com/feeds/api/playlists/",
	// need to ad 8BCDD04DE8F771B2?v=2 for playlist
		
	loadTimeout : 20 * 1000,
	isLoadingPlaylist : false,
	playlistTimer : null,
	
	// Embed the YouTube video in the given channel
	embedTube : function( channel, vidId )
	{
		ytdj.getChannel(channel).loadVideoById(vidId, 1);
		if( pageTracker )
		{
			pageTracker._trackEvent( "YouTube", "Load", vidId );
		}
	},
	
	chromelessTube : function( channel )
	{
		var params = { allowScriptAccess: "always", wmode:"transparent",  bgcolor: "#f0c0f0" };
		var atts = { id: channel };
		swfobject.embedSWF("http://www.youtube.com/apiplayer?" + 
							"autoplay=1&" +
							"&enablejsapi=1&playerapiid=" + channel +
							ytdj.tube.getLicense(),
						   channel, "298", "224", "8", null, null, params, atts);	
	},
	
	// Toggle playing a video
	playVid : function( channel, playIt )
	{
		if( !ytdj.getChannel(channel).playVideo ) return;
		if( playIt )
		{		
			ytdj.getChannel(channel).playVideo();
		}
		else
		{
			ytdj.getChannel(channel).pauseVideo();
		}
	},
	
	playFromCue : function( seconds, channel )
	{
		if( isNaN( parseInt( seconds ) ) ) return;
		if( !ytdj.getChannel( channel ).seekTo ) return;
		
		ytdj.getChannel( channel ).seekTo( seconds, true );
	},
	
	toggleVid : function( channel )
	{
		//Returns the state of the player.
		var state = ytdj.getChannel( channel ).getPlayerState();
		
		switch(state)
		{
			case ytdj.tube.STATE_UNDEFINED:
			case ytdj.tube.STATE_PAUSED:
			case ytdj.tube.STATE_CUED:
				this.playVid( channel, ytdj.PLAY );
				return ytdj.PLAY;
				break;
			case ytdj.tube.STATE_PLAYING:
				this.playVid( channel, ytdj.PAUSE );
				return ytdj.PAUSE;
				break;		
		}
	},
		
	setVolume : function( channel, volume )
	{
		if( !ytdj.getChannel(channel).setVolume ) return;
		ytdj.getChannel(channel).setVolume( volume );
	},
	
	getVolume : function( channel )
	{
		if( !ytdj.getChannel(channel).getVolume ) return;
		return ytdj.getChannel(channel).getVolume();		
	},
	
	mute : function( channel, muted )
	{
		if( !ytdj.getChannel(channel).mute ) return;
		
		if(arguments.length == 1)
		{
			return ytdj.tube.isMuted( channel );
		}
		
		if( muted )
		{
			ytdj.getChannel(channel).mute()
		}
		else
		{
			ytdj.getChannel(channel).unMute();
		}
		
		return muted;
	},
	
	isMuted : function( channel )
	{
		if( !ytdj.getChannel(channel).isMuted ) return;
		return ytdj.getChannel( channel ).isMuted();
	},
	
	toggleMute : function( channel )
	{	
		ytdj.tube.mute( channel, ! ytdj.tube.isMuted( channel ) );
	},
	
	getCurrentTime : function( channel )
	{
		if( !ytdj.getChannel(channel).getCurrentTime ) return;
		return ytdj.getChannel( channel ).getCurrentTime();
	},
	
	getDuration : function( channel )
	{
		if( !ytdj.getChannel(channel).getDuration ) return;
		return ytdj.getChannel( channel ).getDuration();
	},
	
	getBytesLoaded : function( channel )
	{
		if( !ytdj.getChannel(channel).getVideoBytesLoaded ) return;
		return ytdj.getChannel( channel ).getVideoBytesLoaded();
	},

	getBytesTotal : function( channel )
	{
		if( !ytdj.getChannel(channel).getVideoBytesTotal ) return;
		return ytdj.getChannel( channel ).getVideoBytesTotal();
	},
	
	getStartBytes : function( channel )
	{
		if( !ytdj.getChannel(channel).getVideoStartBytes ) return;
		return ytdj.getChannel( channel ).getVideoStartBytes();
	},
	
	getState : function( channel )
	{
		if( !ytdj.getChannel(channel).getPlayerState ) return;
		return ytdj.getChannel( channel ).getPlayerState();
		// Possible values are unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5)
	},
	
	seekTo : function( channel, seconds )
	{
		ytdj.getChannel( channel ).seekTo( seconds, true );
	},
		
	getCurrentVidId : function( channel )
	{
		if( !ytdj.getChannel( channel ).getVideoEmbedCode ) return;
		return ytdj.getChannel(channel).getVideoEmbedCode();
	},
	
	getLicense : function()
	{
		return "";
		//return "&client=" + ytdj.tube.CLIENT + "&key=" + ytdj.tube.KEY;
	},
	
	testVid : function( vidId )
	{	
		$.getJSON( ytdj.tube.GdataApiUrl + vidId + "?alt=json-in-script&callback=?" + ytdj.tube.getLicense(),
		 	function( data )
			{
				if( data.entry.yt$noembed )
				{
					alert("this vid has been removed");
				}
			});
	},
	
	loadPlaylist : function( playlistId, callback_loading, callback_loaded  )
	{
		if( ytdj.tube.isLoadingPlaylist )
		{
			return;
		}
		callback_loading( "YouTube playlist" );
		
		var url = ytdj.tube.PlaylistApiUrl + playlistId + "?alt=json-in-script&v=2&callback=?";
		
		// Set timeout for request
		ytdj.tube.playlistTimer = setTimeout( function()
		{
			ytdj.tube.isLoadingPlaylist = false;
			callback_loaded( "", "timeout" );
		}, ytdj.tube.loadTimeout );
		ytdj.tube.isLoadingPlaylist = true;
		
		try{
	 		$.getJSON( url,
			 	function( data, status )
				{
					if( data == null || data.feed == null || data.feed.entry == null || data.feed.entry.length < 1 )
					{
						ytdj.tube.isLoadingPlaylist = false;
						callback_loaded( "", "error" );
						clearTimeout( ytdj.tube.playlistTimer );
						return;
					}
				
					//  check for call timed out
					if( ! ytdj.tube.isLoadingPlaylist )
					{
						return;
					}
				
					// Clear current playlists
					PlaylistController.emptyPlaylist( ytdj.LEFT );
					PlaylistController.emptyPlaylist( ytdj.RIGHT );
				
					$.each( data.feed.entry, function(index)
					{
						var chan = index % 2 == 0 ? ytdj.LEFT : ytdj.RIGHT;
						var video = ytdj.tube.getVideoObjectFromPlaylistEntry( this );
						
						PlaylistHelper.addTrack( chan, video.vidUrl, video.title.replace( "'", "" ), true );
					} );

					// Display the tracks
					PlaylistController.display( ytdj.LEFT );
					PlaylistController.display( ytdj.RIGHT );
				
					callback_loaded( data.feed.title.$t, "success" );
					clearTimeout( ytdj.tube.playlistTimer );
				});
			}
			catch(e)
			{
				ytdj.tube.isLoadingPlaylist = false;
				callback_loaded( "", "error" );
				clearTimeout( ytdj.tube.playlistTimer );
			}
		
	},
	
	// Retrieve's info from YouTube for a given video id, and fills the video box
	getVidInfo : function( channel, vidId, domContainer )
	{
		$.getJSON( ytdj.tube.GdataApiUrl + vidId + "?alt=json-in-script&callback=?" + ytdj.tube.getLicense(),
		 	function( data )
			{
				if( data.entry.yt$noembed )
				{
					return;
				}
				
				var thisTrack = PlaylistController.getTrackById( channel, vidId );
				var video = ytdj.tube.getVideoObjectFromEntry(data.entry);
				var videoTitle = thisTrack.name.length > 0 ? thisTrack.name : videoTitle;
				
				var videoThumbnail = $("<img/>").addClass("thumb").attr("src", video.thumbnailUrl).css("width","40px");
				var videoDescription = $("<p />").html(video.description.substring(0,100));
				var videoRating = $("<span />").addClass("star-rating").css("width", (video.stats.rating * ytdj.ui.STAR_PIXELS ) );
				var videoTime = $("<p />").addClass("duration").text(video.time);
				var videoMoreLink = $("<p><a href='http://www.youtube.com/watch?v=" + vidId + "' target='_blank'>YouTube page...</a></p>");
				var videoInfoArrow = $('<img src="images/dialog-arrow.png" />').addClass("arrow");
				var videoInfoClose = $('<span />').addClass("close").attr("title","Close").click( function() { 
					$(this).parents(".dialog").fadeOut(100);
					$(this).parents(".info-open").removeClass("info-open");
					PlaylistHelper.cancelOverlaysAndDragging();
				});
				
				videoInfoContainer = $("<div />");
				videoInfoArrow.appendTo( videoInfoContainer );
				videoInfoClose.appendTo( videoInfoContainer );
				$("<input type='text' />").addClass("title").val(videoTitle).appendTo( videoInfoContainer ).bind("blur", function()
					{
						// update track title
						thisTrack.name = $(this).val();
						PlaylistController.update();
					})
					.keypress( function(e){ e.stopPropagation(); }); // Stop event propagtion for keyboard shortucts 
					
				videoThumbnail.appendTo( videoInfoContainer );
				videoRating.appendTo( videoInfoContainer );
				videoTime.appendTo( videoInfoContainer );
				videoDescription.appendTo( videoInfoContainer );
				videoMoreLink.appendTo( videoInfoContainer );
				domContainer.html( videoInfoContainer ).fadeIn();
			});
	},
	
	// Do search for videos on YouTube - send results to listResults()
	searchForVids : function( searchTerms, pageNumber )
	{
		if(searchTerms.length == 0)
		{
			return;
		}
		
		$("#QuickSearch .button").val("Searching...").attr("disabled","disabled").fadeTo("slow", .5);
		
		if( pageTracker )
		{
			pageTracker._trackEvent( "YouTube", "Search", searchTerms );
		}

		$.ajax({ url: ytdj.tube.GdataApiUrl + "?vq=" + searchTerms 
			+ "&orderby=relevance&start-index=" + pageNumber 
			+ "&max-results=" + ytdj.SEARCH_RESULTS_PER_PAGE 
			+ "&alt=json-in-script&callback=?" +
			ytdj.tube.getLicense(),
			dataType : "json",
			success : function( data )
			{
				var feed = data.feed;
   				var entries = feed.entry || [];

				var foundResults = parseInt( feed.openSearch$totalResults.$t );
				var resultsPerPage = parseInt( feed.openSearch$itemsPerPage.$t );
				var totalPages = Math.round( foundResults / resultsPerPage );
				var currentPage = Math.round( feed.openSearch$startIndex.$t / resultsPerPage );
				var youTubeTitleLength = "YouTube Videos matching query:".length;
				var searchTerms = feed.title.$t.substr( youTubeTitleLength, feed.title.$t.length - youTubeTitleLength );
				
				// Clear the tube search box
				$( "#SearchResultItems" ).text("");

				// Set up paging
				$( "#SearchResults .summary" ).css("padding-top", "1.5em");
				$( "#SearchResultsFound" ).text( ytdj.helper.commarise(foundResults) + " video results found." );
				$( "#SearchResultsPaging" ).text("");

				var PagesToShow = 5;
				var leftOffset = totalPages - currentPage < PagesToShow ? PagesToShow - ( totalPages - currentPage ) : 0;

				var firstPage = currentPage <= ( PagesToShow + leftOffset ) ? 1 : currentPage - ( PagesToShow + leftOffset );
				var lastPage = firstPage + ( PagesToShow * 2 ) <= totalPages ? firstPage + ( PagesToShow * 2 ) : totalPages;

				if( firstPage > 1 )
				{
					// Add in previous
					ytdj.tube.addPagingDOMElement( 1, "<<", searchTerms, resultsPerPage, false );
					ytdj.tube.addPagingDOMElement( firstPage - 1, "<", searchTerms, resultsPerPage, false );
				}
				// Add in the middle pages
				for( var i = firstPage; i <= lastPage; i++)
				{
					ytdj.tube.addPagingDOMElement( i, i, searchTerms, resultsPerPage, i == (currentPage + 1) );
				}

				if( lastPage < totalPages)
				{
					// Add in the next
					ytdj.tube.addPagingDOMElement( lastPage + 1, ">", searchTerms, resultsPerPage, false );
					ytdj.tube.addPagingDOMElement( totalPages - 1, ">>", searchTerms, resultsPerPage, false );		
				}

				$( "#SearchResultsPaging li" ).wrapAll("<ul></ul>");
 
				// Add the found results to the search box
			    for (var i = 0; i < entries.length; i++) 
				{
					var video = ytdj.tube.getVideoObjectFromEntry( entries[i] );

					// Append DOM result to search box - this should be done in the view.
					ytdj.tube.createDOMResult( video ).appendTo( $( "#SearchResultItems" ) );
			    }
				$("#QuickSearch .button").val("Search").removeAttr("disabled").fadeTo("slow", 0.999);
				$( "#SearchResultItems li" ).wrapAll("<ul></ul>");
				$( "#SearchResultItems li:odd" ).addClass("alt");
			}
		});

		// TODO: very dodgy timeout: doesn't do anything to the actual request
		setTimeout(function(){$("#QuickSearch .button").val("Search").removeAttr("disabled").fadeTo("slow", 0.999);},7000);
	},
	
	getVideoObjectFromPlaylistEntry : function( entry )
	{
		var video = {}
		video.vidUrl = entry.link[0].href;
	  	video.title = entry.title.$t;
	
		return video;
	},
	
	getVideoObjectFromEntry : function( entry )
	{
		var video = {}
		video.vidUrl = entry.link[0].href;
	  	video.title = entry.title.$t;
		video.description = entry.content.$t;

		if(video.description.length > 500)
		{
			video.description = video.description.substring(0,500) + "...";
		}
      	video.thumbnailUrl = entry.media$group.media$thumbnail[0].url;

		// video duration
	  	video.duration = entry.media$group.yt$duration.seconds;
		video.minutes = parseInt( video.duration / 60 );
		video.seconds = video.duration % 60 < 10 ? "0" + video.duration % 60 : video.duration % 60;
		video.time = video.minutes + ":" + video.seconds;
		
		// Set up some stats for the vid
		video.stats = entry.yt$statistics || {};
		video.stats.viewCount = ytdj.helper.commarise(video.stats.viewCount);
		video.stats.numRaters = entry.gd$rating && entry.gd$rating.numRaters ? entry.gd$rating.numRaters : 0;
		video.stats.average = entry.gd$rating ? entry.gd$rating.average : 0;
		
		// Work out Star Rating
		var wholeRating = Math.floor( video.stats.average ); // Lets round this to .5...
		video.stats.rating = wholeRating + ( video.stats.average - wholeRating < 0.3 ? 0 : video.stats.average - wholeRating < 0.8 ? 0.5 : 1 );
		
		return video;
	},

	addPagingDOMElement : function( pageNumber, displayText, searchTerms, resultsPerPage, selected )
	{
		var pagingElement = $( "<li></li>" )
			.text( displayText )
			// .addClass( "PagingElement")
			.click( function(){ ytdj.tube.searchForVids( searchTerms, ( ( pageNumber - 1 ) * resultsPerPage ) + 1 ); } );

		// Add selected class to current page
		if( selected )
		{
			pagingElement.addClass( "selected" );
		}
		pagingElement.appendTo($( "#SearchResultsPaging" ));
	},
	
	// Create the Search result items.
	createDOMResult : function( video )
	{
		// Create the search result DOM elements
		var resultItem = $( "<li/>" ).addClass( "clearfix" );
		var resultImageContainer = $( "<div></div>" ).addClass( "SearchResultThumbContainer" );
		var resultImage = $( "<img/>" ).attr( "src", video.thumbnailUrl).addClass( "SearchResultThumb" );
		var resultInfo = $( "<div/>" ).addClass( "SearchResultInfo" );
		var resultTitle = $( "<p/>" ).text( video.title ).addClass( "SearchResultTitle" )
			.hover(function(){$(this).css('cursor','pointer')},function(){$(this).css('cursor','')})
			.click(function()
			{
				// TODO: i think we need to add to playlist on click... but might need
				// and fix mouse over if it stays!
				PlaylistHelper.addTrack( ytdj.LEFT, video.vidUrl, video.title.replace("'","") );
				PlaylistController.update();
				$(this).parents("li").effect( "highlight", { color: "#6d787d" },  3000);
				$(this).parents("li").find(".SearchResultAddToPlaylist h3").text("Track added to playlist 1");
			
			});
		var resultDescription = $( "<p/>" ).text( video.description ).addClass( "SearchResultDescription" );
		var resultDuration = $( "<p/>" ).text(video.time).addClass( "SearchResultDuration" );
		
		// Adding in the VIEWS and RATING
		var resultRating = $("<p/>").addClass("star-rating").css("width", (video.stats.rating * ytdj.ui.STAR_PIXELS ) );
		var resultViews = $("<p/>").addClass("views").text( video.stats.viewCount + " views");
		
		var resultAddToPlaylist = $( "<div><h3>Add to playlist: </h3></div>" ).addClass( "SearchResultAddToPlaylist" );
		var resultAddTo1 = $( "<span/>" ).text( "1" ).addClass( "AddToPlaylist" ).attr( "title","Add video to playlist 1" )
								.click( function()
								{ 
									// Add the track to the left playlist
									PlaylistHelper.addTrack( ytdj.LEFT, video.vidUrl, video.title.replace("'","") );

									// TODO: what was i doing here? 
									//ytdj.tube.testVid( video.vidUrl.replace("http://www.youtube.com/watch?v=","") );
									ytdj.helper.log([video.vidUrl]);
									
									PlaylistController.update();
									$(this).parents("li").effect( "highlight", { color: "#6d787d" },  3000);
									$(this).parents("li").find(".SearchResultAddToPlaylist h3").text("Track added to playlist 1");
								});

		var resultAddTo2 = $( "<span/>" ).text( "2" ).addClass( "AddToPlaylist" ).attr("title","Add video to playlist 2")
								.click( function()
								{
									// Add the track to the right playlist
									PlaylistHelper.addTrack( ytdj.RIGHT, video.vidUrl, video.title.replace("'","") );
									
									ytdj.helper.log([video.vidUrl]);
									
									PlaylistController.update();
									$(this).parents("li").effect( "highlight", { color: "#6d787d" },  3000);
									$(this).parents("li").find(".SearchResultAddToPlaylist h3").text("Track added to playlist 2");
								});
		
		// Add them to the result div 
		resultImageContainer.appendTo( resultItem );		
		resultImage.appendTo( resultImageContainer );		
		resultInfo.appendTo( resultItem );
		resultTitle.appendTo( resultInfo );
		resultDescription.appendTo( resultInfo );
		resultDuration.appendTo( resultInfo );
		resultRating.appendTo( resultInfo );
		resultViews.appendTo( resultInfo );
		resultAddTo1.appendTo( resultAddToPlaylist );
		resultAddTo2.appendTo( resultAddToPlaylist );
		resultAddToPlaylist.appendTo( resultItem ).clone(true).appendTo(resultImageContainer);
			
		return resultItem;
	}
}

