package net.flashpunk.graphics 
{
    import flash.display.BitmapData;
    import flash.geom.Rectangle;
    import net.flashpunk.FP;
    
    /**
     * Template used to define a particle type used by the Emitter class. Instead
     * of creating this object yourself, fetch one with Emitter's add() function.
     */
    public class ParticleType 
    {
        /**
         * Constructor.
         * @param    name            Name of the particle type.
         * @param    frames            Array of frame indices to animate through.
         * @param    source            Source image.
         * @param    frameWidth        Frame width.
         * @param    frameHeight        Frame height.
         * @param    frameCount        Frame count.
         */
        public function ParticleType(name:String, frames:Array, source:BitmapData, frameWidth:uint, frameHeight:uint)
        {
            _name = name;
            _source = source;
            _width = source.width;
            _frame = new Rectangle(0, 0, frameWidth, frameHeight);
            _frames = frames;
            _frameCount = frames.length;
        }
        
        /**
         * Defines the motion range for this particle type.
         * @param    angle            Launch Direction.
         * @param    distance        Distance to travel.
         * @param    duration        Particle duration.
         * @param    angleRange        Random amount to add to the particle's direction.
         * @param    distanceRange    Random amount to add to the particle's distance.
         * @param    durationRange    Random amount to add to the particle's duration.
         * @param    ease            Optional easer function.
         * @return    This ParticleType object.
         */
        public function setMotion(angle:Number, distance:Number, duration:Number, angleRange:Number = 0, distanceRange:Number = 0, durationRange:Number = 0, ease:Function = null):ParticleType
        {
            _angle = angle * FP.RAD;
            _distance = distance;
            _duration = duration;
            _angleRange = angleRange * FP.RAD;
            _distanceRange = distanceRange;
            _durationRange = durationRange;
            _ease = ease;
            return this;
        }
        
        /**
         * Defines the motion range for this particle type based on the vector.
         * @param    x                X distance to move.
         * @param    y                Y distance to move.
         * @param    duration        Particle duration.
         * @param    durationRange    Random amount to add to the particle's duration.
         * @param    ease            Optional easer function.
         * @return    This ParticleType object.
         */
        public function setMotionVector(x:Number, y:Number, duration:Number, durationRange:Number = 0, ease:Function = null):ParticleType
        {
            _angle = Math.atan2(y, x);
            _angleRange = 0;
            _duration = duration;
            _durationRange = durationRange;
            _ease = ease;
            return this;
        }
        
        /**
         * Sets the alpha range of this particle type.
         * @param    start        The starting alpha.
         * @param    finish        The finish alpha.
         * @param    ease        Optional easer function.
         * @return    This ParticleType object.
         */
        public function setAlpha(start:Number = 1, finish:Number = 0, ease:Function = null):ParticleType
        {
            start = start < 0 ? 0 : (start > 1 ? 1 : start);
            finish = finish < 0 ? 0 : (finish > 1 ? 1 : finish);
            _alpha = start;
            _alphaRange = finish - start;
            _alphaEase = ease;
            createBuffer();
            return this;
        }
        
        /**
         * Sets the color range of this particle type.
         * @param    start        The starting color.
         * @param    finish        The finish color.
         * @param    ease        Optional easer function.
         * @return    This ParticleType object.
         */
        public function setColor(start:uint = 0xFFFFFF, finish:uint = 0, ease:Function = null):ParticleType
        {
            start &= 0xFFFFFF;
            finish &= 0xFFFFFF;
            _red = (start >> 16 & 0xFF) / 255;
            _green = (start >> 8 & 0xFF) / 255;
            _blue = (start & 0xFF) / 255;
            _redRange = (finish >> 16 & 0xFF) / 255 - _red;
            _greenRange = (finish >> 8 & 0xFF) / 255 - _green;
            _blueRange = (finish & 0xFF) / 255 - _blue;
            _colorEase = ease;
            createBuffer();
            return this;
        }
        
        /** @private Creates the buffer if it doesn't exist. */
        private function createBuffer():void
        {
            if (_buffer) return;
            _buffer = new BitmapData(_frame.width, _frame.height, true, 0);
            _bufferRect = _buffer.rect;
        }
        
        // Particle information.
        /** @private */ internal var _name:String;
        /** @private */ internal var _source:BitmapData;
        /** @private */ internal var _width:uint;
        /** @private */ internal var _frame:Rectangle;
        /** @private */ internal var _frames:Array;
        /** @private */ internal var _frameCount:uint;
        
        // Motion information.
        /** @private */ internal var _angle:Number;
        /** @private */ internal var _angleRange:Number;
        /** @private */ internal var _distance:Number;
        /** @private */ internal var _distanceRange:Number;
        /** @private */ internal var _duration:Number;
        /** @private */ internal var _durationRange:Number;
        /** @private */ internal var _ease:Function;
        
        // Alpha information.
        /** @private */ internal var _alpha:Number = 1;
        /** @private */ internal var _alphaRange:Number = 0;
        /** @private */ internal var _alphaEase:Function;
        
        // Color information.
        /** @private */ internal var _red:Number = 1;
        /** @private */ internal var _redRange:Number = 0;
        /** @private */ internal var _green:Number = 1;
        /** @private */ internal var _greenRange:Number = 0;
        /** @private */ internal var _blue:Number = 1;
        /** @private */ internal var _blueRange:Number = 0;
        /** @private */ internal var _colorEase:Function;
        
        // Buffer information.
        /** @private */ internal var _buffer:BitmapData;
        /** @private */ internal var _bufferRect:Rectangle;
    }
}