/**
 * VERSION: 1.381
 * DATE: 2010-05-17
 * AS3 (AS2 version is also available)
 * UPDATES AND DOCUMENTATION AT: http://www.greensock.com/timelinemax/
 **/
package com.greensock {
    import com.greensock.core.*;
    import com.greensock.events.TweenEvent;
    
    import flash.events.*;
    import flash.utils.*;
/**
 *     TimelineMax extends TimelineLite, offering exactly the same functionality plus useful 
 *  (but non-essential) features like AS3 event dispatching, repeat, repeatDelay, yoyo, 
 *  currentLabel, addCallback(), removeCallback(), tweenTo(), tweenFromTo(), getLabelAfter(), getLabelBefore(),
 *     and getActive() (and probably more in the future). It is the ultimate sequencing tool. 
 *  Think of a TimelineMax instance like a virtual MovieClip timeline or a container where 
 *  you place tweens (or other timelines) over the course of time. You can:
 *     
 * <ul>
 *         <li> build sequences easily by adding tweens with the append(), prepend(), insert(), appendMultiple(), 
 *             prependMultiple(), and insertMultiple() methods. Tweens can overlap as much as you want and you have 
 *             complete control over where they get placed on the timeline.</li>
 * 
 *         <li> add labels, play(), stop(), gotoAndPlay(), gotoAndStop(), restart(), tweenTo() and even reverse()! </li>
 *         
 *         <li> nest timelines within timelines as deeply as you want.</li>
 *         
 *         <li> set the progress of the timeline using its <code>currentProgress</code> property. For example, to skip to
 *           the halfway point, set <code>myTimeline.currentProgress = 0.5</code>.</li>
 *           
 *         <li> tween the <code>currentTime</code>, <code>totalTime</code>, <code>currentProgress</code>, or <code>totalProgress</code> 
 *          property to fastforward/rewind the timeline. You could 
 *           even attach a slider to one of these properties to give the user the ability to drag 
 *           forwards/backwards through the whole timeline.</li>
 *           
 *         <li> add onStart, onUpdate, onComplete, onReverseComplete, and/or onRepeat callbacks using the 
 *           constructor's <code>vars</code> object.</li>
 *         
 *         <li> speed up or slow down the entire timeline with its <code>timeScale</code> property. You can even tween
 *           this property to gradually speed up or slow down the timeline.</li>
 *           
 *         <li> use the insertMultiple(), appendMultiple(), or prependMultiple() methods to create 
 *             complex sequences including various alignment modes and staggering capabilities.  
 *             Works great in conjunction with TweenMax.allTo() too. </li>
 *           
 *         <li> base the timing on frames instead of seconds if you prefer. Please note, however, that
 *           the timeline's timing mode dictates its childrens' timing mode as well. </li>
 *         
 *         <li> kill the tweens of a particular object inside the timeline with killTweensOf() or get the tweens of an object
 *           with getTweensOf() or get all the tweens/timelines in the timeline with getChildren()</li>
 *           
 *         <li> set the timeline to repeat any number of times or indefinitely. You can even set a delay
 *           between each repeat cycle and/or cause the repeat cycles to yoyo, appearing to reverse
 *           every other cycle. </li>
 *         
 *         <li> listen for START, UPDATE, REPEAT, REVERSE_COMPLETE, and COMPLETE events.</li>
 *         
 *         <li> get the active tweens in the timeline with getActive().</li>
 * 
 *         <li> add callbacks (function calls) anywhere in the timeline that call a function of your choosing when 
 *             the "virtual playhead" passes a particular spot.</li>
 *         
 *         <li> Get the <code>currentLabel</code> or find labels at various positions in the timeline
 *             using getLabelAfter() and getLabelBefore()</li>
 *     </ul>
 *     
 * <b>EXAMPLE:</b><br /><br /><code>
 *         
 *         import com.greensock.~~;<br /><br />
 *         
 *         //create the timeline and add an onComplete call to myFunction when the timeline completes<br />
 *         var myTimeline:TimelineMax = new TimelineMax({onComplete:myFunction});<br /><br />
 *         
 *         //add a tween<br />
 *         myTimeline.append(new TweenLite(mc, 1, {x:200, y:100}));<br /><br />
 *         
 *         //add another tween at the end of the timeline (makes sequencing easy)<br />
 *         myTimeline.append(new TweenLite(mc, 0.5, {alpha:0}));<br /><br />
 *         
 *         //repeat the entire timeline twice<br />
 *         myTimeline.repeat = 2;<br /><br />
 *         
 *         //delay the repeat by 0.5 seconds each time.<br />
 *         myTimeline.repeatDelay = 0.5;<br /><br />
 *         
 *         //pause the timeline (stop() works too)<br />
 *         myTimeline.pause();<br /><br />
 *         
 *         //reverse it anytime...<br />
 *         myTimeline.reverse();<br /><br />
 *         
 *         //Add a "spin" label 3-seconds into the timeline.<br />
 *         myTimeline.addLabel("spin", 3);<br /><br />
 *         
 *         //insert a rotation tween at the "spin" label (you could also define the insert point as the time instead of a label)<br />
 *         myTimeline.insert(new TweenLite(mc, 2, {rotation:"360"}), "spin"); <br /><br />
 *         
 *         //go to the "spin" label and play the timeline from there...<br />
 *         myTimeline.gotoAndPlay("spin");<br /><br />
 * 
 *         //call myCallbackwhen the "virtual playhead" travels past the 1.5-second point.
 *         myTimeline.addCallback(myCallback, 1.5);
 *         
 *         //add a tween to the beginning of the timeline, pushing all the other existing tweens back in time<br />
 *         myTimeline.prepend(new TweenMax(mc, 1, {tint:0xFF0000}));<br /><br />
 *         
 *         //nest another TimelineMax inside your timeline...<br />
 *         var nestedTimeline:TimelineMax = new TimelineMax();<br />
 *         nestedTimeline.append(new TweenLite(mc2, 1, {x:200}));<br />
 *         myTimeline.append(nestedTimeline);<br /><br /></code>
 *         
 *         
 *     <code>insertMultiple()</code> and <code>appendMultiple()</code> provide some very powerful sequencing tools as well, 
 *  allowing you to add an Array of tweens/timelines and optionally align them with <code>SEQUENCE</code> or <code>START</code> 
 *  modes, and even stagger them if you want. For example, to insert 3 tweens into the timeline, aligning their start times but 
 *  staggering them by 0.2 seconds, <br /><br /><code>
 *     
 *         myTimeline.insertMultiple([new TweenLite(mc, 1, {y:"100"}),
 *                                    new TweenLite(mc2, 1, {x:120}),
 *                                    new TweenLite(mc3, 1, {alpha:0.5})], 
 *                                    0, 
 *                                    TweenAlign.START, 
 *                                    0.2);</code><br /><br />
 *                                    
 *     You can use the constructor's <code>vars</code> object to do all the setup too, like:<br /><br /><code>
 *     
 *         var myTimeline:TimelineMax = new TimelineMax({tweens:[new TweenLite(mc1, 1, {y:"100"}), TweenMax.to(mc2, 1, {tint:0xFF0000})], align:TweenAlign.SEQUENCE, onComplete:myFunction, repeat:2, repeatDelay:1});</code><br /><br />
 *     
 *     If that confuses you, don't worry. Just use the <code>append()</code>, <code>insert()</code>, and <code>prepend()</code> methods to build your
 *     sequence. But power users will likely appreciate the quick, compact way they can set up sequences now. <br /><br />
 *  
 *
 * <b>NOTES:</b>
 * <ul>
 *     <li> TimelineMax automatically inits the OverwriteManager class to prevent unexpected overwriting behavior in sequences.
 *       The default mode is <code>AUTO</code>, but you can set it to whatever you want with <code>OverwriteManager.init()</code>
 *      (see <a href="http://www.greensock.com/overwritemanager/">http://www.greensock.com/overwritemanager/</a>)</li>
 *     <li> TimelineMax adds about 4.9k to your SWF (not including OverwriteManager).</li>
 * </ul>
 * 
 * <b>Copyright 2010, GreenSock. All rights reserved.</b> This work is subject to the terms in <a href="http://www.greensock.com/terms_of_use.html">http://www.greensock.com/terms_of_use.html</a> or for corporate Club GreenSock members, the software agreement that was issued with the corporate membership.
 * 
 * @author Jack Doyle, jack@greensock.com
 **/
    public class TimelineMax extends TimelineLite implements IEventDispatcher {
        /** @private **/
        public static const version:Number = 1.381;
        
        /** @private **/
        protected var _repeat:int;
        /** @private **/
        protected var _repeatDelay:Number;
        /** @private **/
        protected var _cyclesComplete:uint;
        /** @private **/
        protected var _dispatcher:EventDispatcher;
        /** @private **/
        protected var _hasUpdateListener:Boolean;
        
        /** 
         * Works in conjunction with the repeat property, determining the behavior of each cycle; when <code>yoyo</code> is true, 
         * the timeline will go back and forth, appearing to reverse every other cycle (this has no affect on the <code>reversed</code> property though). 
         * So if repeat is 2 and <code>yoyo</code> is false, it will look like: start - 1 - 2 - 3 - 1 - 2 - 3 - 1 - 2 - 3 - end. 
         * But if repeat is 2 and <code>yoyo</code> is true, it will look like: start - 1 - 2 - 3 - 3 - 2 - 1 - 1 - 2 - 3 - end.  
         **/
         public var yoyo:Boolean;
        
        /**
         * Constructor. <br /><br />
         * 
         * <b>SPECIAL PROPERTIES</b><br />
         * The following special properties may be passed in via the constructor's vars parameter, like
         * <code>new TimelineMax({paused:true, onComplete:myFunction, repeat:2, yoyo:true})</code> 
         * 
         * <ul>
         *     <li><b> delay : Number</b>                Amount of delay in seconds (or frames for frames-based timelines) before the timeline should begin.</li>
         *                                 
         *     <li><b> useFrames : Boolean</b>            If <code>useFrames</code> is set to true, the timeline's timing mode will be based on frames. 
         *                                             Otherwise, it will be based on seconds/time. NOTE: a TimelineLite's timing mode is 
         *                                             always determined by its parent timeline. </li>
         * 
         *  <li><b> paused : Boolean</b>             Sets the initial paused state of the timeline (by default, timelines automatically begin playing immediately)</li>
         * 
         *     <li><b> reversed : Boolean</b>            If true, the timeline will be reversed initially. This does NOT force it to the very end and start 
         *                                             playing backwards. It simply affects the orientation of the timeline, so if <code>reversed</code> is set to 
         *                                             true initially, it will appear not to play because it is already at the beginning. To cause it to
         *                                             play backwards from the end, set reversed to true and then set the <code>currentProgress</code> property to 1 immediately
         *                                             after creating the timeline.</li>
         *                                     
         *     <li><b> tweens : Array</b>                To immediately insert several tweens into the timeline, use the <code>tweens</code> special property
         *                                             to pass in an Array of TweenLite/TweenMax/TimelineLite/TimelineMax instances. You can use this in conjunction
         *                                             with the <code>align</code> and <code>stagger</code> special properties to set up complex sequences with minimal code.
         *                                             These values simply get passed to the <code>insertMultiple()</code> method.</li>
         *     
         *     <li><b> align : String</b>                Only used in conjunction with the <code>tweens</code> special property when multiple tweens are
         *                                             to be inserted immediately through the constructor. The value simply gets passed to the 
         *                                             <code>insertMultiple()</code> method. The default is <code>TweenAlign.NORMAL</code>. Options are:
         *                                             <ul>
         *                                                 <li><b> TweenAlign.SEQUENCE:</b> aligns the tweens one-after-the-other in a sequence</li>
         *                                                 <li><b> TweenAlign.START:</b> aligns the start times of all of the tweens (ignores delays)</li>
         *                                                 <li><b> TweenAlign.NORMAL:</b> aligns the start times of all the tweens (honors delays)</li>
         *                                             </ul>The <code>align</code> special property does <b>not</b> force all child tweens/timelines to maintain
         *                                             relative positioning, so for example, if you use TweenAlign.SEQUENCE and then later change the duration
         *                                             of one of the nested tweens, it does <b>not</b> force all subsequent timelines to change their position
         *                                             on the timeline. The <code>align</code> special property only affects the alignment of the tweens that are
         *                                             initially placed into the timeline through the <code>tweens</code> special property of the <code>vars</code> object.</li>
         *                                         
         *     <li><b> stagger : Number</b>            Only used in conjunction with the <code>tweens</code> special property when multiple tweens are
         *                                             to be inserted immediately. It staggers the tweens by a set amount of time (in seconds) (or
         *                                             in frames if <code>useFrames</code> is true). For example, if the stagger value is 0.5 and the <code>align</code> 
         *                                             property is set to <code>TweenAlign.START</code>, the second tween will start 0.5 seconds after the first one 
         *                                             starts, then 0.5 seconds later the third one will start, etc. If the align property is 
         *                                             <code>TweenAlign.SEQUENCE</code>, there would be 0.5 seconds added between each tween. This value simply gets 
         *                                             passed to the <code>insertMultiple()</code> method. Default is 0.</li>
         *     
         *     <li><b> onStart : Function</b>            A function that should be called when the timeline begins (the <code>currentProgress</code> won't necessarily
         *                                             be zero when onStart is called. For example, if the timeline is created and then its <code>currentProgress</code>
         *                                             property is immediately set to 0.5 or if its <code>currentTime</code> property is set to something other than zero,
         *                                             onStart will still get fired because it is the first time the timeline is getting rendered.)</li>
         *     
         *     <li><b> onStartParams : Array</b>        An Array of parameters to pass the onStart function.</li>
         *     
         *     <li><b> onUpdate : Function</b>            A function that should be called every time the timeline's time/position is updated 
         *                                             (on every frame while the timeline is active)</li>
         *     
         *     <li><b> onUpdateParams : Array</b>        An Array of parameters to pass the onUpdate function</li>
         *     
         *     <li><b> onComplete : Function</b>        A function that should be called when the timeline has finished </li>
         *     
         *     <li><b> onCompleteParams : Array</b>    An Array of parameters to pass the onComplete function</li>
         *     
         *     <li><b> onReverseComplete : Function</b> A function that should be called when the timeline has reached its starting point again after having been reversed </li>
         *     
         *     <li><b> onReverseCompleteParams : Array</b> An Array of parameters to pass the onReverseComplete functions</li>
         *  
         *     <li><b> onRepeat : Function</b>            A function that should be called every time the timeline repeats </li>
         *     
         *     <li><b> onRepeatParams : Array</b>        An Array of parameters to pass the onRepeat function</li>
         *     
         *     <li><b> autoRemoveChildren : Boolean</b> If autoRemoveChildren is set to true, as soon as child tweens/timelines complete,
         *                                             they will automatically get killed/removed. This is normally undesireable because
         *                                             it prevents going backwards in time (like if you want to reverse() or set the 
         *                                             <code>currentProgress</code> value to a lower value, etc.). It can, however, improve speed and memory
         *                                             management. TweenLite's root timelines use <code>autoRemoveChildren:true</code>.</li>
         * 
         *     <li><b> repeat : int</b>                Number of times that the timeline should repeat. To repeat indefinitely, use -1.</li>
         *     
         *     <li><b> repeatDelay : Number</b>        Amount of time in seconds (or frames for frames-based timelines) between repeats.</li>
         *     
         *     <li><b> yoyo : Boolean</b>                 Works in conjunction with the repeat property, determining the behavior of each 
         *                                             cycle. When <code>yoyo</code> is true, the timeline will go back and forth, appearing to reverse 
         *                                             every other cycle (this has no affect on the <code>reversed</code> property though). So if repeat is
         *                                             2 and yoyo is false, it will look like: start - 1 - 2 - 3 - 1 - 2 - 3 - 1 - 2 - 3 - end. But 
         *                                             if repeat is 2 and yoyo is true, it will look like: start - 1 - 2 - 3 - 3 - 2 - 1 - 1 - 2 - 3 - end. </li>
         *                                     
         *     <li><b> onStartListener : Function</b>    A function to which the TimelineMax instance should dispatch a TweenEvent when it begins.
         *                                               This is the same as doing <code>myTimeline.addEventListener(TweenEvent.START, myFunction);</code></li>
         *     
         *     <li><b> onUpdateListener : Function</b>    A function to which the TimelineMax instance should dispatch a TweenEvent every time it 
         *                                             updates values.    This is the same as doing <code>myTimeline.addEventListener(TweenEvent.UPDATE, myFunction);</code></li>
         *       
         *     <li><b> onCompleteListener : Function</b>    A function to which the TimelineMax instance should dispatch a TweenEvent when it completes.
         *                                                   This is the same as doing <code>myTimeline.addEventListener(TweenEvent.COMPLETE, myFunction);</code></li>
         *     </ul>
         * 
         * @param vars optionally pass in special properties like useFrames, onComplete, onCompleteParams, onUpdate, onUpdateParams, onStart, onStartParams, tweens, align, stagger, delay, autoRemoveChildren, onCompleteListener, onStartListener, onUpdateListener, repeat, repeatDelay, and/or yoyo.
         */
        public function TimelineMax(vars:Object=null) {
            super(vars);
            _repeat = (this.vars.repeat) ? Number(this.vars.repeat) : 0;
            _repeatDelay = (this.vars.repeatDelay) ? Number(this.vars.repeatDelay) : 0;
            _cyclesComplete = 0;
            this.yoyo = Boolean(this.vars.yoyo == true);
            this.cacheIsDirty = true;
            if (this.vars.onCompleteListener != null || this.vars.onUpdateListener != null || this.vars.onStartListener != null || this.vars.onRepeatListener != null || this.vars.onReverseCompleteListener != null) {
                initDispatcher();
            }
        }
        
        /**
         * If you want a function to be called at a particular time or label, use addCallback. When you add
         * a callback, it is technically considered a zero-duration tween, so if you getChildren() there will be
         * a tween returned for each callback. You can discern a callback from other tweens by the fact that
         * their target is a function and the duration is zero. 
         * 
         * @param function the function to be called
         * @param timeOrLabel the time in seconds (or frames for frames-based timelines) or label at which the callback should be inserted. For example, myTimeline.addCallback(myFunction, 3) would call myFunction() 3-seconds into the timeline, and myTimeline.addCallback(myFunction, "myLabel") would call it at the "myLabel" label.
         * @param params an Array of parameters to pass the callback
         * @return TweenLite instance
         */
        public function addCallback(callback:Function, timeOrLabel:*, params:Array=null):TweenLite {
            var cb:TweenLite = new TweenLite(callback, 0, {onComplete:callback, onCompleteParams:params, overwrite:0, immediateRender:false});
            insert(cb, timeOrLabel);
            return cb;
        }
        
        /**
         * Removes a callback from a particular time or label. If timeOrLabel is null, all callbacks of that
         * particular function are removed from the timeline.
         * 
         * @param function callback function to be removed
         * @param timeOrLabel the time in seconds (or frames for frames-based timelines) or label from which the callback should be removed. For example, <code>myTimeline.removeCallback(myFunction, 3)</code> would remove the callback from 3-seconds into the timeline, and <code>myTimeline.removeCallback(myFunction, "myLabel")</code> would remove it from the "myLabel" label, and <code>myTimeline.removeCallback(myFunction, null)</code> would remove ALL callbacks of that function regardless of where they are on the timeline.
         * @return true if any callbacks were successfully found and removed. false otherwise.
         */
        public function removeCallback(callback:Function, timeOrLabel:*=n