// ************************************************************************************************
// *** Constructs a player object that wraps the Windows Media player
// ************************************************************************************************

function PlayerWm(objName, playerObject) {
	// ************************************************************************************************
	// *** Interface
	// ************************************************************************************************
	
	// Control methods
	this.getCurrentMediaDuration = wm_GetCurrentMediaDuration;
	this.getPosition = wm_GetPosition;
	this.setPosition = wm_SetPosition;

	this.next = wm_Next;
	this.pause = wm_Pause;
	this.play = wm_Play;
	this.playItem = wm_PlayItem;
	this.previous = wm_Previous;
	this.stop = wm_Stop;
	
	// Settings methods
	this.getMute = wm_GetMute;
	this.setMute = wm_SetMute;	
	this.getRepeat = wm_GetRepeat;
	this.setRepeat = wm_SetRepeat;

	this.getVolume = wm_GetVolume;
	this.setVolume = wm_SetVolume;
	
	// Media quality methods
	this.getQuality = wm_GetQuality;
	this.setQuality = wm_SetQuality;
	
	// Playlist related methods
	this.getCurrentPlaylist = wm_GetCurrentPlaylist;
	this.setCurrentPlaylist = wm_SetCurrentPlaylist;
	
	// Play state
	this.getPlayState = wm_GetPlayState;
	
	// Player general methods
	this.getCurrentMedia = wm_GetCurrentMedia;
	this.getStatus = wm_GetStatus;
	this.fullScreen = wm_FullScreen;
	
	// 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.usePlaylist = false;
	
	// Tick fields
	this.lastCurrentPosition = 0;
	this.lastMediaUrl = '';
	this.lastMute = false;
	this.lastPlayState = this.playState.undefined;
	this.lastStateStr = '';	
	
	// Methods
	// *******
	this.sync = wm_Sync;
	this.createInternalPlaylist = wm_CreateInternalPlaylist;
	this.getCurrentPlaySequenceIndex = wm_GetCurrentPlaySequenceIndex;
	this.tick = wm_Tick;
	
	// Create internal playlist
	this.createInternalPlaylist();
	
	// Start tick
	setTimeout(this.objName +'.tick();', 500);
	
	// Control methods implementation 
	// ******************************
	
	// Sets the current item to the next item in the playlist
	function wm_Next() {
		if(this.usePlaylist)
		{
			if(this.playerObject)
			{
				if(this.playerObject.controls)
				{
					this.playerObject.controls.next();
				}
			}
		}
	}	
	
	// Pauses the playing of media item
	function wm_Pause() {
		if(this.playerObject)
		{
			if(this.playerObject.controls)
			{
				this.playerObject.controls.pause();
			}
		}
	}
	
	// Plays the current media item
	function wm_Play() {
		if(this.playerObject)
		{
			if(this.playerObject.controls)
			{
				this.playerObject.controls.play();
			}
		}
	}
	
	// Plays the specified media item
	function wm_PlayItem(index) {
		var psIndex;
		
		// Get the play sequence index from playlist index
		psIndex = this.currentPlaylist.getPlaySequenceIndex(index);
		
		if(this.usePlaylist)
			this.playerObject.controls.playItem(this.playerObject.currentPlaylist.item(psIndex));
	}
	
	// Sets the current item to the previous in the playlist
	function wm_Previous() {
		if(this.usePlaylist)
		{
			if(this.playerObject)
			{
				if(this.playerObject.controls)
				{
					this.playerObject.controls.previous();
				}
			}
		}
	}
	
	// Stops the playing of media item
	function wm_Stop() {
		if(this.playerObject)
		{
			if(this.playerObject.controls)
			{
				this.playerObject.controls.stop();
			}
		}
	}
	
	// Returns the duration (in seconds) of the current media
	function wm_GetCurrentMediaDuration() {
		if(this.playerObject.currentMedia != null)
			return this.playerObject.currentMedia.duration;
		else
			return 0;
	}
	
	// Gets the current position in the media item in seconds from the beginning
	function wm_GetPosition() {
		if(this.playerObject)
			if(this.playerObject.controls)
				return parseInt(this.playerObject.controls.currentPosition);
		else
			return 0;
	}
	
	// Sets the current position in the media item in seconds from de beginning
	function wm_SetPosition(position) {
		if(this.playerObject)
		{
			if(this.playerObject.controls)
			{
				this.playerObject.controls.currentPosition = position;
			}
		}
	}
	
	// Settings methods implementation
	// *******************************
	
	// Sets the player volume
	function wm_SetVolume(val)
	{
		if(this.playerObject.settings)
		{
			this.playerObject.settings.volume = val;
		}
	}
	
	// Retrieves the player volume
	function wm_GetVolume() {
		if(this.playerObject.settings)
		{
			return this.playerObject.settings.volume;
		}
	}
	
	// Sets the player's mute state
	function wm_SetMute(mute) {
		if(this.playerObject.settings)
		{
			this.playerObject.settings.mute = mute;
		}
	}
	
	// Gets the player's mute state
	function wm_GetMute() {
		if(this.playerObject.settings)
		{
			return this.playerObject.settings.mute;
		}
	}
	
	// Sets the repeat flag
	function wm_GetRepeat() {
		if(player.oPlayer.UsePlayList)
			player.oPlayer.player_obj.settings.setMode('loop', bPlayListRepeat);
	}
	
	// Gets thr repeat flag
	function wm_SetRepeat() {
		if(player.oPlayer.UsePlayList)
			player.oPlayer.player_obj.settings.setMode('loop', bPlayListRepeat);
	}

	
	// Playlist related methods implementation
	// ***************************************

	// Gets the current player's playlist
	function wm_GetCurrentPlaylist() {
		return this.currentPlaylist;
	}
	
	// Sets the current player's playlist
	function wm_SetCurrentPlaylist(playlist) {
		this.currentPlaylist = playlist;
		
		// Register onChange playlist event
		this.currentPlaylist.onChange.add(this.objName, 'sync');
		
		// Forces a sync
		this.sync();
	}
	
	// Syncronize external and internal playlist
	function wm_Sync() {
		var i, seqIndex;
		var media_item, currentPlaylist = this.playerObject.currentPlaylist;
		var playSequence = this.currentPlaylist.getPlaySequence();

		if(playSequence!=null)
		{
			if(!this.usePlaylist) // If player does not use playlist, do nothing
				return;

			seqIndex = this.getCurrentPlaySequenceIndex();

			// Drop all internal playlist items but the current
			i = 0;
			while(i < currentPlaylist.count) {
				if(!currentPlaylist.item(i).isIdentical(this.playerObject.currentMedia) || seqIndex == -1) // If it is not the current, drop it
					currentPlaylist.removeItem(currentPlaylist.item(i));
				else // If it is the current, go to the next item
					i++;
			}

			// Add items into internal playlist
			for(i = 0; i < playSequence.length; i++) {
				if(i == seqIndex)
					continue;

				currentPlaylist.insertItem(i, this.playerObject.newMedia(playSequence[i].mediaUrls[this.quality]));
			}
		}
	}
	
	// Media quality methods
	// *********************
	
	// Get the current media quality
	function wm_GetQuality() {
		return this.quality;
	}

	// Set the current media quality	
	function wm_SetQuality(quality) {
		this.quality = quality;
		if (this.currentPlaylist)
			this.sync();
	}
	
	// Play state
	// **********
	
	// Gets the play state
	function wm_GetPlayState() {
		var playerState;
		
		// Get the play state from player object
		playerState = (this.playerObject) ? this.playerObject.playState : 0;
		
		switch(playerState) {
			case 1 : // Stopped
			case 10 : // Ready
				return this.playState.stopped;
			case 2 : // Paused
				return this.playState.paused;
			case 7 : // Waiting
				this.next(); // End of live, go to next and return 'playing'
			case 3 : // Playing
			case 4 : // ScanForward
			case 5 : // ScanReverse
			case 6 : // Buffering
			case 8 : // MediaEnded
			case 9 : // Transitioning
			case 11 : // Reconnecting
				return this.playState.playing;
			default :
				return this.playState.undefined;
		}
	}

	// General methods implementation
	// *******************************
	
	// Gets the current media item
	function wm_GetCurrentMedia() {
		var currentPlaylist = this.currentPlaylist;
		
		if(currentPlaylist == null)
			return null;
			
		var playSequence = currentPlaylist.getPlaySequence();
		var index = this.getCurrentPlaySequenceIndex();
		
		return (index >= 0) ? playSequence[index] : null;
	}
	
	// Gets the status string from player
	function wm_GetStatus() {
		return this.playerObject.status;
	}
	
	// Puts the player in full screen mode
	function wm_FullScreen() {
		try {
			this.playerObject.fullScreen = true;
		} catch(e) {}
	}	
	
	// Creates the internal playlist
	function wm_CreateInternalPlaylist() {
		var playlistObj = null;
		
		// Create the playlist
		try
		{
			playlistObj = this.playerObject.newPlaylist('Streaming Playlist','');
			this.playerObject.currentPlaylist = playlistObj;
		}
		catch(e) {
		}

		// Internal flag to indicate whether the player uses the internal playlist or not
		this.usePlaylist = playlistObj != null;
	}

	// Returns the index of current media item index (play sequence) (-1 if it is not found)
	function wm_GetCurrentPlaySequenceIndex() {
		var playSequence = this.currentPlaylist.getPlaySequence();
		var i, index, url, str1, str2;
		
		// Determine the current index
		if(this.playerObject.currentMedia != null)
			for(i = 0; i < playSequence.length; i++)
				if(playSequence[i].mediaUrls[this.quality] == this.playerObject.currentMedia.sourceURL)
					return i;
		
		return -1;
	}
	
	// Function to check for changes in the player state
	function wm_Tick() {
		var currentMedia = this.getCurrentMedia();
		var currentMediaUrl = currentMedia != null ? currentMedia.mediaUrls[this.quality] : '';
		
		// State string
		if(this.playerObject.status != this.lastStateStr) {
			// Trigger event
			this.onPlayerStateStringChange.exec();
			
			this.lastStateStr = this.playerObject.status;
		}
		
		// 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);
	}
}