// ************************************************************************************************
// *** Constructs a player object that wraps the Windows Media player
// ************************************************************************************************

function PlayerReal(objName, playerObject) {
	// ************************************************************************************************
	// *** Interface
	// ************************************************************************************************
	
	// Control methods
	this.getCurrentMediaDuration = rm_GetCurrentMediaDuration;
	this.getPosition = rm_GetPosition;
	this.setPosition = rm_SetPosition;

	this.next = rm_Next;
	this.pause = rm_Pause;
	this.play = rm_Play;
	this.playItem = rm_PlayItem;
	this.playForcedIndex = rm_PlayForcedIndex;
	this.playUrl = rm_PlayUrl;
	this.previous = rm_Previous;
	this.stop = rm_Stop;
	this.fastForward = rm_FastForward;
	this.rewind = rm_Rewind;
		
	// Settings methods
	this.getMute = rm_GetMute;
	this.setMute = rm_SetMute;	
	this.getRepeat = rm_GetRepeat;
	this.setRepeat = rm_SetRepeat;

	this.getVolume = rm_GetVolume;
	this.setVolume = rm_SetVolume;
	
	// Media quality methods
	this.getQuality = rm_GetQuality;
	this.setQuality = rm_SetQuality;
	
	// Playlist related methods
	this.getCurrentPlaylist = rm_GetCurrentPlaylist;
	this.setCurrentPlaylist = rm_SetCurrentPlaylist;
	
	// Play state
	this.getPlayState = rm_GetPlayState;
	
	// Player general methods
	this.getCurrentMedia = rm_GetCurrentMedia;
	this.getStatus = rm_GetStatus;
	this.fullScreen = rm_FullScreen;
	this.resize = rm_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 = rm_Sync;
	this.createInternalPlaylist = rm_CreateInternalPlaylist;
	this.getCurrentPlaySequenceIndex = rm_GetCurrentPlaySequenceIndex;
	this.getCurrentIndex = rm_GetCurrentIndex;
	this.tick = rm_Tick;
	
	// Create internal playlist
	this.createInternalPlaylist();
	
	// Differentiates manual stop from natural stop
	this.manualStop = true;
	
	// Start tick
	setTimeout(this.objName +'.tick();', 500);
	
	// Control methods implementation 
	// ******************************
	
	// Sets the current item to the next item in the playlist
	function rm_Next() {
		if(this.getCurrentIndex()<this.currentPlaylist.count()-1)
		{
			this.playItem(this.getCurrentIndex()+1);
		}
		else
		{
			// Loops around
			this.playItem(0);
		}
	}	
	
	// Pauses the playing of media item
	function rm_Pause() {
		this.playerObject.DoPause();
	}
	
	// Plays the current media item
	function rm_Play() {
		if(this.getPlayState()!=this.playState.paused && this.getPlayState()!=this.playState.playing)
		{
			// Starting
			this.playItem(0);
		}
		else
		{
			// Resuming
			this.playerObject.DoPlay();
		}
	}
	
	// Plays the specified media item
	function rm_PlayItem(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.getPlaySequenceIndex(index);
			
			// Plays the item
			this.playerObject.SetSource(playSequence[psIndex].mediaUrls[this.quality]);
			this.playerObject.DoPlay();
			
			this.manualStop = false;
		}
	}
	function rm_PlayForcedIndex(index)
	{
		if(this.currentPlaylist.count() > 0 && index < this.currentPlaylist.count())
		{			
			// Plays the item
			this.playerObject.SetSource(this.currentPlaylist[psIndex].mediaUrls[this.quality]);
			this.playerObject.DoPlay();
			
			this.manualStop = false;
		}
	}
	
	// Plays the specified url
	function rm_PlayUrl(url) {
		// Do NOT use this when working with playlists

		// Plays the item
		this.playerObject.SetSource(url);
		this.playerObject.DoPlay();
		
		this.manualStop = false;
	}

	// Sets the current item to the previous in the playlist
	function rm_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 rm_Stop() {
		this.playerObject.DoStop();
		this.manualStop = true;
	}
	
	// Fast forwards the playing of media item
	function rm_FastForward() {
		// Not supported
	}
	
	// Rewinds the playing of media item
	function rm_Rewind() {
		// Not supported
	}
	
	// Returns the duration (in seconds) of the current media
	function rm_GetCurrentMediaDuration() {
		if(this.playerObject)
			return(this.playerObject.GetLength()/1000);
			
		return(0);
	}
	
	// Gets the current position in the media item in seconds from the beginning
	function rm_GetPosition() {
		if(this.playerObject)
			return(this.playerObject.GetPosition()/1000);
			
		return(0);
	}
	
	// Sets the current position in the media item in seconds from de beginning
	function rm_SetPosition(position) {
		if(this.playerObject)
			this.playerObject.SetPosition(position*1000);
	}
	
	// Settings methods implementation
	// *******************************
	
	// Sets the player volume
	function rm_SetVolume(val)
	{
		this.playerObject.SetVolume(val);
	}
	
	// Retrieves the player volume
	function rm_GetVolume() 
	{
		return this.playerObject.GetVolume();
	}
	
	// Sets the player's mute state
	function rm_SetMute(mute) 
	{
		this.playerObject.SetMute(mute);
	}
	
	// Gets the player's mute state
	function rm_GetMute() 
	{
		return this.playerObject.GetMute();
	}
	
	// Gets the repeat flag
	function rm_GetRepeat() 
	{
		return(this.repeat);
	}
	
	// Sets the repeat flag
	function rm_SetRepeat(state) 
	{
		this.repeat = state;
	}
	
	// Playlist related methods implementation
	// ***************************************

	// Gets the current player's playlist
	function rm_GetCurrentPlaylist() {
		return(this.currentPlaylist);
	}
	
	// Sets the current player's playlist
	function rm_SetCurrentPlaylist(playlist) {
		this.currentPlaylist = playlist;
	}
	
	// Syncronize external and internal playlist
	function rm_Sync() {
		// Windows-media compatibility only
	}
	
	// Media quality methods
	// *********************
	
	// Get the current media quality
	function rm_GetQuality() {
		return this.quality;
	}

	// Set the current media quality	
	function rm_SetQuality(quality) {
		this.quality = quality;
	}
	
	// Play state
	// **********
	
	// Gets the play state
	function rm_GetPlayState() {
		var playerState;
		
		// Get the play state from player object
		playerState = (this.playerObject) ? this.playerObject.GetPlayState() : 0;
		
		switch(playerState) {
			case 0: // Stopped
				return this.playState.stopped;
			case 1: // Contacting
			case 2: // Buffering
			case 5: // Seeking
				return this.playState.buffering;
			case 3: // Playing
				return this.playState.playing;
			case 4: // Paused
				return this.playState.paused;
			default :
				return this.playState.undefined;
		}
	}

	// General methods implementation
	// *******************************
	
	// Gets the current media item
	function rm_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 rm_GetStatus() {
		var status = '';
		try
		{
			status = this.playerObject.GetLastStatus();
		}
		catch(e){}
		return(status);
	}
	
	// Puts the player in full screen mode
	function rm_FullScreen() {
		this.playerObject.SetFullScreen();
	}	

	// Resizes the player
	function rm_Resize(width, height) {
		this.playerObject.width = width;
		this.playerObject.height = height;
	}	
	
	// Creates the internal playlist
	function rm_CreateInternalPlaylist() {
		// Windows-media compatibility only
	}
	
	// Returns the index of current media item index (not play sequence) (-1 if it is not found)
	function rm_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.playerObject.GetSource().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.playerObject.GetSource().indexOf(urlAd)>0)
					{
						return i;
					}
				}
			}
		}
		
		return -1;
	}

	// Returns the index of current media item index (play sequence) (-1 if it is not found)
	function rm_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);
				
				if(this.playerObject.GetSource().indexOf(url)>0)
					return i;
			}
		}
		
		return -1;
	}
	
	// Function to check for changes in the player state
	function rm_Tick() {
		var currentMedia = this.getCurrentMedia();
		var currentMediaUrl = currentMedia != null ? currentMedia.mediaUrls[this.quality] : '';

		// Detects change and manually sets the next media
		if(this.getPlayState()==this.playState.stopped && !this.manualStop)
		{
			var playSequence = this.currentPlaylist.getPlaySequence();
			var currentIndex = this.getCurrentPlaySequenceIndex();

			// Goes to the next playlist index
			if(playSequence!=null)
			{
				if(currentIndex<playSequence.length-1)
				{
					this.playerObject.SetSource(playSequence[currentIndex+1].mediaUrls[this.quality]);
					this.playerObject.DoPlay();
				}
				else
				{
					if(this.repeat)
					{
						this.playItem(0);
					}
					else
					{
						this.manualStop = true;
					}
				}
			}
		}
		
		// State string
		if(this.playerObject)
		{
			if(this.getStatus() != this.lastStateStr) {
				// Trigger event
				this.onPlayerStateStringChange.exec();
				
				this.lastStateStr = this.getStatus();
			}
		}
		
		// Media change
		if(currentMediaUrl != this.lastMediaUrl) {
			this.onCurrentMediaChange.exec();
		
			this.lastMediaUrl = currentMediaUrl;
		}
		
		// Current position
		if(this.lastCurrentPosition != this.getPosition()) {
			this.onCurrentPositionChange.exec()
			
			this.lastCurrentPosition = this.getPosition();
		}
		
		// Mute change
		if(this.lastMute != this.getMute()) {
			this.onMuteChange.exec();
			
			this.lastMute = this.getMute();
		}
		
		// Play state change
		if(this.lastPlayState != this.getPlayState()) {
			this.onPlayStateChange.exec();
			
			this.lastPlayState = this.getPlayState();
		}
		
		setTimeout(this.objName +'.tick();', 500);
	}
}