<?xml version="1.0" encoding="utf-8"?>
<s:SpriteVisualElement xmlns:fx="http://ns.adobe.com/mxml/2009" 
                       xmlns:s="library://ns.adobe.com/flex/spark" 
                       xmlns:mx="library://ns.adobe.com/flex/mx"
                       addedToStage="addedToStageHandler(event)"
                       removedFromStage="removedFromStageHandler(event)">
    
    <fx:Script>
        <![CDATA[            
            import away3d.cameras.HoverCamera3D;
            import away3d.containers.View3D;
            import away3d.core.render.BasicRenderer;
            import away3d.debug.AwayStats;
            
            import flash.display.*;
            import flash.events.*;

            private var _camera:HoverCamera3D;
            private var _view:View3D;
            
            // Variables to rotate the camera
            private var _moveCamera:Boolean = false;
            private var _lastPanAngle:Number;
            private var _lastTiltAngle:Number;
            private var _lastMouseX:Number;
            private var _lastMouseY:Number;

            // Additional flags
            private var _isViewportAddedToStage:Boolean = false;
            private var _isMouseOnScene3D:Boolean = true;
            
            // Initialize component
            protected function addedToStageHandler(event:Event):void
            {
                if(!_isViewportAddedToStage) {
                    initialize();
                    _isViewportAddedToStage = true;
                }
            }

            private function initialize():void
            {
                initializeCamera();
                initListeners();
                
                _view.renderer = new BasicRenderer();
                
                addChild(_view);
                
                var awayStats:AwayStats = new AwayStats(_view);
                awayStats.y = 160;
                awayStats.x = 7;
                
                addChild(awayStats);
                
            }
            
            private function initializeCamera():void
            {
                _camera = new HoverCamera3D();
                _camera.focus = 200;
                _camera.distance = 200000;
                _camera.yfactor = 1;
                _camera.minTiltAngle = -80;
                _camera.maxTiltAngle = 80;
                _camera.panAngle = 140;
                _camera.tiltAngle = 20;
                _camera.hover(true);
                
                _view.camera = camera;
            }
            
            private function initListeners():void
            {
                addEventListener(Event.ENTER_FRAME, onEnterFrame);
                
                stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
                stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
                stage.addEventListener(Event.RESIZE, onResize);
                stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
                
                onResize();
            }
            
            private function onMouseDown(event:MouseEvent):void
            {    
                if(_isMouseOnScene3D) {
                    _lastPanAngle = _camera.panAngle;
                    _lastTiltAngle = _camera.tiltAngle;
                    _lastMouseX = stage.mouseX;
                    _lastMouseY = stage.mouseY;
                    _moveCamera = true;
                    stage.addEventListener(Event.MOUSE_LEAVE, onStageMouseLeave);
                }
                
            }
            
            private function onMouseUp(event:MouseEvent):void
            {
                _moveCamera = false;
                stage.removeEventListener(Event.MOUSE_LEAVE, onStageMouseLeave);     
            }
            
            private function onMouseWheel(event:MouseEvent):void
            {
                if(_isMouseOnScene3D) {
                    if (event.delta >0)
                    {
                        if(_camera.zoom < 180) _camera.zoom +=1;
                    }
                    else if (event.delta <0)
                    {
                        if(_camera.zoom > 1) _camera.zoom -=1;
                    }
                }
            }
            
            private function onStageMouseLeave(event:Event):void
            {
                _moveCamera = false;
                stage.removeEventListener(Event.MOUSE_LEAVE, onStageMouseLeave);     
            }
            
            // center View3D
            private function onResize(event:Event = null):void
            {
                _view.x = stage.stageWidth / 2;
                _view.y = stage.stageHeight / 2;
            }
            
            private function onEnterFrame(event:Event):void
            {
                if (_moveCamera) {
                    _camera.panAngle = 0.3*(stage.mouseX - _lastMouseX) + _lastPanAngle;
                    _camera.tiltAngle = 0.3*(stage.mouseY - _lastMouseY) + _lastTiltAngle;
                }
                _camera.hover();
                _view.render();
            }
            
            protected function removedFromStageHandler(event:Event):void
            {
                removeListeners();
            }
            
            // Cleanup listeners
            private function removeListeners():void 
            {
                removeEventListener(Event.ENTER_FRAME, onEnterFrame);
                
                stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
                stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
                stage.removeEventListener(Event.RESIZE, onResize);
                stage.removeEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);
            }

            // Getters
            public function get view():View3D {
                return _view;
            }
            
            public function get camera():HoverCamera3D {
                return _camera;
            }
            
            public function get isMouseOnScene3D():Boolean {
                return _isMouseOnScene3D;
            }
            
            // Setters
            public function set view(view:View3D):void {
                _view = view;
            }    
            public function set camera(camera:HoverCamera3D):void {
                _camera = camera;
            }
            
            public function set isMouseOnScene3D(isMouseOnScene3D:Boolean):void {
                _isMouseOnScene3D = isMouseOnScene3D;
            }
        ]]>
    </fx:Script>
    
</s:SpriteVisualElement>