package net.flashpunk
{
    /**
     * Updateable Tween container.
     */
    public class Tweener
    {
        /**
         * Persistent Tween type, will stop when it finishes.
         */
        public const PERSIST:uint = 0;
        
        /**
         * Looping Tween type, will restart immediately when it finishes.
         */
        public const LOOPING:uint = 1;
        
        /**
         * Oneshot Tween type, will stop and remove itself from its core container when it finishes.
         */
        public const ONESHOT:uint = 2;
        
        /**
         * If the Tweener should update.
         */
        public var active:Boolean = true;
        
        /**
         * If the Tweener should clear on removal. For Entities, this is when they are
         * removed from a World, and for World this is when the active World is switched.
         */
        public var autoClear:Boolean = false;
        
        /**
         * Constructor.
         */
        public function Tweener() 
        {
            
        }
        
        /**
         * Updates the Tween container.
         */
        public function update():void
        {
            
        }
        
        /**
         * Adds a new Tween.
         * @param    t            The Tween to add.
         * @param    start        If the Tween should call start() immediately.
         * @return    The added Tween.
         */
        public function addTween(t:Tween, start:Boolean = false):Tween
        {
            if (t._parent) throw new Error("Cannot add a Tween object more than once.");
            t._parent = this;
            t._next = _tween;
            if (_tween) _tween._prev = t;
            _tween = t;
            if (start) _tween.start();
            return t;
        }
        
        /**
         * Removes a Tween.
         * @param    t        The Tween to remove.
         * @return    The removed Tween.
         */
        public function removeTween(t:Tween):Tween
        {
            if (t._parent != this) throw new Error("Core object does not contain Tween.");
            if (t._next) t._next._prev = t._prev;
            if (t._prev) t._prev._next = t._next;
            else _tween = t._next;
            t._next = t._prev = null;
            t._parent = null;
            t.active = false;
            return t;
        }
        
        /**
         * Removes all Tweens.
         */
        public function clearTweens():void
        {
            var t:Tween = _tween,
                n:Tween;
            while (t)
            {
                n = t._next;
                removeTween(t);
                t = n;
            }
        }
        
        /** 
         * Updates all contained tweens.
         */
        public function updateTweens():void
        {
            var t:Tween = _tween;
            while (t)
            {
                if (t.active)
                {
                    t.update();
                    if (t._finish) t.finish();
                }
                t = t._next;
            }
        }
        
        // List information.
        /** @private */ internal var _tween:Tween;
    }
}