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.text.TextField;
    import flash.text.TextFormat;
    import flash.utils.ByteArray;
    
    import net.hires.debug.Stats;

    [SWF(width=320,height=240,frameRate=30)]
    public class VideoTest extends Sprite
    {
        [Embed("assets/sepia.pbj", mimeType="application/octet-stream")]
        private var SepiaFilter:Class;
        [Embed("assets/dynamic_palette.pbj", mimeType="application/octet-stream")]
        private var DynamicFilter:Class;
        
        private static const BUFFER_LEN:int=24;

        private var _camera:Camera;
        private var _video:Video;
        private var _buffer:Array=[];
        private var _index:int=0;

        private var _current:Bitmap;

        private var _iSightIndex:int;
        private var _hasISight:Boolean;
        private var _cameraIndex:int;
        
        private var _sepiaShader:Shader;
        private var _sepiafilter:ShaderFilter;
        private var _dynamicShader:Shader;
        private var _dynamicfilter:ShaderFilter;
        
        private var _clickIndex:int = 0;

        public function VideoTest()
        {
            // 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(320, 240, 30);
            this._video=new Video(320, 240);
            this._video.attachCamera(this._camera);

            // create image buffer
            for (var i:int=0; i < BUFFER_LEN; i++)
            {
                var bm:BitmapData=new BitmapData(320, 240, false, 0);
                this._buffer.push(bm);                
            }
            
            // add bitmap
            this._current=this.addChild(new Bitmap()) as Bitmap;
            
            // set message
            var textField:TextField = new TextField();
            textField.text = "click here";
            textField.width = 100;
            textField.height = 20;
            textField.setTextFormat(new TextFormat("Verdana",10,0xffffff));
            this.addChild(textField);
            
            // show stats
            var stats:Stats = new Stats();
            stats.x = 320 - 70;
            this.addChild(stats);
            
            // set filters
            this._sepiaShader = new Shader(new SepiaFilter() as ByteArray);
            this._dynamicShader = new Shader(new DynamicFilter() as ByteArray);            
            this._sepiaShader.data.intensity.value[0] = 0;
            this._sepiafilter = new ShaderFilter(this._sepiaShader);            
            this._dynamicShader.data.palette.value[0] = 7;
            this._dynamicfilter = new ShaderFilter(this._dynamicShader);
            
            // on enter frame
            this.addEventListener(Event.ENTER_FRAME, this._update);
            
            // on click
            stage.addEventListener(MouseEvent.CLICK, this._click);            
        }
        
        private function _click(e:Event):void {
            this._clickIndex++;
            if(this._clickIndex == 3) {
                this._clickIndex = 0;
            }
        }

        private function _update(e:Event):void
        {
            // draw image on buffer
            BitmapData(this._buffer[this._index]).draw(this._video);
            
            // set new index to replace image
            this._index = int(Math.random() * BUFFER_LEN);
            
            // filters
            switch(this._clickIndex) {
                case(0):
                    this._current.filters = [_dynamicfilter, _sepiafilter];
                break;                
                case(1):
                    this._current.filters = [_dynamicfilter];
                break;
                default:
                    this._current.filters = [];
                break;
            }
            
            // set current visible image
            this._current.bitmapData=this._buffer[int(Math.random() * BUFFER_LEN)];
        }
    }
}