/**
 * An example implementation of a control for the Ext.ResourcePlayer.
 * It provides functionality for loading videos, muting/unmuting a video,
 * setting the volume and paging between items in a playlist (though a playlist 
 * is neither part of the Ext.ResourcePlayer nor the Ext.ResourcePlayer.Control).
 *
 * @author Thorsten Suckow-Homberg <ts@siteartwork.de>
 */
Ext.namespace('Ext.ResourcePlayer'); 
Ext.ResourcePlayer.Control = Ext.extend(Ext.Toolbar, {
	
	/**
	 * The youtube player this control should take care of.
	 * @cfg {Ext.ResourcePlayer} player
	 */
	
	/**
	 * The task that is responsible for reading out different states from the video
	 * such as bytesLoaded
	 */
	task : null, 
	
	/**
	 * The table cell in the toolbar that holds information about the runtime
	 * of the video
	 */
	elRuntime : null,
	
	/**
	 * An ext button for starting the video.
	 */
	playButton : new Ext.Toolbar.Button({
		iconCls : 'ext-ux-youtubeplayer-play',
		disabled : true		
	}),
	
	/**
	 * An ext button for stopping the currently playing video
	 */
	stopButton : new Ext.Toolbar.Button({
		iconCls : 'ext-ux-youtubeplayer-stop',
		disabled : true		
	}),
	
	/**
	 * The button to mute/unmute the sound of the video.
	 */
	muteButton : null,
	
	/**
	 * Slider to control the volume of the video
	 */
	volumeSlider : null,
	
	/**
	 * Controls the playback of the video.
	 */
	sliderField : null,	
	
	/**
	 * tells if the user is currently adjusting the play position in the stream
	 */
	isAdjusting : false,
	
	/**
	 * initializes needed listeners.
	 */
	_initListeners : function()
	{
		this.playButton.on('click', this._onPlay, this);
		this.stopButton.on('click', this._onStop, this);
		this.muteButton.on('toggle', this._onMuteToggle, this);
		this.on('resize', this._onResize, this);
		this.on('hide', this._onHide, this);
		this.on('destroy', this._onDestroy, this);
		var c = this;
		this.sliderField.on('dragstart', function(){this.isAdjusting = true;}, this);
		//this.sliderField.on('drag', this._onSeekPosition, this);
		this.sliderField.on('change', this._onSeekPosition, this);
		this.sliderField.on('dragend', function(){this.isAdjusting = false; this._onSeekPosition();}, this);
		//this.volumeSlider.on('drag', this._onSetVolume, this);
		this.volumeSlider.on('change', this._onSetVolume, this);
		
		this.player.on("StateChange", this._processPlayerEvents, this);
		this.player.on("Error", this._onError, this);
	},
	
	/**
	 * Listener or the error-event of the player. If any error occurs, the player
	 * will be stopped.
	 */
	_onError : function()
	{
	}, 
	
	/**
	 * Listener for the progress slider, i.e. when the slider gets dragged and the user
	 * wants to skip to a new position in the video stream.
	 */
	_onSeekPosition : function()
	{
		if (!this.sliderField.nochangeevent && !this.isAdjusting) {
			this.player.seekTo(this.sliderField.getValue());
		}
	},
	
	/**
	 * Listener for the volume slider.
	 */
	_onSetVolume : function()
	{
		this.player.setVolume(this.volumeSlider.getValue());
	},	
	
	/**
	 * Listener for the mute button toggle event
	 */
	_onMuteToggle : function(button, pressed)
	{
		if (pressed) {
			button.setIconClass('ext-ux-youtubeplayer-mute');
			this.player.mute(true);
			this.volumeSlider.setDisabled(true);			
		} else {
			button.setIconClass('ext-ux-youtubeplayer-volume');
			this.player.mute(false);
			this.volumeSlider.setDisabled(false);
		}
		
	},
	

	/**
	 * Listener for the play button
	 */
	_onPlay : function(button)
	{
		var state = this.player.getPlayerState();		
		if (state == 'playing') {
			this.player.pauseVideo();	
		} else if (state == 'paused' || state == 'video_cued' || state == 'ended') {			
			this.player.playVideo();
		}	
	}, 

	/**
	 * Listener for the stop button
	 */
	_onStop : function(button)
	{
		this.player.seekTo(0);
		this.player.stopVideo();
		this.stopButton.setDisabled(true);
	}, 

	/**
	 * Inits this component.
	 */
	initComponent : function()
	{
		this.volumeSlider = new Ext.Slider({
	   		minValue:0,
			maxValue:100,
			width: 60,
			disabled : true
		});
		
		this.sliderField = new Ext.Slider({
			minValue:0,
			maxValue:0,
			disabled : true,
			listeners : {
				render : function() {
					this.el.dom.parentNode.style.width = '100%';	
				}
			}
		});
		/*this.sliderField = new Ext.ResourcePlayer.Control.SliderField({
			minValue:0,
			maxValue:0,
			vertical:false,
			fieldLabel:'Slider',
			//disabled  : true,
			listeners : {
				render : function() {
					this.el.dom.parentNode.style.width = '100%';	
				}
			}
		});			
		*/
		this.muteButton = new Ext.Toolbar.Button({
				iconCls : 'ext-ux-youtubeplayer-volume',
				enableToggle : true,
				disabled : true
		});
		
		Ext.apply(this, {
			items: [
				this.playButton,
				this.stopButton,
				this.muteButton,
				this.volumeSlider,
				' ', 
				this.sliderField, 
				' ' 
			]
		});
			
		this._initListeners();
		Ext.ResourcePlayer.Control.superclass.initComponent.call(this);
	},
	
	/**
	 * Will add a child containing the remaining playtime into the toolbar.
	 * This has to be beautified in future releases.
	 */
	afterRender : function(ct, position)
	{
		Ext.ResourcePlayer.Control.superclass.afterRender.call(this, ct, position);
		
		this.elRuntime = Ext.fly(this.el.dom.getElementsByTagName('tr')[0]).createChild({tag : 'td'});
		this.elRuntime.update('00:00');
		this.add(new Ext.Toolbar.Spacer());
		this.add(this.muteButton);
	},
	
	/**
	 * Re-aligns the volume panel and notifies the sliderField to fire
	 * it's resize event.
	 */
	_onResize : function(adjWidth, adjHeight, rawWidth, rawHeight)
	{
		this.sliderField.fireEvent('resize');
    },
    
   
    /**
     * Stops the task manager, removes the fx element and destroys the volume 
     * panel.
     */
    _onDestroy : function()
	{
		if (this.task) {
			Ext.TaskMgr.stop(this.task);
		}		
    },
    
    /**
     * Callback for the task querying the player's state every 500 ms.
     * Note that in mozilla, a maximize or collapse of a window the player sits 
     * in will reload the whole movie, thus resultig in the current task runnning
     * to be invalid. The task will check for a valid player-insance and end itself
     * if none found.
     */
    _updateVideoInfo : function(test)
    {
    	if (!this.player.playerAvailable()) {
    		this._processPlayerEvents('ended', this.player);
    		return;	
    	}
    	var player = this.player;
    	var slider = this.sliderField;
    	
		//var total  = player.getVideoBytesTotal();
		//var loaded = player.getVideoBytesLoaded();
		
		var currentTime = this.player.getCurrentTime();
		var totalTime   = this.player.getDuration();
		
		if (!player.isRealtime()) {
			player.fireEvent('CurrentPositionChange', currentTime);
		}

		//var percLoaded = Math.floor(((loaded/total)*100));
		
		//var width = slider.sbar.getWidth();
		
		//if (loaded != -1) {
		//	var pixels = Math.floor((width/100)*percLoaded);
		//	slider.updateSliderBg(pixels);
		//}
		
		function hlp_FormatTime(t){
			t = Math.floor(t);
			var hours = Math.floor(t / 3600); t = t % 3600;
			var minutes = Math.floor(t / 60);
			var seconds = t % 60;
						
			var st = "";
			if (hours) st = hours + ":";
			if (minutes < 10) st = st + "0" + minutes + ":"; else st = st + minutes + ":";
			if (seconds < 10) st = st + "0" + seconds; else st = st + seconds;
			
			return st;
		}
		
		if (totalTime != 0) {
			//var rem = Math.floor(totalTime - currentTime);
			//var minutes = Math.floor(rem / 60);	
			//var seconds = (rem%60);
			//this.elRuntime.update((minutes < 10 ? '0'+minutes : minutes)+':'+(seconds < 10 ? '0'+seconds : seconds));	
			
			this.elRuntime.update(hlp_FormatTime(currentTime) + "/" + hlp_FormatTime(totalTime));
			
			if (this.sliderField.maxValue != totalTime) this.sliderField.maxValue = totalTime;
			
			if (!this.isAdjusting) {
				// ×èÖ¹Ñ­»·ÉèÖÃ
				this.sliderField.nochangeevent = true;
				//this.sliderField.setValue(currentTime, true);
				this.sliderField.setValue(currentTime, false);
				this.sliderField.nochangeevent = false;
			}
		}
    },
    
	/**
	 * Gateway for the player events.
	 */    
    _processPlayerEvents : function(state, player)
    {
    	switch (state) {
			case 'unstarted':  
		
			break;
				
			case 'ended':
				if (this.task) {
					Ext.TaskMgr.stop(this.task);
					this.task = null;
				}				
				this._updateVideoInfo();
				
				this.playButton.setIconClass('ext-ux-youtubeplayer-play');
				//this.sliderField.setValue(0,true);
				this.sliderField.setDisabled(true);
				if (this.volumeSlider) {
					this.volumeSlider.setDisabled(true);
				}
				//this.playButton.setDisabled(true);
				this.stopButton.setDisabled(true);
				this.muteButton.setDisabled(true);
			break;
			
			case 'playing':				
				if (!this.player.isRealtime()) this.sliderField.setDisabled(false);
				if (this.volumeSlider) {
					this.volumeSlider.setDisabled(false);					
					this.volumeSlider.setValue(this.player.getVolume());
				}
				this.playButton.setIconClass('ext-ux-youtubeplayer-pause');
				this.playButton.setDisabled(false);
				this.stopButton.setDisabled(false);
				this.muteButton.setDisabled(false);
			break;
			
			case 'paused':	    
				this.playButton.setIconClass('ext-ux-youtubeplayer-play');
			break;
			
			case 'buffering':  
			break;
			
			case 'video_cued': 				
				if(this.player.isRealtime()) break;
				if (!this.task) {
					this.mayReload = true;
					this.playButton.setDisabled(false);
				
					var c = this;
					this.task = {
				    	run: function(){
				    	   	c._updateVideoInfo();
				    	},
				    	interval: 500
					};
					Ext.TaskMgr.start(this.task);
				}
			break;
			
			case 'unknown': 
			break;
			
		}
    }
    
});
