package
{
    import com.derschmale.do3d.filters.EnvMapFilter;
    
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.ui.Keyboard;
    
    import net.hires.debug.Stats;
    
    /**
     * Native FP10 3D Environment Mapping demo
     * 
     * @author David Lenaerts
     * http://www.derschmale.com
     */
    
    [SWF(width="600", height="600", frameRate="30", backgroundColor="0x000000")]
    public class FP10EnvMap extends Sprite
    {
        [Embed(source="/../bagger.jpg")]
        private var Texture : Class;
        
        [Embed(source="/../normalmap.jpg")]
        private var NormalMap : Class;
        
        [Embed(source="/../left.jpg")]
        private var ReflLeft : Class;
        
        [Embed(source="/../right.jpg")]
        private var ReflRight : Class;
        
        [Embed(source="/../front.jpg")]
        private var ReflFront : Class;
        
        [Embed(source="/../back.jpg")]
        private var ReflBack : Class;
        
        [Embed(source="/../top.jpg")]
        private var ReflTop : Class;
        
        [Embed(source="/../bottom.jpg")]
        private var ReflBottom : Class;
        
        private var _startX : Number;
        private var _startY : Number;
        
        private var _mouseDown : Boolean;
        
        private var _surface : Sprite;
        
        private var _filter : EnvMapFilter;
        
        public function FP10EnvMap()
        {
            initView();
            initFilter();
            
            stage.addEventListener(MouseEvent.MOUSE_DOWN, handleMouseDown);
            stage.addEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
            stage.addEventListener(KeyboardEvent.KEY_UP, handleKeyUp);
            addEventListener(Event.ENTER_FRAME, handleEnterFrame);
            addChild(new Stats());
        }
        
        private function initView() : void
        {
            // init background
            var bg : Bitmap = new Bitmap(new ReflBack().bitmapData);
            bg.width = stage.stageWidth;
            bg.height = stage.stageWidth;
            addChild(bg);
            
            var textField : TextField = new TextField();
            textField.textColor = 0xffffff;
            textField.multiline = true;
            textField.text =     "Click & drag : Rotate surface\n" + 
                                "+/- : Change surface reflectance\n" + 
                                "PgUp/PgDown : Change surface relief";
            textField.width = textField.textWidth + 10;
            textField.height = textField.textHeight + 10;
            textField.x = stage.stageWidth-textField.width;
            addChild(textField);
            // init rotatable surface, make sure registration point is in center
            var bmp : Bitmap = new Texture();
            bmp.x = -bmp.width*.5;
            bmp.y = -bmp.height*.5;
            _surface = new Sprite();
            _surface.addChild(bmp);
            
            // higher z gives better reflections
            _surface.z = 1000;
            
            // position and scale
            _surface.x = stage.stageWidth*.5;
            _surface.y = stage.stageHeight*.5;
            
            _surface.scaleY = 2;
            _surface.scaleX = 4;
            
            addChild(_surface);
        }
        
        private function handleKeyUp(event : KeyboardEvent) : void
        {
            switch(event.keyCode) {
                case 107:    // +
                    _filter.alpha += 0.1;
                    if (_filter.alpha > 1) _filter.alpha = 1;
                    _surface.filters = [_filter];
                    break;
                case 109:    // -
                    _filter.alpha -= 0.1;
                    if (_filter.alpha < 0.0) _filter.alpha = 0.0;
                    _surface.filters = [_filter];
                    break;
                case Keyboard.PAGE_UP:
                    _filter.normalMapStrength += 0.005;
                    if (_filter.normalMapStrength > 0.1) _filter.normalMapStrength = 0.1;
                    _surface.filters = [_filter];
                    break;
                case Keyboard.PAGE_DOWN:
                    _filter.normalMapStrength -= 0.005;
                    if (_filter.normalMapStrength < 0.0) _filter.normalMapStrength = 0.0;
                    _surface.filters = [_filter];
                    break;
            }
        }
        
        /**
         * Create the EnvMapFilter object and assign it to the surface
         */
        private function initFilter() : void
        {
            var faces : Array = [];
            faces[EnvMapFilter.LEFT] = new ReflLeft().bitmapData;
            faces[EnvMapFilter.RIGHT] = new ReflRight().bitmapData;
            faces[EnvMapFilter.TOP] = new ReflTop().bitmapData;
            faces[EnvMapFilter.BOTTOM] = new ReflBottom().bitmapData;
            faces[EnvMapFilter.FRONT] = new ReflFront().bitmapData;
            faces[EnvMapFilter.BACK] = new ReflBack().bitmapData; 
            
            _filter = new EnvMapFilter(faces, .5, new NormalMap().bitmapData, 0.03);
            _filter.update(_surface);
            _surface.filters = [ _filter ];
        }
        
        private function handleMouseDown(event : MouseEvent) : void
        {
            _mouseDown = true;
            _startX = mouseX;
            _startY = mouseY;
        }
        
        private function handleMouseUp(event : MouseEvent) : void
        {
            _mouseDown = false;
        }
        
        private function handleEnterFrame(event : Event) : void
        {
            if (_mouseDown) {
                 _surface.rotationY += (_startX-mouseX)*.01;
                 _surface.rotationX += (_startY-mouseY)*.01;
                 _filter.update(_surface);
                 _surface.filters = [ _filter ];
             }
        }
    }
}