/*!

 * Media Element jQuery plugin

 * http://mediaelementjs.com/

 *

 * Creates a controller bar for HTML5 <video> tags

 * and falls back to a Flash player or Silverlight player for browsers that

 * do not support <video> or cannot play the video type.

 * Mostly designed for H.264, but can also play Ogg, WebM, FLV, WMV, ACC and MP3

 *

 * Copyright 2010, John Dyer

 * Dual licensed under the MIT or GPL Version 2 licenses.

 *

 * Version: 1.0.2

 */



// TODO:

// - make volume be event driven, remember setting (cookie, startup)

// - poster for <audio>



(function ($) {



	var v = document.createElement('video');

	var ua = navigator.userAgent;

	

	// native fullscreen (Safari only, Chrome fails)

	var hasNativeFullScreen = (typeof v.webkitEnterFullScreen !== 'undefined');

	if (ua.match('Chrome')) hasNativeFullScreen = false;



	// default player values

	var mediaElementPlayerDefaults = {

		  defaultVideoWidth: 480   	// default if the <video width> is not specified

		, defaultVideoHeight: 270  	// default if the <video height> is not specified

		, videoWidth: -1						// if set, overrides <video width> 

		, videoHeight: -1						// if set, overrides <video height>

		, audioWidth: 300						// width of audio player

		, audioHeight: 30						// height of audio player

		, messages: {

				  start: "Click to Start"

				, loading: "Loading"				  

				, paused: "Paused"

				, error: "Error"

				, ended: "Ended"				

		}		

	}



	// utility methods

	function formatTime(seconds) {

		seconds = Math.round(seconds);

		minutes = Math.floor(seconds / 60);

		minutes = (minutes >= 10) ? minutes : "0" + minutes;

		seconds = Math.floor(seconds % 60);

		seconds = (seconds >= 10) ? seconds : "0" + seconds;

		return minutes + ":" + seconds;

	}



	var playerIndex = 0;



	// wraps a MediaElement object in player controls

	function MediaElementPlayer($media, o) {



		$media = $($media);

		var options = $.extend(true,{},mediaElementPlayerDefaults,o);



		var isVideo = $media[0].tagName.toLowerCase() == 'video';

		var id = 'mep_' + playerIndex++;



		// ipad/iphone test

		var u = navigator.userAgent;

		var isiPad = (u.match(/iPad/i) != null);

		var isiPhone = (u.match(/iPhone/i) != null);

		var isAndroid = (u.match(/Android/i) != null);



		if (isiPad || isiPhone) {

			// add controls and stop

			$media.attr('controls', 'controls');

			// fix Apple bug

			$media.removeAttr('poster');



			// override Apple's autoplay override for iPads

			if (isiPad && $media[0].getAttribute('autoplay') !== null) {

				$media[0].load();

				$media[0].play();

			}



			// don't do the rest

			return;

		} else if (isAndroid && isVideo) {



			// Andriod is better off with native controls (like iOS)

			$media.attr('controls', 'controls');

			return;

			

		} else {



			// remove native controls and use MEP

			$media.removeAttr('controls');

		}



		var html = $(

		'<div id="' + id + '" class="mep-container">\
			<div class="mep-mediaelement">\
			</div>\
			<div class="mep-poster">\
				<img />\
			</div>\
			<div class="mep-overlay">\
				<div class="mep-overlay-message"></div>\
			</div>\
			<div class="mep-controls">\
				<div class="mep-playpause-button mep-play"><span></span></div>\
				<div class="mep-time-rail">\
					<span class="mep-time-total">\
						<span class="mep-time-loaded"></span>\
						<span class="mep-time-current"></span>\
						<span class="mep-time-handle"></span>\
					</span>\
				</div>\
				<div class="mep-time">\
					<span class="mep-currenttime"></span>\
					<span>|</span>\
				<span class="mep-duration"></span>\
				</div>\
				<div class="mep-volume-button mep-mute">\
					<span></span> \
					<div class="mep-volume-slider">\
						<div class="mep-volume-rail">\
							<div class="mep-volume-handle"></div>\
						</div>\
					</div>\
				</div>\
				<div class="mep-fullscreen-button"><span></span></div>\
			</div>\
			<div class="mep-clear"></div>\
		</div>');



		// insert and switch position

		$media.before(html);

		var container = $('#' + id);



		// put the <video> tag in the right spot

		container.find('.mep-mediaelement').append($media);



		// move any skins up to the container

		container.addClass($media[0].className);



		var poster = container.find('.mep-poster');

		var posterImg = poster.find('img');

		poster.hide();



		// append a poster

		var posterUrl = $media.attr('poster');



		if (posterUrl !== '') {			

			posterImg.attr('src',posterUrl);

			poster.show();

		}



		// create overlay

		var overlay = container.find('.mep-overlay');

		var overlayMessage = container.find('.mep-overlay-message');

		if ($media[0].getAttribute('autoplay') !== null)

			showMessage(options.messages.loading);

		else

			showMessage(options.messages.start);		



		// set container size to video size

		function setPlayerSize(width,height) {

			

			// ie9 appears to need this (jQuery bug?)

			width = parseInt(width);

			height = parseInt(height);

			

			container

				.width(width)

				.height(height);



			overlay

				.width(width)

				.height(height);	

				

			posterImg

				.height(height)

				.width(width);								

		}

		

		var width = 0;

		var height = 0;

				

		if (isVideo) {			

			// priority = videoWidth (forced), width attribute, defaultVideoWidth		

			width = (options.videoWidth > 0) ? options.videoWidth : ($media[0].getAttribute('width') !== null) ? $media.attr('width') : options.defaultVideoWidth;

			height = (options.videoHeight > 0) ? options.videoHeight : ($media[0].getAttribute('height') !== null) ? $media.attr('height') : options.defaultVideoHeight;				

		} else {

			width = options.audioWidth;

			height = options.audioHeight;

		}

		

		setPlayerSize(width, height);

		

		// controls bar

		var controls = container.find('.mep-controls')

		var isControlsVisible = true;



		if (isVideo) {

			// show/hide controls

			container

				.bind('mouseenter', function () { controls.fadeIn(200); setRailSize(); isControlsVisible = true; })

				.bind('mouseleave', function () { controls.fadeOut(200); isControlsVisible = false; });

		}



		function showMessage(text) {

			if (isVideo) {

				overlayMessage.html(text);

				//overlay.show();

				overlay.css('visibility','visible');

			}

		}

		function hideMessage() {

			//overlay.hide();

			overlay.css('visibility','hidden');

		}





		// find controls

		var playpause = controls.find('.mep-playpause-button');

		var fullscreen = controls.find('.mep-fullscreen-button');

		if (!isVideo)

			fullscreen.remove();



		var time = controls.find('.mep-time');

		var currentTime = controls.find('.mep-currenttime').html('00:00');

		var duration = controls.find('.mep-duration').html('00:00');



		var mute = controls.find('.mep-volume-button');

		var volumeSlider = controls.find('.mep-volume-slider');

		var volumeRail = controls.find('.mep-volume-rail');

		var volumeHandle = controls.find('.mep-volume-handle');



		var timeRail = controls.find('.mep-time-rail');

		var timeCurrent = timeRail.find('.mep-time-current').width(0);

		var timeLoaded = timeRail.find('.mep-time-loaded').width(0);

		var timeTotal = timeRail.find('.mep-time-total');

		var timeHandle = controls.find('.mep-time-handle');



		function setRailSize() {

			var usedWidth = playpause.outerWidth(true) +

												time.outerWidth(true) +

												mute.outerWidth(true) +

												((isVideo) ? fullscreen.outerWidth(true) : 0);



			var railWidth = controls.width() - usedWidth - (timeRail.outerWidth(true) - timeRail.outerWidth(false));



			timeRail.width(railWidth);

			timeTotal.width(railWidth - 10);

		}



		function setupControls(mediaElement, domNode) {

			controls.show();

			setRailSize();



			// play/pause button

			playpause.bind('click', function () {



				if (playpause.hasClass('mep-play')) {

					//if (mediaElement.paused) {

					mediaElement.play();

					playpause.removeClass('mep-play').addClass('mep-pause');

				} else {

					mediaElement.pause();

					playpause.removeClass('mep-pause').addClass('mep-play');

				}

			});



			// VOLUME SLIDER

			function volumeMove(e) {

				//$('body').css('cursor','N-resize');



				// only allow it to move within the rail

				var railHeight = volumeRail.height();

				var newY = e.pageY - volumeRail.offset().top;

				if (newY < 0)

					newY = 0;

				else if (newY > railHeight)

					newY = railHeight;



				// set position

				volumeHandle.css('top', newY - (volumeHandle.height() / 2));



				// calculate volume

				var volume = (railHeight - newY) / railHeight;



				// make sure to check mute status

				if (volume == 0) {

					mediaElement.setMuted(true);

					mute.removeClass('mep-mute').addClass('mep-unmute');

				} else {

					mediaElement.setMuted(false);

					mute.removeClass('mep-unmute').addClass('mep-mute');

				}



				mediaElement.setVolume(volume);

			};

			function positionVolumeHandle(volume) {

				volumeHandle.css('top', volumeRail.height() - (volumeRail.height() * volume) - (volumeHandle.height() / 2));

			}

			function removeMouseMove() {

				//$(document).css('cursor','');

				$(document)

					.unbind('mousemove', volumeMove)

					.unbind('mouseup', removeMouseMove);

			}

			volumeSlider.bind('mousedown', function (e) {

				volumeMove(e);

				$(document)

					.bind('mousemove', volumeMove)

					.bind('mouseup', removeMouseMove);

			});



			// MUTE

			mute.find('span').bind('click', function () {

				if (mediaElement.muted) {

					mediaElement.setMuted(false);

					mute.removeClass('mep-unmute').addClass('mep-mute');

					positionVolumeHandle(1);

				} else {

					mediaElement.setMuted(true);

					mute.removeClass('mep-mute').addClass('mep-unmute');

					positionVolumeHandle(0);

				}

			});



			// FULLSCREEN

			var isFullScreen = false;

			var normalHeight = 0;

			var normalWidth = 0;

			fullscreen.bind('click', function () {

				setFullScreen(!isFullScreen);

			});



			function setFullScreen(goFullScreen) {

				switch (mediaElement.pluginType) {

					case 'flash':

						mediaElement.setFullscreen(goFullScreen);

						break;

					case 'silverlight':

						mediaElement.setFullscreen(goFullScreen);

						break;

					case 'native':



						if (hasNativeFullScreen) {

							

							if (goFullScreen) {

								mediaElement.webkitEnterFullScreen();

							} else {

								mediaElement.webkitExitFullScreen();

							}

						

						} else {			

							if (goFullScreen) {



								// store

								normalHeight = $media.height();

								normalWidth = $media.width();



								// make full size

								container

									.addClass('mep-container-fullscreen')

									.width('100%')

									.height('100%')

									.css('z-index', 1000);



								$media

									.width('100%')

									.height('100%');



								overlay

									.width('100%')

									.height('100%');



								posterImg

									.width('100%')

									.height('auto');



								fullscreen

									.removeClass('mep-fullscreen')

									.addClass('mep-unfullscreen');



								setRailSize();





								$(document).bind('keydown', escListener);

								$(window).bind('resize', resizeListener);

							} else {



								container

									.removeClass('mep-container-fullscreen')

									.width(normalWidth)

									.height(normalHeight)

									.css('z-index', 1);

								$media

									.width(normalWidth)

									.height(normalHeight);



								posterImg

									.width(normalWidth)

									.height(normalHeight);



								fullscreen

									.removeClass('mep-unfullscreen')

									.addClass('mep-fullscreen');



								setRailSize();



								$(document).unbind('keydown', escListener);

								$(window).unbind('resize', resizeListener);



							}

						}

					}

					isFullScreen = goFullScreen;

			}



			function escListener(e) {

				if (e.keyCode == 27)

					setFullScreen(false);

			}



			function resizeListener(e) {

				setRailSize();

			}



			// time rail

			timeRail.delegate('span', 'click', function (e) {

				// mouse position relative to the object!

				var x = e.pageX;

				var offset = timeTotal.offset();

				var width = timeTotal.outerWidth();

				var percentage = ((x - offset.left) / width);

				var newTime = percentage * mediaElement.duration;



				mediaElement.setCurrentTime(newTime);

			});

			

			overlay.bind('click', function (e) {

				if (mediaElement.paused)

					mediaElement.play();

			}, true);



			// attach events to <video>

			mediaElement.addEventListener('timeupdate', function (e) {



				if (!isControlsVisible)

					return;



				if (mediaElement.currentTime && mediaElement.duration) {



					// update current:duration

					currentTime.html(formatTime(mediaElement.currentTime));

					if (mediaElement.duration)

						duration.html(formatTime(mediaElement.duration));



					// update time bar

					var newWidth = timeTotal.width() * mediaElement.currentTime / mediaElement.duration;

					timeCurrent.width(newWidth);



					// position handle

					var handlePos = newWidth - (timeHandle.width() / 2);

					timeHandle.css('left', handlePos);

				}



				setTimeLoaded(e.target);



			}, true);



			mediaElement.addEventListener('progress', function (e) {				

				setTimeLoaded(e.target);

			}, true);



			// removed byte/loaded

			// changed over to W3C method, even through Chrome currently does this wrong.

			// TODO: account for a real array with multiple values			

			function setTimeLoaded(target) {

				if (target && target.buffered && target.buffered.length > 0 && target.buffered.end && target.duration) {

					// calculate percentage

					var percent = target.buffered.end(0) / target.duration;



					// update loaded bar

					timeLoaded.width(timeTotal.width() * percent);

				}			

			}



			mediaElement.addEventListener('click', function (e) {

				if (mediaElement.paused)

					mediaElement.play();

			}, true);



			mediaElement.addEventListener('playing', function (e) {

				poster.hide();

				playpause.removeClass('mep-play').addClass('mep-pause');

				hideMessage();

			}, true);



			mediaElement.addEventListener('pause', function (e) {	

				playpause.removeClass('mep-pause').addClass('mep-play');

				showMessage(options.messages.paused);

			}, true);



			mediaElement.addEventListener('ended', function (e) {

				poster.show();

				playpause.removeClass('mep-pause').addClass('mep-play');

				showMessage(options.messages.ended);

			}, true);

			

			mediaElement.addEventListener('loadedmetadata', function(e) {				

				console.log(e, e.target, e.target.videoWidth);

				// if the <video height> was not set and the options.videoHeight was not set

				// then resize to the real dimensions

				if (isVideo && options.videoHeight <= 0 && $media[0].getAttribute('height') === null && !isNaN(e.target.videoHeight)) {

					setPlayerSize(e.target.videoWidth, e.target.videoHeight);

					setRailSize();

					mediaElement.setVideoSize(e.target.videoWidth, e.target.videoHeight);			

				}

				

			}, true);

			

			var testEvents = 'play playing played paused pausing'.split(' ');

			for (var i=0; i<testEvents.length;i++) {

				mediaElement.addEventListener(testEvents[i], function(e) {				

					console.log(e.type, e.target.paused);

				}, true);

			}



			// webkit has trouble doing this without a delay

			setTimeout(function () {

				setRailSize();

			}, 50);



			if (options.success)

				options.success(mediaElement, domNode);

		} // end setupControls



		function handleError(me) {

			showMessage(options.messages.error);

			

			var et = '';

			for (var ee in me)

				et += ee + ' = ' + me[ee] + ',';

			console.log('medialementplayer ERROR', et);

		}

		

		// create MediaElement, setup controls on success

		var meOptions = $.extend({}, options, { 

			pluginWidth: height, 

			pluginHeight: width,

			success: setupControls, 

			error: handleError });

			

		var mediaElement = html5.MediaElement($media[0], meOptions);



		return mediaElement;

	}



	// turn into jQuery plugin

	jQuery.fn.mediaelementplayer = function (options) {

		return this.each(function () {

			return new MediaElementPlayer($(this), options);

		});

	};



	window.html5.MediaElementPlayer = MediaElementPlayer;

	window.MediaElementPlayer = MediaElementPlayer;



})(jQuery);
