/*
	VERSION:	3.0
	3.0		Disabled AVOID_LOOP_PANIC().  The revised script-system should make it unnecessary now.
	2.9		Added  LOOP.isRunning[setName] = true/false;		Allowing other code to check the pause-state of entire loop-sets if it doesn't want to have a loop() called by this.
	2.8		Assumes that AVOID_LOOP_PANIC() is created automatically
	2.7		Now uses avoidLoopPanic() to (hopefully) prevent deeply nested function-calls from freezing flash.
	2.6		Added  LOOP.isPaused()  to check whether or not a set / object is paused.
	
	NOTE!!		Duplicate checking during the main loop does NOT work yet!!  (functions may be called multiple times if they're added to multiple loopSets!)
	NOTE:			Objects are NOT automatically removed from the loopManager.
						(movieClips are automatically removed)
	
	WHAT THIS IS FOR:
		This system allows you to pause/resume many objects & movieClips at once.
	
	USAGE:
		#include "loopManagerMC.as"
		_global.LOOP_MC = makeLoopManager( parent_mc, instanceName, depth );
		
		Name the loop functions:		loop()
		
		
	FUNCTIONS:
		addObject( myObject, setName )						Adds an object to a loopSet.  (and creates a new loopSet if neccessary)
		removeObject( myObject, setName )					Removes an object from a loopSet.
		removeSet( setName )											Removes a loopSet.
		pauseSet( setName, pauseValue )						Pause/resume all objects in a loopSet.
		pauseObject( myObject, pauseValue )				Pause/resume an object.
		isPaused( setName/objRef )								Returns true/false
	
	HOW THIS WORKS:
		This manually calls every object's loop() function.
		Groups of objects are organized into sets, 
		allowing many objects to be paused at once, 
		via their "isPaused" variables.
		
	NOTE:
		This version is a movieClip, because setInterval() does NOT fire on every frame like it should.
		But a movieClip's onEnterFrame() DOES fire on every frame;
		
		Pause-able movieClips should not use onEnterFrame() for their loops.		
		Loop functions must be named:		loop()
		
		Pause-able objects should not use the variable "isPaused" internally, since this system uses it.
		Pause-able objects should not use the variable "hasLooped" internally, since this system uses it.
		
		Many systems have their own internal loop intervals.  
		Those intervals must be cleared first before adding those objects to this system,
		otherwise their loops will get called twice per frame.
*/
#include "avoidLoopPanic.as"
makeLoopManager = function( parent_mc, instanceName, depth  )
{
	// create container
	//var _this = new Object();
	var _this = parent_mc.createEmptyMovieClip( instanceName, depth );
	
	_this.loopSets = {};							// contains sets of objects to loop.
	_this.loop_array = [];						// stores one of each object, and loops through each once
	_this.slowMotion = false;					// When on, this makes the loop system run at half-speed.
	_this.slowMotionToggle = false;		// While slow-motion is on, this tracks whether or not to run loops.
	_this.isRunning = {};							// LOOP.isRunning.setName = boolean;		// (!isPaused)
	
	// prevent Flash from panicking when a ton of script-commands are called at once
	// AVOID_LOOP_PANIC() was created automatically
	
	// ______________________________________________________________________________________________
	// MAIN LOOP
	_this.loop = function()
	{
		var allowLoop = true;
		if(_this.slowMotion){
			_this.slowMotionToggle = !_this.slowMotionToggle;		// flips the animation state
			if(_this.slowMotionToggle)
				allowLoop = false;
		}// if:  slow-motion is turned on
		
		if(!allowLoop)		return;		// abort if:  looping is suspended for slow-motion
		
		
		// un-mark all objects for once-each looping
		for( var L in _this.loopSets )
		{
			var thisSet = _this.loopSets[L];
			for( var obj=0; obj<thisSet.length; obj++ )
			{
				var objectPathLength = String(thisSet[obj]).length;
				if(objectPathLength==0){
					thisSet.splice( obj, 1 );		// remove movieClip ref
					obj--;
				}else{
					thisSet[obj].hasLooped = false;		// mark this object as having not run yet
				}
			}// for:  Each object in thisSet
		}// for:  Each of the loopSets
		
		// run all object loops (only once)
		for( var L in _this.loopSets ){

			// AVOID_LOOP_PANIC(function(){
				var thisSet = _this.loopSets[L];
				for( var obj=0; obj<thisSet.length; obj++ )
				{
					if( !thisSet[obj].isPaused  &&  			// if:  object isn't paused
						!thisSet[obj].hasLooped)				// if:  object hasn't already been run
					{
						thisSet[obj].loop();						// run this object's loop
						thisSet[obj].hasLooped = true;		// mark that this object has already run
					}// if:  This object is not paused.
				}// for:  Each object in thisSet
			// });// AVOID_LOOP_PANIC()
		}// for:  Each of the loopSets
	}// loop()
	//_this.loopInterval = setInterval( _this.loop, 1000/30 );		// 30 FPS
	/*
	_this.onEnterFrame = function(){
		_this.loop();
	}
	*/
	_this.onEnterFrame = _this.loop;
	
	
	
	// ______________________________________________________________________________________________
	// FUNCTIONS
	_this.addObject = function( newObject, setName )
	{
		// Create loopSet if neccessary
		_this.addSet(setName);
		var thisSet = _this.loopSets[setName];
		
		if(!newObject)		return;
		
		// Check whether this object is already in this loopSet
		var duplicateFound = false;
		for( var obj=0; obj<thisSet.length; obj++ )
		{
			if( thisSet[obj] == newObject )
			{
				duplicateFound = true;
			}
		}// for:  thisSet
		
		// add a reference to the newObject to this loopSet
		if( !duplicateFound )
		{
			thisSet.push( newObject );
			newObject.isPaused = false;
		}// if:  No duplocate was found
	}// addObject()
	
	
	
	_this.removeObject = function( findObject, setName )
	{
		if(!findObject)		return;
		
		// Find the object in the specified loopSet
		var thisSet = _this.loopSets[setName];
		for( var obj=0; obj<thisSet.length; obj++ )
		{
			if( thisSet[obj] == findObject )
			{
				// remove the object
				thisSet.splice( obj, 1 );
			}// if:  object is found
		}// for:  thisSet
	}// removeObject()
	
	
	
	_this.addSet = function( setName )
	{
		if(!setName)		return;
		
		if(_this.loopSets[setName]==undefined){	// if:  This loopSet doesn't exist.
			_this.loopSets[setName] = [];
			_this.isRunning[setName] = true;		// new sets are not paused
		}
	}// removeSet()
	
	
	
	_this.removeSet = function( setName )
	{
		if(!setName)		return;
		
		_this.isRunning[setName] = false;
		delete _this.isRunning[setName];
		delete _this.loopSets[setName];
	}// removeSet()
	
	
	
	_this.pauseSet = function( setName, pauseValue )
	{
		if(!setName)		return;
		
		var pauseValue = Boolean(pauseValue);
		_this.isRunning[setName] = !pauseValue;
		var thisSet = _this.loopSets[setName];
		//for( var obj in thisSet ){
		for( var obj=0; obj<thisSet.length; obj++ ){
			thisSet[obj].isPaused = pauseValue;
		}// for:  each object within this loopSet
	}// setPause()
	
	
	
	_this.pauseObject = function( myObject, pauseValue )	{
		myObject.isPaused = pauseValue;
	}// pauseObject()
	
	
	_this.isPaused = function( targ ){
		var output = false;
		if( typeof(targ) === "string" ){
			// if:  set-name
			var setName = targ;
			// return:  whether the 1st item in that loopSet is paused
			//output = Boolean(_this.loopSets[setName][0].isPaused) || false;
			// return:  whether that loopSet is paused  (!isRunning)
			output = !Boolean(_this.isRunning[setName]);
		}else if( targ instanceof Object){
			// if:  paused object / movieClip
			output = Boolean(targ.isPaused) || false;
		}else{
			trace('LOOP.isPaused()  ERROR:  no parameter provided');
		}
		return output;
	}// isPaused()
	
	
	
	// ______________________________________________________________________________________________
	// return this system's object
	return _this;
}// makeLoopManager()