/* 
 * WPaudio v3.1 (http://wpaudio.com)
 * by Todd Iceton (todd@wpaudio.com)
 *
 * Converts an mp3 link to a simple player styled by HTML & CSS, powered by HTML5 with SoundManager2 Flash fallback
 *
 * Copyright 2010 Todd Iceton (email: todd@wpaudio.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
/* 
 * WPaudio common parent that will be appended to the mp3 link
 *
 * All interaction happens through this object, which calls the child players' control methods.
 * This takes care of click event listening and link decoration.
 */
function Wpaudio (elem) {
	this.elem = elem;
	var player;
	this.player = player;
	
	var getUrl = function () {
		return _wpaudio.enc[elem.id] ? _wpaudio.enc[elem.id] : elem.href;
	};
	this.getUrl = getUrl;
	
	var isPlaying = function () {
		return player.isPlaying();
	};
	this.isPlaying = isPlaying;
	
	var play = function () {
		// Pause all playing players before starting this one
		jQuery('.wpaudio-playing').each(function(i,v){
			v.wpaudio.pause();
		});
		player.play();
		// Mark as playing and slide down
		jQuery(elem).addClass('wpaudio-playing').parent().find('.wpaudio-slide:hidden').slideDown();
	};
	this.play = play;
	
	var pause = function () {
		player.pause();
		jQuery(elem).removeClass('wpaudio-playing');
	};
	this.pause = pause;
	
	var seek = function ( percent ) {
		if ( !isPlaying() ) {
			play();
		}
		player.seek(percent);
	};
	this.seek = seek;
	
	// Update button image, progress bars, time
	var updateDisplay = function () {
		// Get info from player
		var info = player.getInfo();
		// Set button image based on play/pause (check current and change if necessary)
		var button_url = (info.is_playing) ? _wpaudio.url + '/wpaudio-pause.png' : _wpaudio.url + '/wpaudio-play.png';
		if ( button_url !== jQuery(elem).children('.wpaudio-play').attr('src') ) {
			jQuery(elem).children('.wpaudio-play').attr( 'src', button_url );
		}
		// Set bar positions
		jQuery(elem).parent().find('.wpaudio-bar-position').css({
			left: String((info.playable_start/info.duration) || 0) + '%',
			width: String((info.position - info.playable_start) / info.duration * 100 || 0) + '%'
		});
		jQuery(elem).parent().find('.wpaudio-bar-playable').css({
			left: String((info.playable_start/info.duration) || 0) + '%',
			width: String((info.playable_end - info.playable_start) / info.duration * 100 || 0) + '%'
		});
		
		// Set time
		var min = Math.floor(info.position / 60);
		var sec = Math.floor(info.position % 60);
		var time_string = min + ':';
		if ( sec < 10 ) {
			time_string += '0'; // Add leading 0 to seconds if necessary
		}
		time_string += sec;
		jQuery(elem).parent().find('.wpaudio-position').text(time_string);
	};
	this.updateDisplay = updateDisplay;
	
	// Define the slider HTML so the next bit doesn't get too messy
	var slider =
		'<div class="wpaudio-slide">' +
			'<div class="wpaudio-bar">' +
				'<div class="wpaudio-bar-playable"></div>' +
				'<div class="wpaudio-bar-position"></div>' +
				'<div class="wpaudio-bar-click"></div>' +
			'</div>' +
			'<div class="wpaudio-meta">' +
				String( jQuery(elem).hasClass('wpaudio-nodl') ? '' : '<a class="wpaudio-download" href="' + elem.href + '">Download</a>' ) +
				'<div class="wpaudio-position"></div>' +
			'</div>' +
		'</div>';
	
	// Toggle play/pause on click and style the player
	jQuery(elem).click(function(){
		if ( isPlaying() ) {
			pause();
		}
		else {
			play();
		}
		jQuery(this).blur();
		return false;
	}).prepend('<img class="wpaudio-play" src="' + _wpaudio.url + '/wpaudio-play.png"/>').wrap('<span class="wpaudio-container"></span>').after(slider);

	// Fix slide width for IE -- in a timeout b/c Chrome shits otherwise
	jQuery(elem).parent().children('.wpaudio-slide').width(jQuery(elem).width());

	// Click bar to seek
	jQuery(elem).parent().find('.wpaudio-bar-click').mouseup(function (e) {
		if ( e.pageX ) {
			var percent = ( e.pageX - jQuery(this).offset().left ) / jQuery(this).width();
			seek(percent);
		}
	});
	
	// Initialize the player
	player = new this.Player(this);
}

/*
 * HTML5 player
 *
 * This contains controls and event handling for the native player
 */
function WpaudioHTML5 (parent) {
	var player = document.createElement('audio');
	this.player = player;
	
	this.parent = parent;
	player.src = parent.getUrl();
	player.volume = 1;
	jQuery(player).bind('play pause ended timeupdate progress canplaythrough', parent.updateDisplay);
		
	var isPlaying = function () {
		return !player.paused;
	};
	this.isPlaying = isPlaying;
	
	var getInfo = function () {
		var pos, dur, start, end;
		try {
			pos = player.currentTime;
			dur = player.duration;
			start = player.seekable.start();
			end = player.seekable.end();
		}
		catch (e) {
			pos = 0;
			dur = 0;
			start = 0;
			end = 0;
		}
		return {
			is_playing: isPlaying(),
			position: pos,
			duration: dur,
			playable_start: start,
			playable_end: end
		};
	};
	this.getInfo = getInfo;
	
	var play = function () {
		player.play();
	};
	this.play = play;
	
	this.pause = function () {
		player.pause();
	};
	
	this.seek = function ( fraction ) {
		player.currentTime = player.duration * fraction;
	};
	
	return this;
}


/*
 * SoundManager2 player
 *
 * This contains controls and event handling for the Flash player
 */
function WpaudioSM2 (par) {
	var that = this, player, parent;
	this.player = player;
	this.parent = parent;
	
	this.parent = par;
	this.player = soundManager.createSound({
		id: (par.elem.id && jQuery('#' + par.elem.id).length === 1) ? par.elem.id : 'wpaudio-' + String(Math.random()).split('.')[1] + String((new Date()).getTime()),
		url: par.getUrl(),
		onplay: par.updateDisplay,
		onresume: par.updateDisplay,
		onpause: par.updateDisplay,
		onfinish: par.updateDisplay,
		whileplaying: par.updateDisplay,
		whileloading: par.updateDisplay,
		volume: 100
	});
	
	var isPlaying = function () {
		return !(that.player.paused || that.player.playState === 0);
	};
	this.isPlaying = isPlaying;
	
	var getInfo = function () {
		return {
			is_playing: isPlaying(),
			position: that.player.position / 1000 || 0,
			duration: (((that.player.bytesLoaded == that.player.bytesTotal) ? that.player.duration : that.player.durationEstimate) / 1000) || 0,
			playable_start: 0,
			playable_end: ((that.player.bytesLoaded / that.player.bytesTotal) * that.player.duration) / 1000 || 0
		};
	};
	this.getInfo = getInfo;
	
	var play = function () {
		that.player.togglePause();
	};
	this.play = play;
	
	this.pause = function () {
		that.player.togglePause();
	};
	
	this.seek = function ( fraction ) {
		if ( !isPlaying() ) {
			play();
		}
		that.player.setPosition(((that.player.bytesLoaded == that.player.bytesTotal) ? that.player.duration : that.player.durationEstimate) * fraction);
	};
	
	return this;
}


/*
 * WPaudio ready
 *
 * When WPaudio is loaded, style and autoplay. Consider moving autoplay to the Wpaudio object (play if autoplay and no .wpaudio-playing).
 */
function wpaudioReady () {
	// Autoplay
	if ( jQuery('.wpaudio-autoplay:first').length ) {
		jQuery('.wpaudio-autoplay:first')[0].wpaudio.play();
	}
}


/*
 * Initialize WPaudio players
 *
 * Detect HTML5 support, set WPaudio player to either HTML5 or SM2, and initialize WPaudio players
 */
jQuery(document).ready(function(){
	var wpaudio_selector = '.wpaudio, .wpaudio-autoplay';
	// Handle all mp3 links if selected
	if ( _wpaudio.convert_mp3_links ) {
		jQuery('a[href$=.mp3]').addClass('wpaudio');
	}
	// Detect HTML5
	var _wpaudio_html5 = document.createElement('audio');
	if (!!(_wpaudio_html5.canPlayType && _wpaudio_html5.canPlayType('audio/mpeg;').replace(/no/, ''))) {
		Wpaudio.prototype.Player = WpaudioHTML5;
		jQuery(wpaudio_selector).each(function(i,v){
			v.wpaudio = new Wpaudio(v);
		});
		wpaudioReady();
	}
	// SoundManager2 fallback
	else {
		if ( typeof soundManager !== 'object' ) {
			jQuery.getScript( _wpaudio.url + '/sm2/soundmanager2-nodebug-jsmin.js', function () {
				if ( typeof soundManager === 'object' ) {
					soundManager.debugMode = false;
					soundManager.url =  _wpaudio.url + '/sm2/';
					soundManager.nullURL = 'about:blank'; //_wpaudio.url + '/sm2/null.mp3';
					soundManager.useHighPerformance = true;
					soundManager.useFastPolling = false;
					soundManager.waitForWindowLoad = false;
					soundManager.onready(function(){
						jQuery(wpaudio_selector).each(function(i,v){
							v.wpaudio = new Wpaudio(v);
						});
						wpaudioReady();
					});
				}
			});
		}
		Wpaudio.prototype.Player = WpaudioSM2;
	}
});


// Preload play + pause images -- play first!
(function(){
	var play = new Image(), pause = new Image();
	play.src = _wpaudio.url + '/wpaudio-play.png';
	jQuery( play ).load(function () {
		pause.src = _wpaudio.url + '/wpaudio-pause.png';
	});
}());
