package {
    
    import de.popforge.parameter.Parameter;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.Sprite;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.BlurFilter;
    import flash.filters.ColorMatrixFilter;
    import flash.filters.ConvolutionFilter;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.net.SharedObject;
    
    import mx.core.BitmapAsset;
    
    import net.saqoosha.gui.ParameterSlider;
    import net.saqoosha.motion.PointEasingHelper;
    import net.saqoosha.util.LayoutUtil;
    
    [SWF(width=960,height=720,backgroundColor=0x0,frameRate=30)]

    public class MoyasuComplete extends Sprite {
        
        private static const ZERO_POINT:Point = new Point();
        
        [Embed(source="fire-color.png")]
        private static const fireColorClass:Class;
        private static const fireColorImage:BitmapData = BitmapAsset(new fireColorClass()).bitmapData;
        
        private var _camera:Camera;
        private var _video:Video;
        private var _captrue:BitmapData;
        private var _black:BitmapData;
        private var _greyFilter:ColorMatrixFilter;
        
        private var _canvas:Sprite;
        private var _emitter:Sprite;
        private var _easing:PointEasingHelper;
        private var _step1:BitmapData;
        private var _spread:ConvolutionFilter;
        private var _cooling:BitmapData;
        private var _color:ColorMatrixFilter;
        private var _offset:Array;
        private var _fire:BitmapData;
        private var _palette:Array;
        private var _zeroArray:Array;
        
        private var _upScrollSlider:ParameterSlider;
        private var _sideScorllSlider:ParameterSlider;
        private var _coolingSlider:ParameterSlider;
        private var _noiseSizeSlider:ParameterSlider;
        private var _colorSlider:ParameterSlider;
        private var _thresholdSlider:ParameterSlider;
        
        public function MoyasuComplete() {
            this.stage.scaleMode = StageScaleMode.NO_SCALE;
            
            this._camera = Camera.getCamera();
            this._camera.setMode(320, 240, 30);
            this._video = new Video(320, 240);
            this._video.attachCamera(this._camera);
            this.addChild(this._video);
            this._video.x = 0;
            this._video.y = 480;
            
            this._captrue = new BitmapData(320, 240, false, 0x0);
            
            this._black = new BitmapData(320, 240, true, 0x0);
            var bm:Bitmap = this.addChild(new Bitmap(this._black)) as Bitmap;
            bm.x = 320;
            bm.y = 480;
            
            this._greyFilter = new ColorMatrixFilter([
                0.299, 0.587, 0.114, 0, 0,
                0.299, 0.587, 0.114, 0, 0,
                0.299, 0.587, 0.114, 0, 0,
                0, 0, 0, 1, 0
            ]);
            
            this._canvas = this.addChild(new Sprite()) as Sprite;
            this._canvas.graphics.beginFill(0x0, 0);
            this._canvas.graphics.drawRect(0, 0, 320, 240);
            this._canvas.graphics.endFill();
            this._canvas.addEventListener(MouseEvent.MOUSE_MOVE, this._onMouseMove);
            
            this._emitter = this._canvas.addChild(new Sprite()) as Sprite;
            this._emitter.x = 160;
            this._emitter.y = 120;
            this._emitter.graphics.lineStyle(5, 0xffffff);
            this._emitter.graphics.drawCircle(-10, -10, 20);
            this._easing = new PointEasingHelper(160, 120, 50);
            
            this._step1 = new BitmapData(320, 240, false, 0x0);
            bm = this.addChild(new Bitmap(this._step1)) as Bitmap;
            bm.x = 320;
            
            this._spread = new ConvolutionFilter(3, 3, [0, 1, 0,  1, 1, 1,  0, 1, 0], 5);
            
            this._cooling = new BitmapData(320, 240, false, 0x0);
            this._offset = [new Point(), new Point()];
            bm = this.addChild(new Bitmap(this._cooling)) as Bitmap;
            bm.y = 240;
            bm.filters = [new ColorMatrixFilter([
                10, 0, 0, 0, 0,
                0, 10, 0, 0, 0,
                0, 0, 10, 0, 0,
                0, 0, 0, 10, 0
            ])];
            
            this._fire = new BitmapData(320, 240, false, 0x0);
            bm = this.addChild(new Bitmap(this._fire)) as Bitmap;
            bm.x = 640;
            
            bm = this.addChild(new Bitmap(fireColorImage)) as Bitmap;
            bm.x = 320;
            bm.y = 240;
            
            var composite:Sprite = this.addChild(new Sprite()) as Sprite;
            composite.x = 640;
            composite.y = 480;
            composite.addChild(new Bitmap(this._captrue));
            bm = composite.addChild(new Bitmap(this._fire)) as Bitmap;
            bm.blendMode = BlendMode.ADD;
//            bm.alpha = 0.85;
//            bm.filters = [new BlurFilter(4, 4)];
            
            this.addEventListener(Event.ENTER_FRAME, this._update);
            
            var so:SharedObject = SharedObject.getLocal('parameters');
            LayoutUtil.alignVertical(640 + 10, 240 + 10, 2, [
                this._upScrollSlider = this.addChild(ParameterSlider.createInt(0, 5, 1, 300, 'up', so)) as ParameterSlider,
                this._sideScorllSlider = this.addChild(ParameterSlider.createNumber(-5, 5, 0.8, 300, 'side', so)) as ParameterSlider,
                this._coolingSlider = this.addChild(ParameterSlider.createNumber(0, 0.5, 0.05, 300, 'cooling', so)) as ParameterSlider,
                this._noiseSizeSlider = this.addChild(ParameterSlider.createNumber(10, 100, 50, 300, 'size', so)) as ParameterSlider,
                this._colorSlider = this.addChild(ParameterSlider.createInt(0, 5, 0, 300, 'color', so)) as ParameterSlider,
                this._thresholdSlider = this.addChild(ParameterSlider.createInt(0, 64, 0x20, 300, 'threshold', so)) as ParameterSlider
            ]);
            this._coolingSlider.parameter.addChangedCallbacks(function (parameter:Parameter, oldValue:*, newValue:*):void {
                createCooling(newValue);
            });
            this._colorSlider.parameter.addChangedCallbacks(function (parameter:Parameter, oldValue:*, newValue:*):void {
                createPalette(newValue);
            });
            
            this.createCooling(this._coolingSlider.value);
            this.createPalette(this._colorSlider.value);
        }
        
        private function _onMouseMove(e:MouseEvent):void {
            this._easing.update(this._canvas.mouseX, this._canvas.mouseY);
        }
        
        private function createCooling(a:Number):void {
            this._color = new ColorMatrixFilter([
                a, 0, 0, 0, 0,
                0, a, 0, 0, 0,
                0, 0, a, 0, 0,
                0, 0, 0, 1, 0
            ]);
        }
        
        private function createPalette(idx:int):void {
            this._palette = [];
            this._zeroArray = [];
            for (var i:int = 0; i < 256; i++) {
                this._palette.push(fireColorImage.getPixel(i, idx * 32));
                this._zeroArray.push(0);
            }
        }
        
        private function _update(e:Event):void {
            this._captrue.draw(this._video);
            this._black.applyFilter(this._captrue, this._captrue.rect, ZERO_POINT, this._greyFilter);
//            this._easing.update(NaN, NaN);
//            this._emitter.x = this._easing.currentX;
//            this._emitter.y = this._easing.currentY;
//            this._step1.draw(this._canvas);
            this._step1.threshold(this._black, this._black.rect, ZERO_POINT, '<=', this._thresholdSlider.value, 0xffffffff, 0xff);
            this._step1.applyFilter(this._step1, this._step1.rect, ZERO_POINT, this._spread);
            this._cooling.perlinNoise(this._noiseSizeSlider.value, this._noiseSizeSlider.value, 2, 982374, false, false, 0, true, this._offset);
            this._offset[0].x += this._sideScorllSlider.value;
            this._offset[1].y += this._sideScorllSlider.value * 0.7;
            this._cooling.applyFilter(this._cooling, this._cooling.rect, ZERO_POINT, this._color);
            this._step1.draw(this._cooling, null, null, BlendMode.SUBTRACT);
            this._step1.scroll(0, -this._upScrollSlider.value);
            this._fire.paletteMap(this._step1, this._step1.rect, ZERO_POINT, this._palette, this._zeroArray, this._zeroArray, this._zeroArray);
        }
        
    }
    
}