/*
 * jQuery Sound Manager Plugin
 * http://github.com/adriengibrat/jQuery-SoundManager
 *
 * Copyright (c) 2009 Adrien Gibrat
 * Dual licensed under the MIT and GPL licenses.
 * http://opensource.org/licenses/mit-license.php
 */
( function( jQuery ) {
	var sm = soundManager;
	jQuery.playable = jQuery.extend( function( url, settings ) {
		if ( typeof url == 'object' && url.url ) { // Allow to pass all settings including URL in one single object
			settings = url;
			url = url.url;
			delete settings.url;
		}
		jQuery.each( settings || {}, function( key, value ) { // Parse settings to isolate SoundManager properties
			if ( jQuery.inArray( key, jQuery.playable.properties ) ) {
				sm[key] = ( key == 'flash9Options' || key == 'movieStarOptions' ) ? jQuery.extend( sm[key], value ) : value;
				delete settings[key]; // Unset propeties from default options
			}
		} );
		jQuery.extend( true, sm, {
			url : url, // Set Flash url
			debugMode : window.location.hash.match(/^#debug/i), // Activate Debugging with hash (#debug)
			consoleOnly : window.location.hash.match(/consolejQuery/i), // Debug in console only (#debugconsole)
			defaultOptions : jQuery.extend( jQuery.playable.settings, settings ) // Extends soundManager default options
		} );
		jQuery.each( jQuery.playable.events, function( i, event ) { // Set Events Handler as element custom Handler
			sm.defaultOptions[event] = function() {
				this.options.element.triggerHandler( event, this );
			};
		} );
	}, {
		settings : {
			autoStart : false,
			pauseOnly : false,
			playNext : true,
			loopNext : true,
			playAlone : true,
			doUnload : false
		},
		count : 0,
		current : null,
		searching : null,
		css : {
			playable: 'playable',
			loading : 'loading',
			playing : 'playing',
			paused : 'paused'
		},
		methods : ['play','stop','pause','resume','togglePause','mute','unmute','unload','setPosition','setVolume','setPan'],
		events : ['onload', 'onplay', 'onpause', 'onresume', 'onstop', 'onfinish'],
		properties : ['altURL','allowPolling','allowScriptAccess','debugFlash','debugMode','useConsole','consoleOnly','flashLoadTimeout','flashVersion','nullURL','useFastPolling','useHighPerformance','wmode','waitForWindowLoad','flash9Options','movieStarOptions','allowFullScreen','useMovieStar'],
		init : function( options, playlist ) {
			var options = jQuery.extend( true, {playlist: playlist}, sm.defaultOptions, options ),
				self = jQuery( this );
			self.addClass( jQuery.playable.css.playable )
			.data( 'playable', sm.createSound( jQuery.extend( options, {
				id : 'playable' + jQuery.playable.count++,
				url : this.href,
				element : self
			} ) ) )
			.click( function( event ) {
				event.preventDefault();
				self.data( 'playable' ).togglePause();
				return false;
			} )
			.bind( 'onload.playable', function( event, sound ) {
				if ( sound.readyState == 2 )
					jQuery.playable.next();
			} )
			.bind( 'onplay.playable', function() {
				if ( options.playAlone && jQuery.playable.current && jQuery.playable.current != self )
					jQuery.playable.current.data( 'playable' )[ options.pauseOnly ? 'pause' : 'stop' ]();
				jQuery.playable.current = self.focus();
			} )
			.bind( 'onresume.playable', function( event, sound ) {
				self.triggerHandler( 'onplay', sound );
			} )
			.bind( 'onstop.playable', function( event, sound ) {
				if ( options.doUnload )
					sound.unload();
			} )
			.bind( 'onfinish.playable', function( event, sound ) {
				self.triggerHandler( 'onstop', sound );
				if ( options.playNext )
					jQuery.playable.next();
			} );
			jQuery.each( jQuery.playable.ui, function( i, ui ) { // Bind UIs
				ui.call( self, options );
			} );
		},
		ui : {
			basic : function() {
				var self = this
				.bind( 'onload.playable', function(){
					self.removeClass( jQuery.playable.css.loading );
				} )
				.bind( 'onplay.playable', function(){
					self.removeClass( jQuery.playable.css.paused ).addClass( jQuery.playable.css.playing );
					if ( self.data( 'playable' ).readyState == 1 )
						self.addClass( jQuery.playable.css.loading );
				} )
				.bind( 'onpause.playable', function(){
					if ( ! jQuery.playable.searching )
						self.removeClass( jQuery.playable.css.playing ).addClass( jQuery.playable.css.paused );
				} )
				.bind( 'onstop.playable', function(){
					self.removeClass( [jQuery.playable.css.playing, jQuery.playable.css.loading, jQuery.playable.css.paused].join(' ') );
				} );
			}
		},
		next : function( move ) {
			if ( ! this.current )
				return;
			var options  = this.current.data( 'playable' ).options,
				playlist = jQuery( options.playlist ),
				songs    = playlist.is( 'a[href]' ) ? playlist : playlist.find( 'a[href]' ),
				move     = move || 1,
				next     = songs.eq( songs.index( options.element ) + move ).data( 'playable' );
			if ( ! next && options.loopNext )
				next = songs.eq( 0 ).data( 'playable' );
			if ( next && ! next.playState )
				next.play();
		}
	} );
	jQuery.fn.playable = function( options ) {
		var playlist	= this.selector,
			songs		= this.is( 'a[href]' ) ? this : this.find( 'a[href]' ),
			options		= options || {};
		if ( typeof options == 'string' && jQuery.inArray( options, jQuery.playable.methods ) != -1 )
			songs.each( function( args ) {
				var sound = jQuery( this ).data( 'playable' );
				sound && sound[options]( args );
			}, [arguments[1]] );
		else
			sm.onready( function() {
				songs.each( function() {
					if ( sm.canPlayURL( this.href ) )
						jQuery.playable.init.call( this, options, playlist );
				});
				if ( options && options.autoStart )
					songs.filter( ':first' ).click();
			} );
		return this;
	};
} )( jQuery );
