package {
    
    import org.libspark.thread.EnterFrameThreadExecutor;
    import org.libspark.thread.Thread;
    import org.papervision3d.view.BasicView;
    
    [SWF(width=640, height=480, backgroundColor=0xffffff, frameRate=60)]

    public class MediasMotion extends BasicView {
        
        public function MediasMotion() {
            super(640, 480);
            Thread.initialize(new EnterFrameThreadExecutor());
            new MainThread(this).start();
        }
    }
}


import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.filters.ColorMatrixFilter;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.ByteArray;
import flash.utils.getTimer;

import frocessing.color.ColorHSV;

import nochump.util.zip.ZipFile;

import org.libspark.thread.Thread;
import org.papervision3d.core.effects.BitmapLayerEffect;
import org.papervision3d.core.geom.Particles;
import org.papervision3d.core.geom.renderables.Particle;
import org.papervision3d.materials.special.ParticleMaterial;
import org.papervision3d.view.BasicView;
import org.papervision3d.view.layer.BitmapEffectLayer;
import nochump.util.zip.ZipEntry;
import flash.display.LoaderInfo;
import flash.events.KeyboardEvent;

class MainThread extends Thread {
    
    private var _view:BasicView;
    private var _zip:ZipFile;
    private var _object:Particles;
    private var _currentMotionIndex:int;
    private var _currentMotionData:BitmapData;
    private var _startTime:int;
    
    public function MainThread(view:BasicView) {
        this._view = view;
        this._view.camera.fov = 60;
        
        this._object = this._view.scene.addChild(new Particles()) as Particles;
        this._object.scale = 0.1;
        for (var i:int = 0; i < 27; i++) {
            var pmat:ParticleMaterial = new ParticleMaterial(new ColorHSV(i / 27 * 360).value, 0.7, ParticleMaterial.SHAPE_CIRCLE);
            this._object.addParticle(new Particle(pmat, 20));
        }
        
        var bfx:BitmapEffectLayer = new BitmapEffectLayer(this._view.viewport, 640, 480);
        bfx.addEffect(new BitmapLayerEffect(new BlurFilter(2, 2, 1)));
        bfx.addEffect(new BitmapLayerEffect(new ColorMatrixFilter([
            1, 0, 0, 0, 15,
            0, 1, 0, 0, 15,
            0, 0, 1, 0, 15,
            0, 0, 0, 1, 0,
        ])));
        bfx.addDisplayObject3D(this._object);
        this._view.viewport.containerSprite.addLayer(bfx);
    }    
    
    protected override function run():void {
        var loader:URLLoader = new URLLoader();
        loader.dataFormat = URLLoaderDataFormat.BINARY;
        loader.load(new URLRequest('a.zip'));
        event(loader, Event.COMPLETE, this._onZipLoaded);
    }

    private function _onZipLoaded(e:Event):void {
        this._zip = new ZipFile(ByteArray(URLLoader(e.target).data));
        this._currentMotionIndex = -1;
        this._nextMotion();
    }
    
    private function _nextMotion(e:Event = null):void {
        if (++this._currentMotionIndex == this._zip.entries.length) {
            this._currentMotionIndex = 0;
        }
        var entry:ZipEntry = this._zip.entries[this._currentMotionIndex];
        trace(entry);
        if (entry.name.match(/png$/)) {
            var loader:Loader = new Loader();
            loader.loadBytes(this._zip.getInput(this._zip.entries[this._currentMotionIndex]));
            event(loader.contentLoaderInfo, Event.COMPLETE, this._onMotionLoaded);
        } else {
            next(this._nextMotion);
        }
    }
    
    private function _onMotionLoaded(e:Event):void {
        this._currentMotionData = Bitmap(LoaderInfo(e.target).loader.content).bitmapData;
        this._startTime = getTimer();
        this._update();
    }
    
    private function _update():void {
        var particles:Array = this._object.particles;
        var p:Particle;
        var dx:int = ((getTimer() - this._startTime) /1000 * 30) % this._currentMotionData.width;
        var dy:int;
        var n:int = particles.length;
        for (var i:int = 0; i < n; i++) {
            p = particles[i];
            dy = i * 3;
            p.x = this._currentMotionData.getPixel(dx, dy) - 0xf00000;
            p.y = this._currentMotionData.getPixel(dx, dy + 1) - 0xf00000;
            p.z = this._currentMotionData.getPixel(dx, dy + 2) - 0xf00000;
        }
        //
        p = particles[3];
        this._object.x += (-p.x * this._object.scale - this._object.x) * 0.03;
        this._object.y += (-p.y * this._object.scale - this._object.y) * 0.03;
        this._object.z += (-p.z * this._object.scale - this._object.z) * 0.03;
        this._view.singleRender();
        
        next(this._update);
        event(this._view.stage, MouseEvent.CLICK, this._nextMotion);
        event(this._view.stage, KeyboardEvent.KEY_DOWN, this._nextMotion);
    }
}