<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()"
    layout="absolute" width="500" height="500"  
    backgroundColor="0xFFFFFF" themeColor="0x0066FF" 
    frameRate="60" viewSourceURL="srcview/index.html">
    
    <mx:Script>
        <![CDATA[
            
            import caurina.transitions.Tweener;
            
            import flash.display.Shape;
            import flash.display.Sprite;
            import flash.events.Event;
            import flash.events.KeyboardEvent;
            import flash.events.NetStatusEvent;
            import flash.media.Camera;
            import flash.media.Video;
            import flash.net.NetConnection;
            import flash.net.NetStream;
            import flash.utils.Timer;
            
            import org.papervision3d.cameras.Camera3D;
            import org.papervision3d.materials.ColorMaterial;
            import org.papervision3d.materials.VideoStreamMaterial;
            import org.papervision3d.objects.DisplayObject3D;
            import org.papervision3d.objects.primitives.Plane;
            import org.papervision3d.render.BasicRenderEngine;
            import org.papervision3d.scenes.Scene3D;
            import org.papervision3d.view.Viewport3D;
            
            private var scene                        :Scene3D;
            private var camera                        :Camera3D;
            private var viewport                    :Viewport3D;
            private var box                            :DisplayObject3D = new DisplayObject3D();
            private var obj_front                    :DisplayObject3D = new DisplayObject3D();
            private var obj_back                    :DisplayObject3D = new DisplayObject3D();
            private var obj_left                    :DisplayObject3D = new DisplayObject3D();
            private var obj_right                    :DisplayObject3D = new DisplayObject3D();
            private var obj_top                        :DisplayObject3D = new DisplayObject3D();
            private var obj_bottom                    :DisplayObject3D = new DisplayObject3D();
            private var render                        :BasicRenderEngine;
            
            private var plane_front                    :Plane;
            private var plane_back                    :Plane;
            private var plane_left                    :Plane;
            private var plane_right                    :Plane;
            private var plane_top                    :Plane;
            private var plane_bottom                :Plane;
            
            private var materiel_front                :VideoStreamMaterial;
            private var materiel_back                :VideoStreamMaterial;
            private var materiel_left                :VideoStreamMaterial;
            private var materiel_right                :VideoStreamMaterial;
            private var materiel_top                :ColorMaterial;
            private var materiel_bottom                :ColorMaterial;
            
            private var timer_0                        :Timer;
            private var timer_1                        :Timer;
            
            private var video_0                        :Video;
            private var video_1                        :Video;
            
            private var ns_0                         :NetStream;
            private var ns_1                         :NetStream;
            
            private var nc_0                        :NetConnection;
            private var nc_1                        :NetConnection;
            
            private var custom_client                    :Object = new Object();
            private var metadata_object                    :Object = new Object();
            
            private var list_videos                    :Array;
            
            private var clic_ok                        :Boolean = false;
            
            private var largeur_plane                :int = 320;
            private var hauteur_plane                :int = 240;
            
            private var pos_rotation_y                :Number = 0;
            private var face                        :Number = 0;
        
            private function init():void
            {    
                list_videos = new Array("http://book.jb-interactive.com/experimentation/olcube/assets/clip_benzema.flv", "http://book.jb-interactive.com/experimentation/olcube/assets/clip_govou.flv");
                
                loading_0_txt.text = "";
                loading_1_txt.text = "";
                
                video_0 = new Video(320, 240);
                video_1 = new Video(320, 240);
                
                timer_0 = new Timer(100);
                timer_0.addEventListener(TimerEvent.TIMER, update_timer);
                
                timer_1 = new Timer(100);
                timer_1.addEventListener(TimerEvent.TIMER, update_timer);
            }
            
            private function active_demo(e:MouseEvent):void
            {
                load_videos();
                voir_demo_btn.visible = false;
            }
            
            private function load_videos():void
            {
                nc_0 = new NetConnection();
                nc_0.addEventListener(NetStatusEvent.NET_STATUS, net_0_handler);
                nc_0.connect(null);
                
                nc_1 = new NetConnection();
                nc_1.addEventListener(NetStatusEvent.NET_STATUS, net_1_handler);
                nc_1.connect(null);
            }
            
            private function net_0_handler(e:NetStatusEvent):void
            {
                switch (e.info.code)
                {
                    case "NetConnection.Connect.Success":
                        trace("NetConnection.Connect.Success");
                        connect_stream_0();
                        ns_0.bufferTime = 4;
                        timer_0.start();
                    break;
                    case "NetStream.Play.Start":
                        trace("NetStream.Play.Start");
                    break;
                }
            }
            
            private function net_1_handler(e:NetStatusEvent):void
            {
                switch (e.info.code)
                {
                    case "NetConnection.Connect.Success":
                        trace("NetConnection.Connect.Success");
                        connect_stream_1();
                        ns_1.bufferTime = 4;
                        timer_1.start();
                        init3d();
                    break;
                    case "NetStream.Play.Start":
                        trace("NetStream.Play.Start");
                    break;
                }
            }
            
            private function connect_stream_0():void
            {
                ns_0 = new NetStream(nc_0);
                ns_0.addEventListener(NetStatusEvent.NET_STATUS, net_0_handler);
                video_0.attachNetStream(ns_0);
                
                custom_client.onMetaData = metadata_handler;
                ns_0.client = custom_client;
            
                ns_0.play(list_videos[0]);;
                ns_0.pause();
            }
            
            private function connect_stream_1():void
            {
                ns_1 = new NetStream(nc_1);
                ns_1.addEventListener(NetStatusEvent.NET_STATUS, net_1_handler);
                video_1.attachNetStream(ns_1);
                
                custom_client.onMetaData = metadata_handler;
                ns_1.client = custom_client;
                
                ns_1.play(list_videos[1]);
                ns_1.pause();
            }
            
            private function metadata_handler(info:Object):void
            {
                for(var prop:* in info)
                {
                    metadata_object[prop] = info[prop];
                    trace("PROP : " + prop + " - " + metadata_object[prop]);
                }
            }
            
            private function update_timer(e:TimerEvent):void
            {
                loading_0_txt.text = "chargement de la première vidéo";
                loading_1_txt.text = "chargement de la seconde vidéo";
                
                var percent_0:Number = Math.floor((ns_0.bytesLoaded / ns_0.bytesTotal) * 100);
                var percent_1:Number = Math.floor((ns_1.bytesLoaded / ns_1.bytesTotal) * 100);
                
                loading_percent_0_txt.text = percent_0 + " %";
                loading_percent_1_txt.text = percent_1 + " %";
                
                if(percent_0 == 100 && percent_1 == 100)
                {
                    timer_0.stop();
                    timer_1.stop();
                    timer_0.removeEventListener(TimerEvent.TIMER, update_timer);
                    timer_1.removeEventListener(TimerEvent.TIMER, update_timer);
                    
                    Tweener.addTween(loading, {alpha:0, time:1, transition:"easeOutSine", onComplete:start_animation});
                    
                    loading_0_txt.text = "";
                    loading_percent_0_txt.text = "";
                    loading_1_txt.text = "";
                    loading_percent_1_txt.text = "";
                }
            }
            
            private function init3d():void
            {
                var sprite:Sprite = new Sprite();
                base.rawChildren.addChild(sprite);
                
                var rect:Shape = new Shape();
                rect.graphics.beginFill(0xFFFFFF, 1);
                rect.graphics.drawRect(0, 100, 500, 400);
                rect.graphics.endFill();
                sprite.addChild(rect);
                
                scene = new Scene3D();
                
                scene.addChild(box);
                box.y = -(hauteur_plane / 2) - 39;
                
                camera = new Camera3D(null, 3, 420);
                camera.x = -50000;
                camera.y = 10000;
                camera.z = -50000;
                
                viewport = new Viewport3D(50, 50, true);
                base.rawChildren.addChild(viewport);
                
                materiel_front = new VideoStreamMaterial(video_0, ns_0);
                materiel_back = new VideoStreamMaterial(video_0, ns_0);
                materiel_left = new VideoStreamMaterial(video_1, ns_1);
                materiel_right = new VideoStreamMaterial(video_1, ns_1);
                materiel_top = new ColorMaterial(0xCC0000, 1);
                materiel_bottom = new ColorMaterial(0xCC0000, 1);
                
                materiel_front.doubleSided = materiel_back.doubleSided = materiel_left.doubleSided = materiel_right.doubleSided = materiel_top.doubleSided = materiel_bottom.doubleSided = true;
                
                plane_front = new Plane(materiel_front, largeur_plane, hauteur_plane, 10, 10);
                plane_back = new Plane(materiel_back, largeur_plane, hauteur_plane, 10, 10);
                plane_left = new Plane(materiel_left, largeur_plane, hauteur_plane, 10, 10);
                plane_right = new Plane(materiel_right, largeur_plane, hauteur_plane, 10, 10);
                plane_top = new Plane(materiel_top, largeur_plane, largeur_plane, 10, 10);
                plane_bottom = new Plane(materiel_bottom, largeur_plane, largeur_plane, 10, 10);
                
                plane_bottom.rotationX = -90;
                obj_bottom.addChild(plane_bottom);
                box.addChild(obj_bottom);
                
                plane_back.rotationX = -90;
                plane_back.rotationZ = 180;
                plane_back.z = hauteur_plane / 2;
                obj_back.addChild(plane_back);
                obj_back.z = largeur_plane / 2;
                box.addChild(obj_back);
                
                plane_front.rotationX = 90;
                plane_front.z = -(hauteur_plane / 2);
                obj_front.addChild(plane_front);
                obj_front.z = -(largeur_plane / 2);
                box.addChild(obj_front);
                
                plane_left.rotationX = 180;
                plane_left.rotationY = 90;
                plane_left.rotationZ = -90;
                plane_left.x = -(hauteur_plane / 2);
                obj_left.addChild(plane_left);
                obj_left.x = -(largeur_plane / 2);
                box.addChild(obj_left);
                
                plane_right.rotationX = 180;
                plane_right.rotationY = -90;
                plane_right.rotationZ = 90;
                plane_right.x = hauteur_plane / 2;
                obj_right.addChild(plane_right);
                obj_right.x = largeur_plane / 2;
                box.addChild(obj_right);
                
                plane_top.rotationX = -90;
                plane_top.x = largeur_plane / 2;
                obj_top.addChild(plane_top);
                obj_top.x = hauteur_plane;
                obj_right.addChild(obj_top);
                
                render = new BasicRenderEngine();
            }
            
            private function run(e:Event):void
            {
                render.renderScene(scene, camera, viewport);
            }
            
            private function start_animation():void
            {
                ns_0.seek(5.5);
                ns_1.seek(5);
                
                stage.addEventListener(Event.ENTER_FRAME, run);
                stage.addEventListener(KeyboardEvent.KEY_UP, key_handler);
                
                Tweener.addTween(camera, {x:-2000, y:500, z:-2500, delay:1, time:1.5, transition:"easeOutSine", onComplete:anim_obj_back});
            }
            
            private function anim_obj_back():void
            {
                Tweener.addTween(obj_back, {rotationX:90, time:.5, transition:"easeOutSine", onComplete:anim_obj_left});
            }
            
            private function anim_obj_left():void
            {
                Tweener.addTween(obj_left, {rotationZ:-90, time:.5, transition:"easeOutSine", onComplete:anim_obj_right});
            }
            
            private function anim_obj_right():void
            {
                Tweener.addTween(obj_right, {rotationZ:90, time:.5, transition:"easeOutSine", onComplete:anim_obj_top});
            }
            
            private function anim_obj_top():void
            {
                Tweener.addTween(obj_top, {rotationZ:90, time:.5, transition:"easeOutSine", onComplete:anim_obj_front});
            }
            
            private function anim_obj_front():void
            {
                Tweener.addTween(obj_front, {rotationX:-90, time:.5, transition:"easeOutSine", onComplete:rotation_box});
            }
            
            private function rotation_box():void
            {
                Tweener.addTween(box, {rotationY:360, time:1, transition:"linear", onComplete:placement_camera});
            }
            
            private function placement_camera():void
            {
                Tweener.addTween(camera, {x:0, y:0, z:-1000, zoom:4, time:.5, transition:"easeOutSine", onComplete:play_flv});
            }
            
            private function play_flv():void
            {
                ns_0.resume();
                clic_ok = true;
            }
            
            private function key_handler(e:KeyboardEvent):void
            {
                if(clic_ok == true)
                {
                    clic_ok = false;
                    
                    switch(face)
                    {
                        case 0:
                            ns_0.pause();
                        break;
                        case 1:
                            ns_1.pause();
                        break;
                        case 2:
                            ns_0.pause();
                        break;
                        case 3:
                            ns_1.pause();
                        break;
                    }
                
                    switch(e.keyCode)
                    {
                        case 37:
                            Tweener.addTween(camera, {y:900, z:-2000, zoom:3, time:1, transition:"easeOutSine"});
                            Tweener.addTween(box, {rotationY:(box.rotationY - 90), delay:1, time:1, transition:"easeOutSine"});
                            Tweener.addTween(camera, {x:0, y:0, z:-1000, zoom:4, delay:2, time:.5, transition:"easeOutSine", onComplete:update_rotation_y});
                        break;
                        case 39:
                            Tweener.addTween(camera, {y:900, z:-2000, zoom:3, time:1, transition:"easeOutSine"});
                            Tweener.addTween(box, {rotationY:(box.rotationY + 90), delay:1, time:1, transition:"easeOutSine"});
                            Tweener.addTween(camera, {x:0, y:0, z:-1000, zoom:4, delay:2, time:.5, transition:"easeOutSine", onComplete:update_rotation_y});
                        break;
                    }
                }
            }
            
            private function update_rotation_y():void
            {
                pos_rotation_y = (box.rotationY / 90);
                face = pos_rotation_y % 4;
                
                switch(face)
                {
                    case 0:
                        ns_0.resume();
                    break;
                    case 1:
                        ns_1.resume();
                    break;
                    case 2:
                        ns_0.resume();
                    break;
                    case 3:
                        ns_1.resume();
                    break;
                }
                
                clic_ok = true;
            }
            
        ]]>
    </mx:Script>
    
    <mx:Style source="main.css"/>
    
    <mx:Canvas id="base" width="100%" height="100%" backgroundColor="0xFFFFFF" backgroundAlpha="1">
        <mx:Image id="logo" x="10" y="10" source="@Embed('assets/logo_noir.png')"/>
        <mx:Text x="98" y="10" text="Vous pouvez faire pivoter le cube de 90°&#xa;sur la droite ou sur la gauche en utilisant les flèches&#xa;gauche et droite de votre clavier." width="392" height="48" fontWeight="bold" textAlign="center" color="#0066FF"/>
    </mx:Canvas>
    
    <mx:Canvas id="loading" width="100%" height="100%" backgroundColor="0xFFFFFF" backgroundAlpha="1">
        <mx:Image x="210" y="90" source="@Embed('assets/logo_noir.png')"/>
        <mx:Text id="loading_0_txt" x="153.5" y="208" textAlign="center" styleName="texte" fontWeight="bold" color="#0066FF" selectable="false"/>
        <mx:Text id="loading_percent_0_txt" x="220" y="228" width="50" textAlign="center" styleName="texte" fontWeight="bold" color="#0066FF" selectable="false"/>
        <mx:Text id="loading_1_txt" x="158.5" y="268" textAlign="center" styleName="texte" fontWeight="bold" color="#0066FF" selectable="false"/>
        <mx:Text id="loading_percent_1_txt" x="220" y="288" width="50" textAlign="center" styleName="texte" fontWeight="bold" color="#0066FF" selectable="false"/>
        <mx:Button id="voir_demo_btn" x="160.5" y="248" label="VOIR LA DÉMONSTRATION" click="active_demo(event)"/>
    </mx:Canvas>
    
</mx:Application>