// ************************************************************************************************
// *** 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.playForcedIndex = wm_PlayForcedIndex;
	this.playUrl = wm_PlayUrl;
	this.setUrl = wm_SetUrl;
	this.previous = wm_Previous;
	this.stop = wm_Stop;
	this.fastForward = wm_FastForward;
	this.rewind = wm_Rewind;
	
	// 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;
	this.resize = wm_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;
	
	// 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.getCurrentIndex = wm_GetCurrentIndex;
	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() {
		this.playerObject.controls.next();
	}	
	
	// Pauses the playing of media item
	function wm_Pause() {
		this.playerObject.controls.pause();
	}
	
	// Plays the current media item
	function wm_Play() {
		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);
		
		this.playerObject.controls.playItem(this.playerObject.currentPlaylist.item(psIndex));
	}
	function wm_PlayForcedIndex(index)
	{
		var forcedIndex;
		
		// Get the original play sequence index from playlist index
		forcedIndex = this.currentPlaylist.getPlayIndex(index);
		
		this.playerObject.controls.playItem(this.playerObject.currentPlaylist.item(forcedIndex));
	}
	
	// Plays the specified url
	function wm_PlayUrl(url) {
		// Do NOT use this when working with playlists

		// Sets the URL and plays
		this.playerObject.URL = url;	
		this.playerObject.controls.play();
	}
	
		// Plays the specified url
	function wm_SetUrl(url) {
		// Do NOT use this when working with playlists

		// Sets the URL 
		this.playerObject.URL = url;	
	}

	// Sets the current item to the previous in the playlist
	function wm_Previous() {
		this.playerObject.controls.previous();
	}
	
	// Stops the playing of media item
	function wm_Stop() {
		this.playerObject.controls.stop();
	}

	// Fast forwards the playing of media item
	function wm_FastForward() {
		this.playerObject.controls.fastForward();
	}
	
	// Rewinds the playing of media item
	function wm_Rewind() {
		this.playerObject.controls.fastReverse();
	}
	
	// Returns the duration (in seconds) of the current media
	function wm_GetCurrentMediaDuration() {
		if(this.playerObject.currentMedia != null)
			return this.playerObject.currentMedia.duration;
		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);
		return 0;
	}
	
	// Sets the current position in the media item in seconds from de beginning
	function wm_SetPosition(position) {
		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)
			if(this.playerObject.settings)
				return this.playerObject.settings.mute;
				
		return(false);
	}
	
	// Gets the repeat flag
	function wm_GetRepeat() 
	{
		return (this.playerObject.settings.getMode('loop'));
	}
	
	// Sets the repeat flag
	function wm_SetRepeat(state)
	{
		this.playerObject.settings.setMode('loop', state);
	}

	
	// 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)
		{
			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;
		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 4 : // ScanForward
				return this.playState.forwarding;
			case 5 : // ScanReverse
				return this.playState.rewinding;
			case 3 : // Playing
			case 8 : // MediaEnded
			case 9 : // Transitioning
			case 11 : // Reconnecting
				return this.playState.playing;
			case 6 : // Buffering
				return this.playState.buffering;
			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) {}
	}
	
	// Resizes the player
	function wm_Resize(width, height)
	{
		this.playerObject.width = width;
		this.playerObject.height = height;

		// Workaround for Mozilla
		// Usually it doesn't redraw the player correctly after resizing
		// Setting the body height and returning it to auto forces a redraw
		if(window.GeckoActiveXObject)
		{
			document.getElementsByTagName("body")[0].style.height = '1px';
			window.setTimeout('document.getElementsByTagName("body")[0].style.height = \'auto\';',100); // Apparently a small delay is required
		}
	}
	
	// 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) {}
	}

	// Returns the index of current media item index (play sequence) (-1 if it is not found)
	function wm_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.currentMedia.sourceURL.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].mediaUrls[this.quality];
					urlAd = url.substring(url.indexOf("://") + 3);

					if(this.playerObject.currentMedia.sourceURL.indexOf(urlAd)>0)
					{
						return i;
					}
				}
			}
		}
		
		return -1;
	}

	// 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.getStatus() != this.lastStateStr) {
			// Trigger event
			this.onPlayerStateStringChange.exec();
			
			this.lastStateStr = this.getStatus();
		}
		
		// Media change
		if(currentMediaUrl != this.lastMediaUrl && this.getPlayState()!=this.playState.stopped) {
			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);
	}
}