<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="initApp()" styleName="plain" horizontalAlign="center" paddingTop="15" viewSourceURL="srcview/index.html">
  
  <mx:Script>
  <![CDATA[
    import pbjAS.PBJParam;
    import pbjAS.ops.OpSub;
    import pbjAS.ops.OpAdd;
    import pbjAS.ops.OpDiv;
    import pbjAS.ops.OpRSqrt;
    import pbjAS.ops.OpSqrt;
    import flash.utils.ByteArray;
    
    import mx.controls.Alert;
 
    import pbjAS.ops.OpMov;
    import pbjAS.ops.OpMul;
    import pbjAS.regs.RFloat;
    import pbjAS.PBJType;
    import pbjAS.params.Parameter;
    import pbjAS.PBJ;
    import pbjAS.PBJAssembler;
    import pbjAS.PBJChannel;
    import pbjAS.params.Texture;
    import pbjAS.ops.OpSampleNearest;
  
    [Bindable] private var initDone:Boolean = false;
    [Bindable] private var running:Boolean = false;

    private var timer:Timer;
    
    private var testShader:Shader;
    private var shaderJob:ShaderJob
    
    private function initApp():void
    {
      var width:Number = 1000;
      var height:Number = 1000;
      
      var myPBJ:PBJ = new PBJ();
      myPBJ.version = 1;
      myPBJ.name = "TestOpSampleNearest";
      myPBJ.metadatas = [];
      myPBJ.parameters = [new PBJParam("_OutCoord", new Parameter(PBJType.TFloat2, false, new RFloat(0, [PBJChannel.R, PBJChannel.G]))), // f0.rg
        new PBJParam("texture", new Texture(1, 0)), // t0
        new PBJParam("result", new Parameter(PBJType.TFloat2, true, new RFloat(1, [PBJChannel.R, PBJChannel.B]))) // f1.rg
        ];
      myPBJ.code = [
        new OpSampleNearest(new RFloat(1, [PBJChannel.R, PBJChannel.G]), new RFloat(0, [PBJChannel.R, PBJChannel.G]), 0) // texn    f1.rg, f0.rg, t0
        ];
        
      for (var k:int = 0; k < 1000; k++)
      {
        myPBJ.code.push(new OpSqrt(new RFloat(1, [PBJChannel.R, PBJChannel.G]), new RFloat(1, [PBJChannel.R, PBJChannel.G]))); // sqrt f1.rg, f1.rg
        myPBJ.code.push(new OpRSqrt(new RFloat(1, [PBJChannel.R, PBJChannel.G]), new RFloat(1, [PBJChannel.R, PBJChannel.G]))); // rsqrt f1.rg, f1.rg
        myPBJ.code.push(new OpMul(new RFloat(1, [PBJChannel.R, PBJChannel.G]), new RFloat(1, [PBJChannel.R, PBJChannel.G]))); // mul f1.rg, f1.rg
        myPBJ.code.push(new OpDiv(new RFloat(1, [PBJChannel.R, PBJChannel.G]), new RFloat(1, [PBJChannel.R, PBJChannel.G]))); // div f1.rg, f1.rg
        myPBJ.code.push(new OpAdd(new RFloat(1, [PBJChannel.R, PBJChannel.G]), new RFloat(1, [PBJChannel.R, PBJChannel.G]))); // add f1.rg, f1.rg
        myPBJ.code.push(new OpSub(new RFloat(1, [PBJChannel.R, PBJChannel.G]), new RFloat(1, [PBJChannel.R, PBJChannel.G]))); // sub f1.rg, f1.rg
      }

      var assembledPBJByteArray:ByteArray = PBJAssembler.assemble(myPBJ);

      var texture:Vector.<Number> = new Vector.<Number>();

      for (var i:int = 1; i <= height; i++)
      {
        for (var j:int = 1; j <= width; j++)
        {
          texture.push(j * i);
          texture.push(j / i);
        }
      }

      testShader = new Shader(assembledPBJByteArray);

      testShader.data.texture.width = width;
      testShader.data.texture.height = height;
      testShader.data.texture.input = texture;
      
      initDone = true;
    }
    
    private function startJob():void
    {
      running = true;
      
      timer = new Timer(100);
      timer.addEventListener(TimerEvent.TIMER, tick);
      timer.start();
      
      moveRight.play();
      
      var result:Vector.<Number> = new Vector.<Number>;

      shaderJob = new ShaderJob(testShader, result, width, height);
      shaderJob.addEventListener(Event.COMPLETE, onFloatShaderJobComplete);
      shaderJob.start();
    }
    
    private function tick(event:TimerEvent):void
    {
      ta.text = (shaderJob.progress * 100) + "% complete";
    }
    
    private function onFloatShaderJobComplete(event:ShaderEvent):void
    {
      shutDownJob();
      ta.text = "done! \n";
    }
    
    private function stopJob():void
    {
      shaderJob.cancel();
      shaderJob.removeEventListener(Event.COMPLETE, onFloatShaderJobComplete);
      shaderJob = null;
      shutDownJob();
    }
    
    private function shutDownJob():void
    {
      running = false;
      timer.stop();
    }
      
  ]]>
  </mx:Script>
  
  <mx:Move id="moveRight" xTo="240" target="{i}">
    <mx:effectEnd>
      if (running)
      {
        moveLeft.play();
      }
    </mx:effectEnd>
  </mx:Move>
  <mx:Move id="moveLeft" xTo="0" target="{i}">
  <mx:effectEnd>
      if (running)
      {
        moveRight.play();
      }
    </mx:effectEnd>
  </mx:Move>
  
  <mx:Label text="Run 6000 operations on 1,000,000 numbers."/>
  
  <mx:HBox>
    <mx:Button label="start" click="startJob()" enabled="{initDone &amp;&amp; !running}"/>
    <mx:Button label="cancel" click="stopJob()" enabled="{running}"/>
  </mx:HBox>
  
  <mx:Label id="ta"/>
  
  <mx:Panel title="Look Ma! The UI isn't locked!" width="300" layout="absolute">
    <mx:Image id="i" source="@Embed('jamescowboy.jpg')"/>
  </mx:Panel>
  
</mx:Application>