package {

    import cmodule.vector.CLibInit;
    
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.utils.getTimer;

    public class AlchemySpeedTest extends Sprite {

        private var vectorUtils:Object;

        public function AlchemySpeedTest() {

            // Set up the stage
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            // Create the Alchemy bridge to C++ methods
            var loader:CLibInit = new CLibInit;
            vectorUtils = loader.init();

            // Create a text field                        
            var timerText:TextField = new TextField();
            timerText.autoSize = TextFieldAutoSize.LEFT;
            addChild(timerText);
                
            // Initialise a timer
            var time0:int = getTimer()

            // Perform the speed test
            var vector:Vector3D = speedTest1();
            //var vector:Vector3D = speedTest2();
            //var vector:Vector3D = nativeSpeedTest1();
            //var vector:Vector3D = nativeSpeedTest2();
            
            // Calculate the elapsed time
            var time1:int = getTimer()
            var totalTime:int = time1 - time0;
            
            // Display elapsed time and final vector
            timerText.text = "Time taken = " + totalTime + " vector = (" + vector.x + ", " + vector.y + ", " + vector.z + ")";
        }

        /**
         * Speed test using C++ to iteratively calculate the cross products of two vectors
         */
        private function speedTest1():Vector3D {
            var vector1:Vector3D = new Vector3D(0.123, 0.456, 0.789);
            var vector2:Vector3D = new Vector3D(0.987, 0.654, 0.321);

            return vectorUtils.speedTest1(vector1, vector2);
        }

        /**
         * Speed test using C++ to iteratively calculate rotation matrices and apply these to a vector
         */
        private function speedTest2():Vector3D {
            var vector:Vector3D = new Vector3D(0.123, 0.456, 0.789);
            
            return vectorUtils.speedTest2(vector);            
        }

        /**
         * Speed test using AS3 to iteratively calculate the cross products of two vectors
         */
        private function nativeSpeedTest1():Vector3D {
            var vector1:Vector3D = new Vector3D(0.123, 0.456, 0.789);
            var vector2:Vector3D = new Vector3D(0.987, 0.654, 0.321);
            var vector3:Vector3D;
            
            var time0:int = getTimer()
            
            for (var i:int = 0; i < 1000000; i++) {
                vector3 = vector1.crossProduct(vector2);
                vector3.normalize();
                vector1 = vector2;
                vector2 = vector3;
            }
            
            return vector3;
        }

        /**
         * Speed test using AS3 to iteratively calculate rotation matrices and apply these to a vector
         */
        private function nativeSpeedTest2():Vector3D {
            var vector:Vector3D = new Vector3D(0.123, 0.456, 0.789);

            var copy:Vector3D = vector.clone();

            var rotationX:Matrix3D = new Matrix3D();
            var rotationY:Matrix3D = new Matrix3D();
            var rotationZ:Matrix3D = new Matrix3D();

            for (var i:int = 0; i < 1000; i++) {
                vector = copy.clone();
                for (var ang:Number = 0; ang < 180; ang++) {
                    rotationX.identity();
                    rotationX.appendRotation(ang, Vector3D.X_AXIS);
                    rotationY.identity();
                    rotationY.appendRotation(ang, Vector3D.Y_AXIS);
                    rotationZ.identity();
                    rotationZ.appendRotation(ang, Vector3D.Z_AXIS);
                    
                    vector = rotationX.transformVector(vector);
                    vector = rotationY.transformVector(vector);
                    vector = rotationZ.transformVector(vector);
                    
                }
            }
            
            return vector;
        }

    }
}