package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Shader;
    import flash.display.Sprite;
    import flash.events.ErrorEvent;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.ShaderFilter;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.utils.ByteArray;
    
    import net.hires.debug.Stats;


    [SWF(width=400,height=300,frameRate=30)]
    public class HalfToneVideoEffect extends Sprite
    {
        [Embed("assets/halftone.pbj", mimeType="application/octet-stream")]
        private var HalfToneFilter:Class;
        
        private var _camera:Camera;
        private var _video:Video;
        private var _bmpEffect:BitmapData;
        private var _bmpNormal:BitmapData;
        
        private var _currentEffect:Bitmap;
        private var _currentNormal:Bitmap;

        private var _iSightIndex:int;
        private var _hasISight:Boolean;
        private var _cameraIndex:int;
        
        private var _halfToneShader:Shader;
        private var _halfTonefilter:ShaderFilter;
        
        private var _clickIndex:int = 0;
        
        private var _mask:Sprite;

        public function HalfToneVideoEffect()
        {
            // Search Mac iSight
            while (_cameraIndex < Camera.names.length) { 
                // Check camera label
                if (Camera.names[_cameraIndex] == "USB Video Class Video") { 
                    // found Mac iSight
                    _hasISight = true;
                    _iSightIndex = _cameraIndex;
                    break;
                }       
                _cameraIndex++;
            }
            
            if (_hasISight) { // mac iSight
                this._camera = Camera.getCamera(String(_iSightIndex));
            }
            else { // default webcam
                this._camera = Camera.getCamera();
            }
            if (!this._camera) { // no webcam  
                this.dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, "no webcam!"));    
                return;            
            }    
            
            // set camera mode
            this._camera.setMode(400, 300, 30);
            this._video=new Video(400, 300);
            this._video.attachCamera(this._camera);

            // create image buffers
            this._bmpEffect = new BitmapData(400, 300, false, 0);
            this._bmpNormal = new BitmapData(400, 300, false, 0);
            
            // add bitmaps
            this._currentEffect=this.addChild(new Bitmap()) as Bitmap;
            this._currentNormal=this.addChild(new Bitmap()) as Bitmap;
            
            // set mask
            this._mask = new Sprite();
            this._mask.graphics.beginFill(0x000000, 1);
            this._mask.graphics.drawRect(0, 0, 400, 300);
            this._mask.graphics.endFill();
            
            this._currentNormal.mask = this._mask;
            
            // show stats
            var stats:Stats = new Stats();
            stats.x = 400 - 70;
            //this.addChild(stats);
            
            // set filter
            this._halfToneShader = new Shader(new HalfToneFilter() as ByteArray);
            this._halfToneShader.data.angle.value[0] = 45;
            this._halfToneShader.data.max_dot_size.value[0] = 5;
            this._halfToneShader.data.gamma.value[0] = 1;
            this._halfToneShader.data.dot_spacing.value[0] = 4;
            this._halfTonefilter = new ShaderFilter(this._halfToneShader);            
            
            // on enter frame
            this.addEventListener(Event.ENTER_FRAME, this._update);
            
            // on click
            stage.addEventListener(MouseEvent.CLICK, this._click);  
        }
        
        private var _mode:int = 0;
        private var _clickCounter:int = 0;
        
        private function _click(e:MouseEvent):void {
            _clickCounter++;
            this._mode = _clickCounter % 4;
        }

        private function _update(e:Event):void
        {
            // get images from video
            this._bmpEffect.draw(this._video);
            this._bmpNormal.draw(this._video);
            
            // apply filter
            this._currentEffect.filters = [_halfTonefilter];
            
            // set images
            this._currentEffect.bitmapData=this._bmpEffect;
            this._currentNormal.bitmapData=this._bmpNormal;
            
            // set mask
            this._mask.graphics.clear();
            this._mask.graphics.beginFill(0x000000, 1);
            if(this._mode == 0) {
                this._mask.graphics.drawRect(0,0,this.mouseX,300);
            }
            else if(this._mode == 1) {
                this._mask.graphics.drawRect(this.mouseX,0,400,300);
            }
            else if(this._mode == 2) {
                this._mask.graphics.drawRect(0,0,400,this.mouseY);
            }
            else if(this._mode == 3) {
                this._mask.graphics.drawRect(0,this.mouseY,400,300);
            }
            this._mask.graphics.endFill();
            
            
        }
    }
}