var playerTpl = $('<div class="video-controls">' +
						'<span class="video-play-pause paused"></span>' +
						'<span class="video-time">00:00</span>' +
						'<span class="video-seeker">' +
							'<span class="video-seeker-bg">' +
								'<div class="movie-loaded-amount"></div>' +
							'</span>' +
						'</span>' +
						'<span class="video-time-total"></span>' +
						'<span class="volume-seeker">'+
							'<span class="volume-left"></span>' +
							'<span class="volume-bg"></span>' +
							'<span class="volume-right"></span>' +
						'</span>'+
					'</div>');


$.widget("ui.videoPlayerEmbed", 
{
	// startup, go go gadget...
	_init: function() 
	{
		this.detectBrowserPlugins();
		this.buildPlayer();
	},
	
	// what plugins does you browser have? The higher in this list, the more important it is.
	detectBrowserPlugins: function()
	{
		if(this.supportsNativeH264() && this.playableByNativeH264(this.options.mime)) 
		{
			this.setPlayer('native');
		}
		else if(this.supportsNativeOggTheora() && this.playableByNativeOggTheora(this.options.mime)) 
		{
			this.setPlayer('native');
		}
		else if(this.detectFlash() && this.playableByFlash(this.options.mime))
		{
			this.setPlayer('flash');
		}
		else if(this.detectWindowsMediaPlayer() && this.playableByWindowsMediaPlayer(this.options.mime))
		{
			this.setPlayer('windows');
		}
		else if(this.detectQuickTime() && this.playableByQuickTime(this.options.mime))
		{
			this.setPlayer('quicktime');
		}
		else
		{
			this.setPlayer('default');
		}
	},
	
	setPlayer: function(kind)
	{
		this.playerKind = kind;
	},
	
	// Build the html according to the playerKind.
	// Then add it to the player div.
	buildPlayer: function()
	{
		var self = this;
		
		switch(this.playerKind)
		{
			case 'native':
				this.videoPlayer = $('<video></video>')
										.attr(
										{
											width: self.options.width, 
											height: self.options.height, 
											poster: self.options.poster, 
											autoplay: self.options.autoplay
										})
										.appendTo(self.element);

				$('<source />')
					.attr({src: self.options.source, type: self.options.mime})
					.prependTo(self.videoPlayer);

				nativePlayerManager.init($('video', self.element), self.options.autoplay);
				
			break;
			
			case 'flash':
				
				if(self.options.mime == 'video/x-vimeo')
				{
					self.vimeoOembedUri = 'http://vimeo.com/api/oembed.json';

					//build vimeo player with oembed (temporary)
					$.ajax(
					{ 
						type: "GET", 
						url: self.vimeoOembedUri, 
						dataType: "jsonp", 
						data: 
						{ 
							url: self.options.source, 
							width: self.options.width, 
							maxwidth: self.options.width, 
							height: self.options.height, 
							maxheight: self.options.height, 
							byline: 0, 
							title: 0, 
							portrait: 0 
						}, 
						success: function(data) 
						{ 
							self.element.append(data.html); 
						}, 
						error: function(data) 
						{ 
							throw('vimeo oembed error'); 
						} 
					});
				}
				else
				{
					self.flashvars   = { 
						file: self.options.source, 
						image: self.options.poster, 
						controlbar: 'none', 
						icons: false, 
						displayclick: 'none', 
						type: self.options.type, 
						autostart: self.options.autoplay 
					};
					
					self.randID      = Math.random().toString().replace('.', '');
					self.flashPlayer = new SWFObject(self.options.playerLoc, 'flashPlayer'+self.randID, self.options.width, self.options.height, '9');
					
					self.flashPlayer.addParam('allowscriptaccess','always');
					self.flashPlayer.addParam('wmode','transparent');
					self.flashPlayer.addParam('allowfullscreen','true');
					self.flashPlayer.addParam('flashvars', $.param(self.flashvars));
					
					self.element[0].innerHTML += self.flashPlayer.getSWFHTML();
					
					flashPlayerManager.init(self.options.autoplay);
				}
				
			break;
			
			case 'quicktime':

				self.randID      = Math.random().toString().replace('.', '');
				self.videoPlayer = $('<embed />').attr(
									{
										id: 'qt-'+self.randID, 
										width: self.options.width, 
										height: self.options.height + 15, 
										src: self.options.source, 
										controller: true, 
										type: 'video/quicktime', 
										autoplay: true, 
										enablejavascript: false,
										name: 'qt-'+self.randID,
										postdomevents: false
									});
				
				self.element.append(self.videoPlayer);
			
			break;
			
			case 'windows': 
				
				self.randID 	 = Math.random().toString().replace('.', '');
				self.videoPlayer = $('<embed />').attr(
									{
										id: 'winPlayer-'+self.randID, 
										width: self.options.width, 
										height: self.options.height, 
										src: self.options.source, 
										type: self.options.mime, 
										name: 'winPlayer-'+self.randID
									});

				self.element.append(self.videoPlayer);
			
			break;
			
			case 'default':
				self.element.append('<img src='+self.options.poster+' /><p>Your browser cannot play this video. It\'s mimetype is: '+ self.options.mime +'</p>');
			break;
		}
		
		self.poster = $('<img />')
							.addClass('video-poster')
							.attr('src', self.options.poster)
							.css(
							{
								width: self.options.width, 
								height: self.options.height,
								position: 'absolute', 
								top: 0, 
								left: 0 
							});
		
		self.playButton = $('<div></div>')
							.addClass('video-play')
							.css(
							{
								width: self.options.width, 
								height: self.options.height,
								position: 'absolute', 
								top: 0, 
								left: 0
							});
		
		self.element
			.css(
			{ 
				width: self.options.width, 
				height: self.options.height,
				position: 'relative'
			});			
			
		if(this.playerKind == 'flash' || this.playerKind == 'native')
		{
			self.element
				.hover(function()
				{
					var self = $(this);
	
					if(self.data('animating')) return;
					
					self.data('animating', true);
	
					playerTpl.fadeIn(250, function() 
					{
						self.data('animating', false);
					});
				},
				function()
				{
					playerTpl.fadeOut(250);			
				})
				.prepend(self.poster)
				.append(self.playButton);
		}
	},

	supportsNativeVideo: function()
	{
		return !!document.createElement('video').canPlayType;
	},
		
	supportsNativeH264: function()
	{
		if(!this.supportsNativeVideo()) { return false; }
		return document.createElement("video").canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
	},
		
	supportsNativeOggTheora: function(self)
	{
		if(!this.supportsNativeVideo()) { return false; }
		return document.createElement("video").canPlayType('video/ogg; codecs="theora, vorbis"');
	},
	
	detectFlash: function() 
	{
		if (window.ActiveXObject) 
		{
			try { control = new ActiveXObject('ShockwaveFlash.ShockwaveFlash'); } catch (e) { return; }

			if (control) 
			{
		        this.pluginFound = true;
       		    return this.pluginFound;
			}
		} 
		else 
		{
	    	this.pluginFound = this.detectPlugin('Flash');
		    return this.pluginFound;
		}
	},
	
	detectWindowsMediaPlayer: function()
	{
		if(window.ActiveXObject) 
		{
		    try { var control = new ActiveXObject('WMPlayer.OCX'); }  catch(e) { return; }
		    
		    if(control) 
		    {
		        this.pluginFound = true;
       		    return this.pluginFound;
		    }
		} 
		else 
		{
			this.pluginFound = this.detectPlugin('Windows Media');
		    return this.pluginFound;
		}
	},
	
	// helperfunction to detect if the QuickTime plugin is installed
 	detectQuickTime: function() 
 	{
		if (window.ActiveXObject) 
		{
		    var control = null;
		
		    try { control = new ActiveXObject('QuickTime.QuickTime'); } catch (e) { return }

		    if (control) 
		    {
		        // In case QuickTimeCheckObject.QuickTimeCheck does not exist
		        this.pluginFound = true;
       		    return this.pluginFound;
       		}
		
			// This generates a user prompt in Internet Explorer 7		
		    try { control = new ActiveXObject('QuickTimeCheckObject.QuickTimeCheck'); } catch (e) { return; }

		    if (control) 
		    {
		        // In case QuickTime.QuickTime does not exist
		        this.pluginFound = true;
       		    return this.pluginFound;
       		}
		} 
		else 
		{
			this.pluginFound = this.detectPlugin('QuickTime Plug-in');
		    return this.pluginFound;
		}
	}, 	
 	
 	// helperfunction that loops through a list of plugins. 
 	// It returns true when it gets a hit.
 	// You can pass multiple plugins to this function because they might have a dependency.
 	// 'Shockwave','Flash' could be the arguments...
 	detectPlugin: function()
	{
	    this.plugins 	 = this.detectPlugin.arguments;
	    this.pluginFound = false;
		
		if(navigator.plugins && navigator.plugins.length > 0) 
	    {
			for(var i=0; i < navigator.plugins.length; i++) 
			{
			    this.numFound = 0;
			    
			    for(var c=0; c < this.plugins.length; c++)
			    {
					if((navigator.plugins[i].name.indexOf(this.plugins[c]) >= 0) 
					|| (navigator.plugins[i].description.indexOf(this.plugins[c]) >= 0)) 
				    {
					    this.numFound++;
					}   
			    }
	
				if(this.numFound == this.plugins.length) 
				{
					this.pluginFound = true;
					break;
			   	}
			}
	    }
	 
	    return this.pluginFound;
	},
	
	playableByNativeH264: function(mime)
	{
		switch(mime) 
		{ 
			case 'video/mp4': 
			case 'video/wmv': 
			case 'video/x-ms-wmv':
				return true; 
		}
		return false;
	},
	
	playableByNativeOggTheora: function(mime)
	{
		switch(mime) { case 'video/ogg': return true; }
		return false;
	},
	
	playableByFlash: function(mime)
	{
		switch (mime)
		{
			case 'video/x-flv':
			case 'video/mp4':
			case 'video/x-youtube':
			case 'video/x-vimeo':
				return true;
			break;
		}
		return false;
	},
	
	// favour Quicktime
	playableByQuickTime: function(mime)
	{
		switch(mime)
		{
			case 'video/avi':
			case 'video/wmv':
			case 'video/asf':
			case 'video/x-msvideo':
			case 'video/x-ms-wmv':
			case 'video/x-ms-wvx':
			case 'video/x-ms-asf':
			case 'application/x-mplayer2':
			case 'video/ogg':
				return false;
			break;
		}
		return true;
	},
	
	playableByWindowsMediaPlayer: function(mime)
	{
		switch(mime)
		{
			case 'audio/wma':
			case 'audio/x-ms-wax':
			case 'audio/x-ms-wma':

			case 'video/x-ms-wm':
			case 'video/avi':
			case 'video/asf':
			case 'video/wmv':
			case 'video/x-msvideo':
			case 'video/x-ms-wmv':
			case 'video/x-ms-wvx':
			case 'video/x-ms-asf':
			
			case 'application/x-mplayer2':
			case 'application/x-ms-wmz':
			case 'application/x-ms-wmd':
				return true;
			break;
		}
			
		return false;
	}	
});

$.ui.videoPlayerEmbed.defaults = 
{
	width: 854,
	height: 480,
	playerLoc: 'player.swf',
	autoplay: false
}

var flashPlayerManager = 
{
	init: function(autoplay)
	{
		autoplay = autoplay || false;
		
		// jw player demands that this is used to determine if the player is ready.
		try { var controlbarReady = playerReady; } catch (err){ }
		
		playerReady = function(obj) 
		{
			try 
			{
				var player = $("#"+obj['id']);
				player.each(function()
				{
					this.addModelListener("TIME", "flashPlayerManager.timeTracker");
					this.addModelListener("STATE", "flashPlayerManager.playTracker");
					this.addModelListener("LOADED", "flashPlayerManager.loaded");
					this.addControllerListener("VOLUME","flashPlayerManager.volumeTracker");
				});
		
				var controls = playerTpl;
				player.after(controls);		
		
				flashPlayerManager.bindControls(player, autoplay);
			} 
			catch(err){}
		
			try { controlbarReady(obj); } catch(err) {}
		}

	},
	
	loaded: function(obj)
	{
		var totalLoaded = Math.floor((obj.loaded / obj.total) * 100);
		$('.movie-loaded-amount', flashPlayerManager.player).animate({width: totalLoaded+'%'}, 200);
	},
	
	bindControls: function(player, autoplay)
	{
		var player = player[0];
		
		if(autoplay) 
		{
			$('.video-play-pause').removeClass('paused').addClass('playing');
			if($('.video-play').length)
			{
				$('.video-play').fadeOut(150, function()
				{
					$('.video-poster').fadeOut(150)
				});
			}
		}
		
		$(document).keyup(function(e)
		{
			if(e.keyCode == $.ui.keyCode.SPACE)
			{
				player.sendEvent("PLAY");
				
				if($('.video-play').length)
				{
					$('.video-play').fadeOut(150, function()
					{
						$('.video-poster').fadeOut(150)
					});
				}
				
			}
			return false;
		});

		$('.video-play-pause, .video-play').live('click', function() 
		{
			player.sendEvent("PLAY");
			
			if($('.video-play').length)
			{
				$('.video-play').fadeOut(150, function()
				{
					$('.video-poster').fadeOut(150)
				});
			}
		});
		
		$('.video-seeker-bg').slider(
		{
			range: "min",
			min: 0,
			max: 100000,
			slide: function(event, ui) 
			{
				player.sendEvent("SEEK", Math.round(player.getPlaylist()[0].duration * ui.value / 100000));
			}
		});
		
		$('.volume-bg').slider(
		{
			range: "min",
			min: 0,
			max: 100,
			value: player.getConfig()['volume'],
			slide: function(event, ui) 
			{
				player.sendEvent("VOLUME", ui.value);
			}
		});
	},
	
	timeTracker: function(obj)
	{
		var percentComplete = Math.round(100000 * obj.position / obj.duration);
		var player = $("#"+obj['id']);
		
		$('.video-seeker-bg').slider('option', 'value', percentComplete);
		$('.video-time').text(flashPlayerManager.formatTime(obj.position));
		$('.video-time-total').text(flashPlayerManager.formatTime(obj.duration));
	},
	
	formatTime: function(seconds)
	{
		var pad = function(s,l) { return( l.substr(0, (l.length-s.length) )+s ); }
		
		var result 		= "";
		var remaining 	= Math.floor(seconds);
		
		if (seconds > 3600)
		{
			result 		+= pad((Math.floor(remaining/3600)).toString(),"00")+":";
			remaining 	= remaining % 3600;
		}
		
		result 		+= pad((Math.floor(remaining/60)).toString(),"00")+":";
		remaining 	= remaining % 60;
		result 		+= pad(remaining.toString(),"00")+"";
		
		return result;
	},
	
	playTracker: function(obj)
	{
		if(obj.newstate == "PLAYING")
		{
			$('.video-play-pause').removeClass('paused').addClass('playing');
		} 
		else 
		{
			$('.video-play-pause').addClass('paused').removeClass('playing');
		}			
	},

	volumeTracker: function(obj)
	{
		$('.volume-bg').slider('option', 'value', obj.percentage);
	}
};

var nativePlayerManager = 
{
	init: function(video, autoplay)
	{
		var self = nativePlayerManager;
		
		self.obj		= video;
		self.video 		= video[0];
		self.autoplay 	= autoplay;
		
		self.buildControls();
		self.assignListeners();
		self.bindControls();
	},
	
	// insert the player controls. 
	// This is done in one long string for speed improvements.
	buildControls: function()
	{
		var self = nativePlayerManager;

		self.controls = playerTpl;
		self.obj.after(self.controls);

		self.playPauseButton = $('.video-play-pause', self.controls);
		self.seeker 		 = $('.video-seeker-bg', self.controls);	
		self.volumeSeeker 	 = $('.volume-bg', self.controls);
		
		if(self.autoplay) self.playPauseButton.removeClass('paused').addClass('playing');
	},
		
	assignListeners: function()
	{
		var self = nativePlayerManager;

		// event listener for when the progress updates
		self.obj.bind("timeupdate", function() 
		{
			if($('.ui-slider-handle').css('left'))
			{
				var left = $('.ui-slider-handle').css('left');
			}
			
			self.seeker.slider('option', 'value', self.getCurrentTime(self.video));
			$('.video-time').text(self.formatTime(self.getCurrentTime(self.video)));
			$('.video-time-total').text(self.formatTime(self.getDuration(self.video)));
		});
			
		self.obj.bind("progress", function(e) 
		{
			var totalLoaded = Math.floor((e.originalEvent.loaded / e.originalEvent.total) * 100);
			$('.movie-loaded-amount').animate({width: totalLoaded+'%'}, 200)
		});	
		
		self.obj.bind("volumechange", function(e) 
		{
			self.volumeSeeker.slider('option', 'value', e.currentTarget.volume);
		});
	},
	
	formatTime: function(seconds)
	{
		var pad = function(s,l) { return( l.substr(0, (l.length-s.length) )+s ); }
		
		var result 		= "";
		var remaining 	= Math.floor(seconds);
		
		if (seconds > 3600)
		{
			result 		+= pad((Math.floor(remaining/3600)).toString(),"00")+":";
			remaining 	= remaining % 3600;
		}
		
		result 		+= pad((Math.floor(remaining/60)).toString(),"00")+":";
		remaining 	= remaining % 60;
		result 		+= pad(remaining.toString(),"00")+"";
		
		return result;
	},
	
	// Bind the buttons within the controller to actions
	// Here you can also bind special things per player kind
	bindControls: function()
	{
		var self = nativePlayerManager;

		// event listener for when the video is ready to start playing
		self.obj.bind("canplay", function()
		{
			if(self.autoplay)
			{
				$('.video-play').fadeOut(150, function()
				{
					$('.video-poster').fadeOut(150)
				});
			}
			
			self.seeker.slider(
			{ 
				range: "min",
				min: 	0, 
				max: 	self.getDuration(self.video), 
				step: 	.1, 
				slide: 	function(e, ui) 
				{ 
					self.setCurrentTime(ui.value, self.video); 
				} 
			});
		});
	
		self.obj.bind("canplay", function()
		{
			self.volumeSeeker.slider(
			{
				range: "min",
				min: 0,
				max: 1,
				step: .1,
				value: self.getVolume(self.video),
				slide: function(event, ui) 
				{
					self.setVolume(self.video, ui.value);
				}
			});
		});			

		$(document).keyup(function(e)
		{
			if(e.keyCode == $.ui.keyCode.SPACE)
			{
				self.playPause();
				
				if($('.video-play').length)
				{
					$('.video-play').fadeOut(150, function()
					{
						$('.video-poster').fadeOut(150)
					});
				}
				
			}
			return false;
		});
		
		self.playPauseButton.click(function()
		{
			self.playPause();
			
			if($('.video-play').length)
			{
				$('.video-play').fadeOut(150, function()
				{
					$('.video-poster').fadeOut(150)
				});
			}
		});

		$('.video-play').live('click', function()
		{
			self.playPause();
			
			if($('.video-play').length)
			{
				$('.video-play').fadeOut(150, function()
				{
					$('.video-poster').fadeOut(150)
				});
			}
		});
	},
	
	// helper functions
	getDuration: function(video)
	{
		return video.duration;
	},
	
	getCurrentTime: function(video)
	{
		return video.currentTime;
	},
	
	setCurrentTime: function(time, video)
	{
		video.currentTime = time;
	},
	
	getVolume: function(video)
	{
		return video.volume;
	},
	
	setVolume: function(video, volume)
	{
		video.volume = volume;
	},
	
	playPause: function()
	{
		var self = nativePlayerManager;

		if(self.video.paused)
    	{
    		self.video.play();
    		self.playPauseButton.addClass('playing').removeClass('paused');
    	}
  		else
		{
			self.video.pause();
    		self.playPauseButton.addClass('paused').removeClass('playing');
		}
	}
};
