//******************************************************************************
// DiffusionCanvas.java:        Canvas
//
//******************************************************************************
import java.applet.Applet;
import java.awt.*;
//import gjt.*;

class DiffusionCanvas3 extends Panel implements Runnable
{
        // THREAD SUPPORT:
        //              m_diffusion     is the Thread object for the applet
        //--------------------------------------------------------------------------
        Thread  m_diffusion = null;
        //Thread        m_watch = null;
        protected Applet applet;
        public int NUM_PARTICLE=200, rate, n_runs, total_sum, total_sum2; 
        double tcontin, tcontout;
        public Particle p[];
        public double Cinr, Coutr;
        protected Graphics m_g,m_r;
        protected Image m_image,m_ready;
        protected Dimension m_dimImage;
        protected int Tick=0;
        protected Color BG=new Color(153,204,204);
        protected Point Start,UL,LR;
        protected boolean ResetLocation=false;
        protected boolean ImageReady=false;

        public Membrane m_Membrane;
        protected int m_Barrier=-1;
        int Rin,Rout,Bin,Bout,VU2=0;
        protected int m_InnerLoop;
        //ReportLabel R_in=new ReportLabel("+100"), 
        //  R_out=new ReportLabel("+0"), 
        //  B_in=new ReportLabel("-100"), 
        //  B_out=new ReportLabel("-0"), 
        //  Voltage=new ReportLabel("-60 mV");
        protected Label R_in=new Label("100"), 
          R_out=new Label("000"), 
          B_in=new Label("100"), 
          B_out=new Label("000"), 
          Voltage=new Label("0"),
          Average=new Label("0");

        // diffusion Class Constructor
        //--------------------------------------------------------------------------
        public DiffusionCanvas3(Applet applet)
        {
                this.applet=applet;
        }

        
        public DiffusionCanvas3(){}
        
        // APPLET INFO SUPPORT:
        //              The getAppletInfo() method returns a string describing the applet's
        // author, copyright date, or miscellaneous information.
    //--------------------------------------------------------------------------
        public String getAppletInfo()
        {
                return "Name: diffusion\r\n" +
                       "Author: Joe Patlak\r\n" +
                       "Created with Microsoft Visual J++ Version 1.0";
        }


        // The init() method is called by the AWT when an applet is first loaded or
        // reloaded.  Override this method to perform whatever initialization your
        // applet needs, such as initializing data structures, loading images or
        // fonts, creating frame windows, setting the layout manager, or adding UI
        // components.
    //--------------------------------------------------------------------------
        public void init()
        {
                Dimension dim=size();
                int nWidth=dim.width;
                int nHeight=dim.height;
            //    Start= new Point((int)Math.round(Math.random()*35),(int)Math.round(Math.random()*35));
                m_InnerLoop=0;
                UL=new Point(0,0);
                LR=new Point(nWidth-5,nHeight-5);

                m_Membrane=new Membrane();
                m_Membrane.SetVoltage(0);
                m_Membrane.addElement(0.2);
                m_Membrane.addElement(0.0);

                m_Barrier=nWidth/2;


                int charge=1;
                p = new Particle[NUM_PARTICLE];

                for (int i=0; i<NUM_PARTICLE; i++){
                        Start= new Point((int)Math.round(Math.random()*dim.width/2)-15,(int)Math.round(Math.random()*dim.height));
                        if (i>=NUM_PARTICLE/2) charge=1;
                        p[i]= new Particle(applet,charge,Start,UL,LR);
                        p[i].m_StdDev=5.0;
                        p[i].BG=getBackground();
                        p[i].m_Barrier=m_Barrier;
                        p[i].m_Membrane=m_Membrane;
                        p[i].m_MembraneIndex=0;
                        // if (i<NUM_PARTICLE/2) p[i].m_MembraneIndex=0;
                        // else p[i].m_MembraneIndex=1;
                }
                /*
                charge=1;
                for (int i=0; i<20; i++){
                        if (i>=10) charge=-1;
                        p[i+NUM_PARTICLE]= new Particle(applet,charge,LR,UL,LR);
                        p[i+NUM_PARTICLE].m_StdDev=5.0;
                        p[i+NUM_PARTICLE].BG=getBackground();
                        p[i+NUM_PARTICLE].m_Barrier=m_Barrier;
                        p[i+NUM_PARTICLE].m_Membrane=m_Membrane;
                        //p[i].m_MembraneIndex=0;
                        if (i<10) p[i+NUM_PARTICLE].m_MembraneIndex=0;
                        else p[i+NUM_PARTICLE].m_MembraneIndex=1;
                }
                                                         
                */



                ResizeImage();


                R_in.setAlignment(Label.CENTER);
                B_in.setAlignment(Label.CENTER);
                R_out.setAlignment(Label.CENTER);
                R_out.setAlignment(Label.CENTER);
                Voltage.setAlignment(Label.CENTER);
                Average.setAlignment(Label.CENTER);
        }

        // Place additional applet clean up code here.  destroy() is called when
        // when you applet is terminating and being unloaded.
        //-------------------------------------------------------------------------
        public void destroy(){
        }

        // diffusion Paint Handler
        //--------------------------------------------------------------------------
        public void paint(Graphics g)
        {
                if (m_ready != null){
                        g.drawImage(m_ready,0,0,null);
                }
                R_in.setText(""+Rin/5);
                B_in.setText(""+Bin);
                R_out.setText(""+Rout/5);
                B_out.setText(""+Bout);
        }

        //--------------------------------------------------------------------------
        public void update(Graphics g)
        {
                ResizeImage();
                paint(g);
                ImageReady=false;
        }


        //--------------------------------------------------------------------------
        protected void ResizeImage(){
                Dimension dim = size();
                int nWidth = dim.width;
                int nHeight = dim.height;

                if (m_dimImage != null &&
                        m_dimImage.width == nWidth &&
                        m_dimImage.height == nHeight){

                        return;
                }

                m_dimImage = new Dimension(nWidth, nHeight);
                m_image = createImage(nWidth, nHeight);
                m_ready = createImage(nWidth, nHeight);
                m_g = m_image.getGraphics();
                m_r = m_ready.getGraphics();
                LR=new Point(nWidth-5,nHeight-5);       
                m_Barrier=nWidth/2;
                for (int i=0; i<NUM_PARTICLE; i++){
                        if (p[i].m_StdDev>=0.0){
                                p[i].NewLimits(UL,LR);
                                p[i].m_Barrier=m_Barrier;
                        }
                }
        }



        //--------------------------------------------------------------------------
        public void start()
        {
                if (m_diffusion == null)
                {
                        m_diffusion = new Thread(this);
                        //m_watch = new Stopwatch();  //Don't be its client for now
                        m_diffusion.start();
                        //m_watch.start();
                }
        }
        
        //--------------------------------------------------------------------------
        public void stop()
        {
                if (m_diffusion != null)
                {
                        m_diffusion.stop();
                        //m_watch.stop();
                        m_diffusion = null;
                        //m_watch = null;
                }

        }


        //--------------------------------------------------------------------------
        //public void tick(){
        //      Tick = ++Tick % 4;
        //      if ( Tick==0 && ImageReady) repaint();
        //}

        //--------------------------------------------------------------------------
        public void run()
        {
                Dimension dim=size();
                int VUnits, c=0;
                VU2=NUM_PARTICLE;
                while (true)
                {
                  if (m_g != null){
                    if (ResetLocation){
                      int charge=1;
                      for (int i=0; i<NUM_PARTICLE; i++){
                        // if (i>=NUM_PARTICLE/2) charge=-1;
                        Start= new Point((int)Math.round(Math.random()*dim.width/2)-15,(int)Math.round(Math.random()*dim.height));
                        p[i].Init(charge,Start,UL,LR);
                      }
                      /*
                        charge = 1;                                                                        //****
                                                                                                                 for (int i=0; i<20; i++){
                                                                                                                 if (i>=10) charge=-1;
                                                                                                                 p[i+NUM_PARTICLE].Init(charge,LR,UL,LR);
                                                                                                                 } \
                      */
                      ResetLocation=false;
                    }

                    m_g.setColor(BG);
                    m_g.fillRect(0,0,m_dimImage.width,m_dimImage.height);
                    for (int i=0; i<NUM_PARTICLE; i++){                                            //***
                      //for (int j=0; j<m_InnerLoop; j++){
                      p[i].NewMove();
                      //}
                      //}

                      //((Stopwatch)m_watch).reset();
                      //for (int i=0; i<NUM_PARTICLE; i++){
                      p[i].DrawParticle(m_g);
                    }
                    //m_InnerLoop=(int)((Stopwatch)m_watch).elapsedTime()/100;


                    m_g.setColor(Color.black);
                    m_g.drawLine(m_Barrier,0,m_Barrier,m_dimImage.height);
                    m_r.drawImage(m_image,0,0,null);
                    Rin=0; Rout=0; Bin=0; Bout=0;
                    for (int i=0; i<NUM_PARTICLE; i++){        //***
                      if (p[i].IsInside()){
                        Rin+=p[i].m_Charge;
                      }else{
                        Rout+=p[i].m_Charge;
                      }
                    }
                    if (c == 10){
                        VUnits=Rin;
                        rate=VU2-VUnits;
                        VU2=VUnits;
                        c=0;
                    }
                        else{ 
                                c++;
                        }
                    // m_Membrane.SetVoltage(VUnits*800.0/(double)NUM_PARTICLE);     
                    if(((Fick3)applet).stop){
                        ((Fick3)applet).t.resume();
                        ((Fick3)applet).stop=false;
                    }
                    Voltage.setText(rate+" ");
                    ImageReady=true;
                    ((Fick3)applet).OutBar.setFillPercent((double)Math.abs(100-(double)Rin/(double)NUM_PARTICLE*100));
                    repaint();
                  }
                }
        }

  // MOUSE SUPPORT:
  //            The mouseDown() method is called if the mouse button is pressed
        // while the mouse cursor is over the applet's portion of the screen.
        //--------------------------------------------------------------------------
        public boolean mouseDown(Event evt, int x, int y)
        {
           //     Start=new Point(x,y);
           //     ResetLocation=true;
                return true;
        }

        // MOUSE SUPPORT:
        //              The mouseUp() method is called if the mouse button is released
        // while the mouse cursor is over the applet's portion of the screen.
        //--------------------------------------------------------------------------
        public boolean mouseUp(Event evt, int x, int y)
        {
                return true;
        }

        // MOUSE SUPPORT:
        //              The mouseDrag() method is called if the mouse cursor moves over the
        // applet's portion of the screen while the mouse button is being held down.
        //--------------------------------------------------------------------------
        public boolean mouseDrag(Event evt, int x, int y)
        {
                return true;
        }

        // MOUSE SUPPORT:
        //              The mouseMove() method is called if the mouse cursor moves over the
        // applet's portion of the screen and the mouse button isn't being held down.
        //--------------------------------------------------------------------------
        public boolean mouseMove(Event evt, int x, int y)
        {
                return true;
        }

        // MOUSE SUPPORT:
        //              The mouseEnter() method is called if the mouse cursor enters the
        // applet's portion of the screen.
        //--------------------------------------------------------------------------
        public boolean mouseEnter(Event evt, int x, int y)
        {
                return true;
        }

        // MOUSE SUPPORT:
        //              The mouseExit() method is called if the mouse cursor leaves the
        // applet's portion of the screen.
        //--------------------------------------------------------------------------
        public boolean mouseExit(Event evt, int x, int y)
        {
                return true;
        }


}


/*
class ReportLabel extends Label {

        ReportLabel(){
                super.setAlignment(Label.LEFT);
        }

        ReportLabel(String string){
                super.setAlignment(Label.LEFT);
                super.setText(string);
        }

        ReportLabel(String string, int alignment){
                super.setAlignment(alignment);
                super.setText(string);
        }


        public Insets insets(){
                return new Insets(0,0,0,0);
        }


}
*/

