// ************************************************************************************************
// *** Constructs a player object that wraps the Windows Media player
// ************************************************************************************************

function PlayerSilverlight(objName, playerObject) {
	// ************************************************************************************************
	// *** Interface
	// ************************************************************************************************
	
	// Control methods
	this.getCurrentMediaDuration = sl_GetCurrentMediaDuration;
	this.getPosition = sl_GetPosition;
	this.setPosition = sl_SetPosition;

	this.next = sl_Next;
	this.pause = sl_Pause;
	this.play = sl_Play;
	this.playItem = sl_PlayItem;
	this.playForcedIndex = sl_PlayForcedIndex;
	this.playUrl = sl_PlayUrl;
	this.previous = sl_Previous;
	this.stop = sl_Stop;
	this.fastForward = sl_FastForward;
	this.rewind = sl_Rewind;
		
	// Settings methods
	this.getMute = sl_GetMute;
	this.setMute = sl_SetMute;	
	this.getRepeat = sl_GetRepeat;
	this.setRepeat = sl_SetRepeat;

	this.getVolume = sl_GetVolume;
	this.setVolume = sl_SetVolume;
	
	// Media quality methods
	this.getQuality = sl_GetQuality;
	this.setQuality = sl_SetQuality;
	
	// Playlist related methods
	this.getCurrentPlaylist = sl_GetCurrentPlaylist;
	this.setCurrentPlaylist = sl_SetCurrentPlaylist;
	
	// Play state
	this.getPlayState = sl_GetPlayState;
	
	// Player general methods
	this.getCurrentMedia = sl_GetCurrentMedia;
	this.getStatus = sl_GetStatus;
	this.fullScreen = sl_FullScreen;
	this.resize = sl_Resize;
	
	// Events
	this.onCurrentMediaChange = new EventManager(); // Occurs when the current media changes
	this.onCurrentPositionChange = new EventManager(); // Occurs when the current position in the media item changes
	this.onMuteChange = new EventManager(); // Occurs when the mute state changes
	this.onPlayerStateStringChange = new EventManager(); // Occurs when the player state string changes	
	this.onPlayStateChange = new EventManager(); // Occurs when the play state changes

	// ************************************************************************************************
	// *** Implementation
	// ************************************************************************************************
	
	// Fields
	// ******
	this.currentPlaylist = null;	
	this.objName = objName;
	this.playerObject = playerObject;
	this.playState = new PlayState();
	this.quality = new Quality().low;
	this.repeat = false;
	
	// Tick fields
	this.lastCurrentPosition = 0;
	this.lastMediaUrl = '';
	this.lastMute = false;
	this.lastPlayState = this.playState.undefined;
	this.lastStateStr = '';	
	
	// Methods
	// *******
	this.sync = sl_Sync;
	this.createInternalPlaylist = sl_CreateInternalPlaylist;
	this.getCurrentPlaySequenceIndex = sl_GetCurrentPlaySequenceIndex;
	this.getCurrentIndex = sl_GetCurrentIndex;
	this.tick = sl_Tick;
	this.getMediaObject = sl_GetMediaObject;
	this.mediaEnd = sl_MediaEnd;
	this.next = sl_Next;
	
	// Create internal playlist
	this.createInternalPlaylist();
	
	// Differentiates manual stop from natural stop
	this.manualStop = true;
	
	// Start tick
	setTimeout(this.objName +'.tick();', 999);
	
	// Control methods implementation 
	// ******************************
	function sl_Next()
	{
		var cIndex = this.getCurrentIndex();
		if(cIndex < this.currentPlaylist.count()-1)
		{
			if(this.getCurrentMedia().isAd)
			{
				this.playItem(cIndex);
			}
			else
			{
				this.playItem(cIndex + 1);
			}
		}
		else
		{
			// Loops around
			this.playForcedIndex(0);
		}
	}
	
	function sl_MediaEnd()
	{
		var currentMedia = this.getCurrentMedia();
		var currentMediaUrl = currentMedia != null ? currentMedia.mediaUrls[this.quality] : '';

		// Detects change and manually sets the next media
		try
		{
			var playSequence = this.currentPlaylist.getPlaySequence();
			var currentIndex = this.getCurrentPlaySequenceIndex();
				
			// Goes to the next playlist index
			if(playSequence!=null)
			{
				//alert(currentIndex);
				if(currentIndex < playSequence.length - 1)
				{
					var iURL = playSequence[currentIndex+1].mediaUrls[this.quality];
					this.getMediaObject().Source = iURL;
					this.getMediaObject().Play();
				}
				else 
				{
					if(this.repeat)
					{
						this.playForcedIndex(0);
					}
					else
					{
						this.manualStop = true;
					}
				}
			}
		}
		catch(e){}
		
		this.onCurrentMediaChange.exec();
		this.lastMediaUrl = currentMediaUrl;
	}
	
	function sl_GetMediaObject()
	{
		return this.playerObject.Content.findName("media");
	}
	
	// Pauses the playing of media item
	function sl_Pause() {
		this.getMediaObject().Pause();
	}
	
	// Plays the current media item
	function sl_Play()
	{		
		this.getMediaObject().Play();
		this.currentPlayState = this.playState.playing;
	}
	
	function sl_PlayItem(index, wait)
	{
		if(this.currentPlaylist.count() > 0 && index < this.currentPlaylist.count())
		{
			// Gets the play sequence
			var playSequence = this.currentPlaylist.getPlaySequence();

			// Get the play sequence index for the requested index
			var psIndex = this.currentPlaylist.getPlaySequenceIndex(index);
			
			// Plays the item
			this.getMediaObject().Source = playSequence[psIndex].mediaUrls[this.quality];
			this.getMediaObject().Play();
			
			this.manualStop = false;
			this.onCurrentMediaChange.exec();
		}
	}
	function sl_PlayForcedIndex(index)
	{
		if(this.currentPlaylist.count() > 0 && index < this.currentPlaylist.count())
		{
			// Gets the play sequence
			var playSequence = this.currentPlaylist.getPlaySequence();

			// Get the play sequence index for the requested index
			var psIndex = this.currentPlaylist.getPlayIndex(index);
					
			// Plays the item
			this.getMediaObject().Source = playSequence[psIndex].mediaUrls[this.quality];
			
			this.getMediaObject().Play();
			
			this.manualStop = false;
			this.currentPlayState = this.playState.playing;
			
			this.onCurrentMediaChange.exec();
		}
	}
	
	// Plays the specified url
	function sl_PlayUrl(url)
	{
		this.getMediaObject().Source = url;
		this.getMediaObject().Play();
		
		this.manualStop = false;
	}

	// Sets the current item to the previous in the playlist
	function sl_Previous() {
		if(this.getCurrentIndex()>0)
		{
			this.playItem(this.getCurrentIndex()-1);
		}
		else
		{
			// Loops around
			this.playItem(this.currentPlaylist.count()-1);			
		}
	}
	
	// Stops the playing of media item
	function sl_Stop() {
		this.getMediaObject().Stop();
		this.manualStop = true;
	}
	
	// Fast forwards the playing of media item
	function sl_FastForward() {
		// Not supported
	}
	
	// Rewinds the playing of media item
	function sl_Rewind() {
		// Not supported
	}
	
	// Returns the duration (in seconds) of the current media
	function sl_GetCurrentMediaDuration() {
		if(this.playerObject && this.getMediaObject() && this.getMediaObject().NaturalDuration)
		{
			return(this.getMediaObject().NaturalDuration.Seconds);
		}
			
		return(0);
	}
	
	// Gets the current position in the media item in seconds from the beginning
	function sl_GetPosition()
	{
		if(this.playerObject)
			return(this.getMediaObject().Position.Seconds);
			
		return(0);
	}
	
	// Sets the current position in the media item in seconds from de beginning
	function sl_SetPosition(position) {
		if(this.playerObject)
		{
			var pos = this.getMediaObject().Position;
			pos.Seconds = position;
			this.getMediaObject().Position = pos;
		}
	}
	
	// Settings methods implementation
	// *******************************
	
	// Sets the player volume
	function sl_SetVolume(val)
	{
		this.getMediaObject().Volume = val / 100;
	}
	
	// Retrieves the player volume
	function sl_GetVolume() 
	{
		return this.getMediaObject().Volume * 100;
	}
	
	// Sets the player's mute state
	function sl_SetMute(mute) 
	{
		try
		{
			this.getMediaObject().IsMuted = mute;
		}
		catch(e){}
	}
	
	// Gets the player's mute state
	function sl_GetMute() 
	{
		return this.getMediaObject().IsMuted;
	}
	
	// Gets the repeat flag
	function sl_GetRepeat() 
	{
		return(this.repeat);
	}
	
	// Sets the repeat flag
	function sl_SetRepeat(state) 
	{
		this.repeat = state;
	}
	
	// Playlist related methods implementation
	// ***************************************

	// Gets the current player's playlist
	function sl_GetCurrentPlaylist() {
		return(this.currentPlaylist);
	}
	
	// Sets the current player's playlist
	function sl_SetCurrentPlaylist(playlist) {
		this.currentPlaylist = playlist;
	}
	
	// Syncronize external and internal playlist
	function sl_Sync() {
		// Windows-media compatibility only
	}
	
	// Media quality methods
	// *********************
	
	// Get the current media quality
	function sl_GetQuality() {
		return this.quality;
	}

	// Set the current media quality	
	function sl_SetQuality(quality) {
		this.quality = quality;
	}
	
	// Play state
	// **********
	
	// Gets the play state
	function sl_GetPlayState() {
		
		var playerState;
		
		// Get the play state from player object
		playerState = (this.playerObject && this.getMediaObject()) ? this.getMediaObject().CurrentState.toString() : 0;
		
		switch(playerState) {
			case "Stopped":
				return this.playState.stopped;
			case "Opening":
			case "Buffering":
				return this.playState.buffering;
			case "Playing":
				return this.playState.playing;
			case "Paused":
				return this.playState.paused;
			case "Buffering":
				return this.playState.buffering;
			default :
				return this.playState.undefined;
		}
	}

	// General methods implementation
	// *******************************
	
	// Gets the current media item
	function sl_GetCurrentMedia()
	{
		if(this.currentPlaylist == null)
			return null;
			
		var playSequence = this.currentPlaylist.getPlaySequence();
		var index = this.getCurrentPlaySequenceIndex();
		
		return (index >= 0) ? playSequence[index] : null;
	}
	
	// Gets the status string from player
	function sl_GetStatus() {
		return this.getPlayState();
	}
	
	// Puts the player in full screen mode
	function sl_FullScreen()
	{
		toggle_fullScreen();
	}	

	// Resizes the player
	function sl_Resize(width, height)
	{
		this.playerObject.width = width;
		this.playerObject.height = height;
		
		this.getMediaObject().Width = width;
		this.getMediaObject().Height = height;
	}	
	
	// Creates the internal playlist
	function sl_CreateInternalPlaylist() {
		// Windows-media compatibility only
	}
	
	// Returns the index of current media item index (not play sequence) (-1 if it is not found)
	function sl_GetCurrentIndex() {

		// Determine the current index
		for(var i = 0; i < this.currentPlaylist.mediaItems.length; i++)
		{
			// Strips protocol information
			var url = this.currentPlaylist.mediaItems[i].mediaUrls[this.quality];
			url = url.substring(url.indexOf("://") + 3);

			if(this.getMediaObject().Source.indexOf(url)>0)
			{
				return i;
			}
			else
			{
				for(var j = 0; j < this.currentPlaylist.mediaItems[i].ads.length;j++)
				{
					// Strips protocol information
					var urlAd = this.currentPlaylist.mediaItems[i].ads[j].mediaUrls[this.quality];
					urlAd = urlAd.substring(urlAd.indexOf("://") + 3);
					if(this.getMediaObject().Source.indexOf(urlAd)>0)
					{
						return i;
					}
				}
			}
		}
		
		return -1;
	}

	// Returns the index of current media item index (play sequence) (-1 if it is not found)
	function sl_GetCurrentPlaySequenceIndex()
	{
		var playSequence = this.currentPlaylist.getPlaySequence();

		// Determine the current index
		if(playSequence!=null)
		{
			for(i = 0; i < playSequence.length; i++)
			{
				// Must strip url from protocol to allow comparison
				var url = playSequence[i].mediaUrls[this.quality];
				url = url.substring(url.indexOf("://") + 3);
				var playerUrl = this.getMediaObject().Source;
				
				if(this.getMediaObject() && playerUrl.indexOf(url) > 0)
				{
					return i;
				}
			}
		}
		
		return -1;
	}
	
	// Function to check for changes in the player state
	function sl_Tick()
	{
		// Current position
		if(this.lastCurrentPosition != this.getPosition())
		{
			this.onCurrentPositionChange.exec()			
			this.lastCurrentPosition = this.getPosition();
		}
		setTimeout(this.objName +'.tick();', 1000);
	}
}