/*
	VERSION:		2.2
	2.2		multiple instances of the same sound starting at once will be muted so you only hear one
	2.1		remove()	changed to search its array in reverse
	2.0		Triggers onSoundComplete() & "onSoundEnd" event upon stopping OR looping
	
	PURPOSE:
		This system allows you to easily play sound-effects
		without them interupting each other.
	
	MINIMAL USAGE:
		#include "makeSoundSystem.as"
		SOUND = makeSoundSystem();	
		SOUND.play(linkage);
		
	MAX USAGE:
		#include "makeSoundSystem.as"
		SOUND = makeSoundSystem( target_mc:MovieClip, newName:String, [newDepth:Number] );
		SOUND.play(linkage, [volume]);
		
	FUNCTIONS:
		SOUND.play(linkage, [volume], [true]);		Plays a sound effect, and sets its individual volume.
		SOUND.stopAll();							Stops all currently-playing sound effects.
		sound_ref.remove();						Removes this sound.
		
	EVENTS:
		mySound.onSoundDone()					Externally-defined function that triggers when a non-looping sound completes.
	
	PROPERTIES
		volume										Changes the overall volume of the sound system.
															(scales every sound's volume, while retaining relative volume levels)
	DEPENDANCIES
		nextDepth.as
*/
makeSoundSystem = function(target_mc, name, depth)
{
	// resolve optional parameters
	target_mc = (target_mc!=undefined) ? target_mc : this;
	name = (target_mc!=undefined) ? name : "soundSystem_mc";
	#include "nextDepth.as"
	depth = (depth!=undefined) ? depth : nextDepth(target_mc);
	
	// create sound container
	var _this = target_mc.createEmptyMovieClip( name, depth );
	_this.sound_array = new Array();
	_this.soundVolume = 100;
	
	
	
	// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 
	// Keep track of which sounds began playing during this frame
	
	var startList = {};
	function get_isStarting( soundPath ){
		return  Boolean( startList[ soundPath ] !== undefined );		// undefined => false,   else => true
	}// get_isStarting()
	function set_isStarting( soundPath ){
		startList[ soundPath ] = true;
	}// set_isStarting()
	function clear_isStarting( soundPath ){
		delete startList[ soundPath ];
	}// clear_isStarting()
	
	
	// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 
	
	
	
	_this.play = function( soundName, volume, loop )
	{
		if(soundName.length > 0)
		{// if:  sound file is specified
			// optional parameters
			var volume = (volume!=undefined) ? volume : 100;
			var loop = (loop!=undefined) ? loop : false;
			
			// Create a useless movieClip for this sound's volume control
			var clipName = "transformClip_"+Math.floor( Math.random()*999 );		// transformClip_315
			var transformClip = _this.createEmptyMovieClip( clipName, nextDepth(_this)  );
			
			// Create a new sound
			var new_sound = new Sound( transformClip );
			AsBroadcaster.initialize( new_sound );		// this sound effect can fire events
			_this.sound_array.push( new_sound );
			
			// store a reference to this sound's transformClip
			new_sound.transformClip = transformClip;
			
			// store this sound's volume
			new_sound.volume = volume;
			
			// apply volume
			new_sound.setVolume( new_sound.volume * (_this.soundVolume/100) );		// this sound's volume * global volume
			
			// define the sound effect
			new_sound.attachSound( soundName );
			
			// play the sound
			if( loop ){
				//new_sound.start( 0, 99999 );		// repeats
				new_sound.start();		// plays once
			}else{
				new_sound.start();		// plays once
			}
			
			
			
			// don't allow this sound effect to be heard again during the same frame  (the perceived volume is increased when the same sound is played multiple times at once)
			var isAlreadyStarting = get_isStarting( soundName );
			if( isAlreadyStarting ){
				// if:  this sound was already starting to play
				// mute this particular sound instance
				new_sound.volume = 0;
				new_sound.setVolume( 0 );
				// this sound instance will play silently and fire normal events as expected
			}// if:  this sound was already starting to play
			else
			{// if:  this sound was not playing
				// remember that this sound is beginning to play
				set_isStarting( soundName );
				// wait 1 frame
				setTimeout( function(){
					// forget about this sound effect  =>  allow it to be played again
					clear_isStarting( soundName );
				}, 33 );
			}// if:  this sound was not playing
			
			
			
			new_sound.remove = function()
			{
				// find this sound in the sound_array
				for (var i=_this.sound_array.length-1; i>=0; i--)
				{
					if( this == _this.sound_array[i] )
					{
						_this.sound_array[i].onSoundComplete = null;	// prevent looping upon stopping
						_this.sound_array[i].stop();
						_this.sound_array[i].onSoundDone();		// externally-defined function
						_this.sound_array[i].broadcastMessage("onSoundComplete");
						// remove all listeners in this sound
						for(var s in _this.sound_array[i]._listeners)
							_this.sound_array[i].removeListener( _this.sound_array[i]._listeners[s] );
						// erase this sound's transformClip
						_this.sound_array[i].transformClip.removeMovieClip();
						
						// splice out this sound
						_this.sound_array.splice( i, 1 );
						
						// stop searching
						break;
					}// if:  this sound is found in the array
				}// for:  sound_array
			}// remove()
			
			
			
			if( loop )
			{// if:  sound effect loops
				new_sound.onSoundComplete = function()
				{
					new_sound.onSoundDone();		// externally-defined function
					new_sound.broadcastMessage("onSoundComplete");
					new_sound.start();
				}// onSoundComplete()
			}// if:  sound effect loops
			else
			{// if:  sound effect plays only once
				// remove the sound object when it's done playing
				new_sound.onSoundComplete = function()
				{
					new_sound.remove();		// contains the sound-stop events
				}// onSoundComplete()
			}// if:  sound effect plays only once
			/*
			if( !loop )
			{// if:  sound effect plays only once
				// remove the sound object when it's done playing
				new_sound.onSoundComplete = function()
				{
					_this.sound_array[i].onSoundDone();		// externally-defined function
					_this.sound_array[i].broadcastMessage("onSoundComplete");
					new_sound.remove();
				}// onSoundComplete()
			}// if:  sound effect plays only once
			*/
			
			
			if(new_sound.duration == 0)
			{// if:  sound failed to load  /  is empty
				new_sound.onSoundDone();		// externally-defined function
				new_sound.remove();
				new_sound = null;
				delete new_sound;
			}// if:  sound failed to load  /  is empty
			
			
			return new_sound;
		}// if:  sound file is specified
	}// play()
	
	
	
	_this.stopAll = function()
	{
		// empty the sound_array
		for( var nam in _this.sound_array)
		{
			_this.sound_array[nam].stop();
			_this.sound_array.pop();
		}// for...in:  sound_array
	}// stopAll()
	
	
	
	_this.setVolume = function( newVolume )
	{
		// store the new volume
		_this.soundVolume = newVolume;
		
		// update currently playing sounds
		for( var i=0; i< _this.sound_array.length; i++)
		{
			_this.sound_array[i].setVolume( _this.sound_array[i].volume * (_this.soundVolume/100) );
		}// for:  sound_array
	}// setVolume()
	_this.getVolume = function()
	{
		return _this.soundVolume;
	}// setVolume()
	_this.addProperty( "volume", _this.getVolume, _this.setVolume );
	
	
	
	return _this;
}// makeSoundSystem()
