(function($) {
	$.fn.player = function(options) {
		var defaults = {
			id: 'ytplayer',
			url: 'http://www.youtube.com/apiplayer?enablejsapi=1&playerapiid=',
			video: '8LiQ-bLJaM4',
			flashWidth: '100%',
			flashHeight: 600,
			playerWidth: '100%',
			playerHeight: '100%',
			flashContainerName: 'player',
			flashContainer: 'div',
			playerContainer: 'div' //the container of the flash and controls
		}
		var config = $.extend(defaults, options);
		return this.each(function(i) {
			var playerId = generatePlayerId(i);
			$playerContainer = generatePlayerContainer();
			$playerContainer = generateFlashPlayer($playerContainer, playerId);
			$playerContainer = assembleHtml($playerContainer, playerId);
			$(this).append($playerContainer);
      $.data(getPlayerSlider(playerId), 'video', config.video);
	  $('.ui-slider-handle')
		.attr('id', 'slider-handle-'+playerId)
		.attr('role', 'slider')
		.attr('aria-valuemin', '0')
		.attr('aria-valuemax', '100')
		.attr('aria-valuenow', '0')
		.attr('aria-valuetext', '0 percent')
		.attr('title', 'slider control');
		});
		//Skinning - related to the display and look on the player
		/*
		Create a main container that holds the flash and the controls
		*/
		function generatePlayerContainer() {
			var $playerContainer = $('<'+config.playerContainer+' />')
									.css('height', config.playerHeight)
									.css('width', config.playerWidth)
									.addClass('player-container');
			return $playerContainer;
		}
		function assembleHtml(element, playerId) {
			//controlBar holds all the controls
			var $controlBar = $('<div />')
								.addClass('ui-corner-bottom')
								.addClass('control-bar');
			var $functionalControls = $('<div />').addClass('functional-controls');
			var $volumeControls = $('<div />').addClass('volume-controls');
			var $vol = $('<span />').attr('id', 'vol-'+playerId);
			var $logo = $('<a />').attr('href', 'http://www.nomensa.com/').html('nomensa');
			//timerBar sits in the controlBar and holds all the time based elements
			
			var $timerBar = $('<div />').addClass('timer-bar');
			var $instructionsText = $('<p>The slider bar below indicates the current position of '+
								'the video. Screen reader users should use the tab key to move '+
								'onto the slider bar.</p>'+
								'<p>Older screen readers may not recognise the slider fully. '+
								'The Rewind and Forward buttons above can still be used to '+
								'move through the video content though.</p>'+
								'<p>Recent screen readers will recognise the bar, but will need '+
								'to toggle a setting in order to report the current position. '+
								'Guidance for popular screen readers is given below:</p>'+
								'<p>Jaws: Press Jaws key + z to toggle virtual buffer mode '+
								'on/off. Window Eyes: Press Control + Shift + a to toggle '+
								'browser mode on/off. Hal: Press NumPad minus to toggle '+
								'virtual focus mode on/off.</p>'+
								'<p>Users of SA To Go will not need to toggle any settings. '+
								'It will also be possible for users of SA To Go to use the '+
								'right and left arrow keys to move backwards and forwards '+
								'through the video from the slider bar.</p>'+
								'<p>If you experience any problems using this player, please '+
								'contact <a href="http://www.nomensa.com">Nomensa</a>.</p>');
			var $instructions = $('<div />')
						.addClass('ui-helper-hidden-accessible')
						.append($instructionsText);
						//.html(" Jaws: Press Jaws key + z to toggle virtual buffer mode on/off. Window Eyes: Press Control + Shift + a to toggle browser mode on/off. Hal: Press NumPad minus to toggle virtual focus mode on/off. Users of SA To Go will not need to toggle any settings. It will also be possible for users of SA To Go to use the right and left arrow keys to move backwards and forwards through the video from the slider bar. If you experience any problems using this player, please contact <Léonie Watson>.");
			$timerBar.append($instructions);
			var $sliderBar = $('<div />')
								.attr('id', getPlayerSliderId(playerId))
								.slider({change: function(event, ui) {
						playerPlayPosition(getPlayerElement(playerId), event, ui);
					}
				});
			var $progressBar = $('<div />')
									.addClass('progress-bar')
									.attr('id', getProgressBarId(playerId))
									.attr('tabindex', '-1')
									.addClass('ui-progressbar-value')
									.addClass('ui-widget-header')
									.addClass('ui-corner-left')
									.css('width', '0%')
									.css('height', '95%'); //sits in the slider to show progress
      var $loadedBar = $('<div />')
                  .attr('id', getLoadedBarId(playerId))
				  .addClass('loaded-bar')
                  .addClass('ui-progressbar-value')
				  .attr('tabindex', '-1')
									.addClass('ui-widget-header')
									.addClass('ui-corner-left')
									.css('width', '0%')
									.css('height', '95%');
			var $played = $('<span />').html('00:00:00').attr('id', 'current-'+playerId).addClass('current-time');
			var $duration = $('<span />').html('00:00:00').attr('id', 'duration-'+playerId).addClass('duration-time');
			$sliderBar.append($progressBar);
      $sliderBar.append($loadedBar);
			$timerBar.append($played).append($sliderBar).append($duration);
			$controlBar.append($logo);
			//control bar is split into volume controls and functional controls
			addButton($functionalControls,playerId, 'Stop', 'stop');
			addButton($functionalControls,playerId, 'Rewind', 'rewind');
			addButton($functionalControls,playerId, 'Play', 'play');
			addButton($functionalControls,playerId, 'Pause', 'pause');
			addButton($functionalControls,playerId, 'Forward', 'forward');
			$controlBar.append($functionalControls);
			addButton($volumeControls,playerId, 'Mute', 'mute');
			addButton($volumeControls,playerId, '-', 'vol-down');
			addButton($volumeControls,playerId, '+', 'vol-up');
			$volumeControls.append($vol);
			$controlBar.append($volumeControls);
			$controlBar.append($timerBar);
			$playerContainer.append($controlBar);
			return $playerContainer;
		}
		function addButton($container, playerId, name, action) {
			var $label = 0;
			
			if(action == 'vol-down') {
				$label = $('<span />')
							.html('Volume down')
							.addClass('ui-helper-hidden-accessible');
			}
			if(action == 'vol-up') {
				$label = $('<span />')
							.html('Volume up')
							.addClass('ui-helper-hidden-accessible');
			}
			
			var $btn = $('<button />')
						.append(name)
						.addClass(action)
						.attr('title', action)
						.addClass('ui-corner-all')
						.addClass('ui-state-default').
						hover(function() {
							$(this).addClass("ui-state-hover");
						},
						function() {
							$(this).removeClass("ui-state-hover"); 
						});
			
			btnAddClickEvent($btn, playerId, action);
			if($label == 0) {
				$container.append($btn);
			} else {
				$btn.append($label);
				$container.append($btn);
			}
		}
		function btnAddClickEvent($btn, playerId, action) {
			$btn.click(function(event, ui) {
				var player = getPlayerElement(playerId);
				var btnId = action+'-'+playerId;
				$(this).attr('id', btnId);
				switch(action) {
					case 'play':
						playerPlay(player);
						$('#'+btnId).btnOn(); 
						$('#pause-'+playerId).btnOff();
						break;
					case 'stop':
						playerStop(player);
						$('#play-'+playerId).btnOff(); 
						break;
					case 'rewind':
						playerSkip(player, 'rewind');
						break;
					case 'forward':
						playerSkip(player, 'forward');
						break;
					case 'pause':
						player.pauseVideo();
						$('#'+btnId).btnOn(); 
						$('#play-'+playerId).btnOff();
						break;
					case 'mute':
						if(player.isMuted()) {
							player.unMute();
							$('#'+btnId).btnOff(); 
						} else {
							player.mute();
							$('#'+btnId).btnOn(); 
						}
						break;
					case 'vol-up':
						if(player.getVolume() < 100) {
							player.setVolume(player.getVolume()+10);
							$('#vol-'+playerId).html(player.getVolume());
						}
						break;
					case 'vol-down':
						if(player.getVolume() > 0) {
							player.setVolume(player.getVolume()-10);
							$('#vol-'+playerId).html(player.getVolume());
						}
						break;
				}
				return false;
			})
		}
		/*
			Create the actual flash player. When it's created it will trigger a call
			to onYouTubePlayerReady.
		*/
		function generateFlashPlayer($playerContainer, playerId) {
			var params = { allowScriptAccess: "always" };
			var atts = { id: playerId };
			var $container = $('<'+config.flashContainer+' />');
			var $videoContainer = $('<div />').addClass('video');
			$container.attr('id', config.flashContainerName+playerId);
			swfobject.embedSWF(config.url+playerId, 
					$container.attr('id'), config.flashWidth, config.flashHeight, "8", null, null, params, atts);
			$videoContainer.append($container);
			$playerContainer.append($videoContainer);
			return $playerContainer;
		}
		/* Each player needs a unique id */
		function generatePlayerId(id) {
			return config.id+id;
		}	
		//Returns the element associated with a player for use with the YouTube API.
		//Each API calls needs an element associated with it.
		function getPlayerElement(playerId) {
			return $('#'+playerId)[0];
		}
		//Each player has a unique slider and progressbar associated with it
		function getPlayerSlider(playerId) {
			return $('#'+getPlayerSliderId(playerId))[0];
		}
		function getPlayerSliderId(playerId) {
			return 'slider-'+playerId;
		}
		function getProgressBarId(playerId) {
			return 'progress-bar-'+playerId;
		}
    function getLoadedBarId(playerId) {
			return 'loaded-bar-'+playerId;
		}
		function setSlider(player, markerPosition) {
			$('#'+getPlayerSliderId(player.id))
				.slider('option', 'value', parseInt(markerPosition,10));
			$('#slider-handle-'+player.id)
				.attr('aria-valuenow', parseInt(markerPosition,10))
				.attr('aria-valuetext', parseInt(markerPosition,10)+' percent');
			$('#'+getProgressBarId(player.id))
				.attr('aria-valuenow', parseInt(markerPosition,10))
				.attr('aria-valuetext', parseInt(markerPosition,10)+' percent')
				.css('width', parseInt(markerPosition,10)+'%');
			var loaded = (player.getVideoBytesLoaded()/player.getVideoBytesTotal())*100;
			$('#'+getLoadedBarId(player.id))
				.attr('aria-valuenow', parseInt(loaded, 10))
				.attr('aria-valuetext', parseInt(loaded, 10)+' percent')
				.css('width', parseInt(loaded, 10)+'%');
		}
		//Functionality - related to the player actually doing something
		/*
		Called when the user clicks the slider to change it. The slider 
		provides a percentage value of how
		far along the marker was moved to the end. This needs to be
		converted to the appropriate time in the video being played so that the
		player can skip to that point.
		*/
		function playerPlayPosition(player, event, ui) {
			//ui.value is between 0-100
			var jumpTo = player.getDuration()*(ui.value/100);
			playerSeek(player, jumpTo);
			updateSlider(player, getPlayerSliderId(player.id));
		}
		function playerPlay(player) {
			player.playVideo();
			initPlayer(player);
		}
		function playerStop(player) {
			player.stopVideo();
			setSlider(player, 0);
			playerCueVideo(player, config.video)
		}
		function playerCueVideo(player, videoId) {
			player.cueVideoById(videoId);
		}
		function playerSeek(player, seconds) {
			player.seekTo(seconds, false);
		}
		//fastforward and rewind
		function playerSkip(player, direction) {
			var amount = player.getDuration()/60;
			if(direction == 'rewind') {
				amount = -amount;
			}
			playerSeek(player, player.getCurrentTime()+amount);
		}
		//Updates the slider to show progression of the playing video
		function updateSlider(player, sliderId) {
			var currentTime = player.getCurrentTime();
			var duration = player.getDuration();
			var markerPosition = 0;
			//get the correct value to set the marker to, converting time played to %
			if(duration > 0) {
				markerPosition = (currentTime/duration)*100;
			}
      $('#duration-'+player.id).updateTime(player.getDuration());
      $('#current-'+player.id).updateTime(player.getCurrentTime());
			setSlider(player, markerPosition);
		}
		function initPlayer(player) {
			var sliderId = getPlayerSliderId(player.id);
			//set up the timer to automatically update the timerbar items
			setInterval(function() { 
				updateSlider(player, sliderId);
			}, 350);
		}
	};
	
	$.init = function(player) {
    var video = $.data($('#slider-'+player.id)[0], 'video');
		//loading the video this way removes the play button from the flash screen
		player.loadVideoById(video);
		player.stopVideo();
		player.cueVideoById(video);
	}
	$.fn.btnOn = function() {
		return this.each(function(i) {
			$(this).addClass("ui-state-active");
		});
	}
	$.fn.btnOff = function() {
		return this.each(function(i) {
			$(this).removeClass("ui-state-active");
		});
	}
  $.fn.updateTime = function(time) { //time in seconds
    return this.each(function(i) {
      var hours = '00';
      var minutes = '00';
      var seconds= '00';
      time = parseInt(time);
      if(time >= 60) {
          minutes = parseInt(time/60);
          seconds = time-(minutes*60);
          if(minutes >= 60) {
              hours = parseInt(minutes/60);
              minutes -= parseInt(hours*60);
          }
      } else {
          seconds = time;
      }
      if(seconds < 10) { seconds = '0'+seconds; }
      minutes = (minutes < 10)?((minutes=='00')?minutes:'0'+minutes):minutes;
      hours = (hours < 10)?((hours=='00')?hours:'0'+hours):hours;
			$(this).html(hours+":"+minutes+":"+seconds);
		});
  }
})(jQuery);


function onYouTubePlayerReady(playerId) {
	var player = $('#'+playerId)[0];
	$.init(player);
	$('#vol-'+playerId).html(player.getVolume());
	player.addEventListener('onStateChange', 
		'(function(state) { return playerState(state, "' + playerId + '"); })' );
}
function playerState(state, playerId) {
	switch(state) {
		case 1: //playing
			$('#play-'+playerId).addClass("ui-state-active");
			$('#pause-'+playerId).removeClass("ui-state-active");
			break;
		case 2: //paused
			$('#pause-'+playerId).addClass("ui-state-active");
			$('#play-'+playerId).removeClass("ui-state-active");
			break;
		default:
			$('#play-'+playerId).removeClass("ui-state-active");
			$('#pause-'+playerId).removeClass("ui-state-active");
			break;
	}
}


