//import DiffusionCanvas;
import java.applet.Applet;
import java.awt.*;
/*
 *
 * OsmCanvas
 *
 */
public class OsmPCanvas extends DiffusionCanvas
{
        public int differ, InWater=110, OutWaterMax=150, InIon=10, OutIon=10, OutWater=110;
        public int Hydration=3;
        public int NUM_PARTICLE=350;
        private final int MAX_PARTICLE=350, MaxWater=150, MaxIon=20;
        public double Cin=0, Cout=0; 
        
//-------------------------------------------------------------------------
        public OsmPCanvas(Applet applet){
                this.applet=applet;
        }

  //-------------------------------------------------------------------------
  double round(double value, int decimalPlace) {
    double power_of_ten = 1;
    while (decimalPlace-- > 0)
      power_of_ten *= 10.0;
    return Math.round(value * power_of_ten)
      / power_of_ten;
  }
  
//-------------------------------------------------------------------------
        public void init()
        {
                Dimension dim=size();
                int nWidth=dim.width;
                int nHeight=dim.height;
                Start= new Point(15,15);
                UL=new Point(0,0);
                LR=new Point(nWidth-5,nHeight-5);
                Cinr=0;
                Coutr=0;
                m_Membrane=new Membrane();
                m_Membrane.SetVoltage(-60);
                m_Membrane.addElement(1.0);
                m_Membrane.addElement(0.0);

                //m_Barrier=nWidth/2;
                m_InnerLoop=0;


                p = new OsmParticle[MAX_PARTICLE];

                for (int i=0; i<MAX_PARTICLE; i++){
                        p[i]= new OsmParticle(applet);
                        p[i].m_StdDev=-1.0;
                        p[i].BG=getBackground();
                        //p[i].m_Barrier=m_Barrier;
                        p[i].m_Membrane=m_Membrane;
                }
                ParticleInit(nWidth,nHeight);
                ResizeImage();

                ResetLocation=true;

                //R_in.setAlignment(Label.LEFT);
                //B_in.setAlignment(Label.LEFT);
                //R_out.setAlignment(Label.LEFT);
                //R_out.setAlignment(Label.LEFT);
                //Voltage.setAlignment(Label.CENTER);

        }
//-------------------------------------------------------------------------
        public void paint(Graphics g)
        {
                //m_InnerLoop=(int)((Stopwatch)m_watch).elapsedTime()/100;
                //((Stopwatch)m_watch).reset();

                if (m_ready != null){
                        g.drawImage(m_ready,0,0,null);
                }

                Cinr = round (Cin, 2);
                Coutr = round (Cout, 2);

                //g.drawString("i="+m_InnerLoop,10,10);
                R_in.setText("   "+Rin);
                B_in.setText("   ["+Cinr+"]");
                R_out.setText("   "+Rout);
                B_out.setText("   ["+Coutr+"]");
        }

//-------------------------------------------------------------------------
        public void ParticleInit(int width, int height){
                if (width<20) width=20;
                if (height<20) height=20;
                int i,WLim;
                int r_in,r_out;

                r_in=InWater+(1+Hydration)*InIon;
                r_out=OutWater+(1+Hydration)*OutIon;
                m_Barrier=r_in*width/(r_in+r_out);
                
                if (m_Barrier>5){
                        WLim=m_Barrier-5;
                }else WLim=m_Barrier;
                for (i=0; i<InWater; i++){
                        Start.x=(int)(Math.random()*WLim)+1;
                        Start.y=(int)(Math.random()*(height-15))+10;
                        p[i].Init(0,Start,UL,LR);
                        p[i].m_MembraneIndex=0;
                        p[i].m_Barrier=m_Barrier;
                        p[i].m_StdDev=6.0;
                }
                for (i=MaxWater; i<MaxWater+OutWater; i++){
                        Start.x=(int)(Math.random()*(width-WLim))+WLim+5;
                        Start.y=(int)(Math.random()*(height-15))+10;
                        p[i].Init(0,Start,UL,LR);
                        p[i].m_MembraneIndex=0;
                        p[i].m_Barrier=m_Barrier;
                        p[i].m_StdDev=6.0;
                }
                for (i=2*MaxWater; i<2*MaxWater+InIon; i++){
                        Start.x=(int)(Math.random()*WLim)+1;
                        Start.y=(int)(Math.random()*(height-15))+10;
                        p[i].Init(-1,Start,UL,LR);
                        p[i].m_MembraneIndex=1;
                        p[i].m_Barrier=m_Barrier;
                        p[i].m_StdDev=2.0;
                }
                for (i=2*MaxWater+MaxIon; i<2*MaxWater+MaxIon+OutIon; i++){
                        Start.x=(int)(Math.random()*(width-WLim))+WLim+5;
                        Start.y=(int)(Math.random()*(height-15))+10;
                        p[i].Init(-1,Start,UL,LR);
                        p[i].m_MembraneIndex=1;
                        p[i].m_Barrier=m_Barrier;
                        p[i].m_StdDev=2.0;
                }
        }

//-------------------------------------------------------------------------
        public void run()
        {
        n_runs=0;
        total_sum=0;
        total_sum2=0;
        tcontin=0;
        tcontout=0;
                while (true)
                {
                  if (m_g != null){
                    if (ResetLocation){
                      ParticleInit(m_dimImage.width,m_dimImage.height);
                      ResetLocation=false;
                    }

                    m_g.setColor(BG);
                    m_g.fillRect(0,0,m_dimImage.width,m_dimImage.height);
                    //int IMin=InWater+OutWaterMax;
                    //int IMax=IMin+InIon+OutIon;
                    int i;
                    for (i=0; i<InWater; i++){
                      p[i].NewMove();
                      p[i].DrawParticle(m_g);
                      if (i % 10 == 0) m_diffusion.yield();
                    }
                    for (i=MaxWater; i<MaxWater+OutWater; i++){
                      p[i].NewMove();
                      p[i].DrawParticle(m_g);
                      if (i % 10 == 0) m_diffusion.yield();
                    }
                    for (i=2*MaxWater; i<2*MaxWater+InIon; i++){
                      p[i].NewMove();
                      p[i].DrawParticle(m_g);
                      if (i % 10 == 0) m_diffusion.yield();
                    }
                    for (i=2*MaxWater+MaxIon; i<2*MaxWater+MaxIon+OutIon; i++){
                      p[i].NewMove();
                      p[i].DrawParticle(m_g);
                      if (i % 10 == 0) m_diffusion.yield();
                    }
                    m_g.setColor(Color.black);
                    if (m_Barrier!=0){
                      m_g.fillRect(m_Barrier+2,0,4,m_dimImage.height);
                    }
                    //m_g.drawString("i="+m_InnerLoop,10,10);
                    m_r.drawImage(m_image,0,0,null);
                    Rin=0; Rout=0; Cin=0; Cout=0;
                    for (i=0; i<InWater; i++){
                      if (p[i].IsInside()) Rin+=1;
                      else Rout+=1;
                    }
                    for (i=MaxWater; i<MaxWater+OutWater; i++){
                      if (p[i].IsInside()) Rin+=1;
                      else Rout+=1;
                    }
                    for (i=2*MaxWater; i<2*MaxWater+InIon; i++){
                      if (p[i].IsInside()){
                        Rin+=Hydration+1; 
                        Cin++;
                      }else{
                        Rout+=Hydration+1; 
                        Cout++;
                      }
                    }
                    for (i=2*MaxWater+MaxIon; i<2*MaxWater+MaxIon+OutIon; i++){
                      if (p[i].IsInside()){
                        Rin+=Hydration+1; 
                        Cin++;
                      }else{
                        Rout+=Hydration+1; 
                        Cout++;
                      }
                    }
                    Cin*= 55.5/Rin;
                    Cout *= 55.5/Rout;
                    n_runs++;
                    total_sum = total_sum+Rin-Rout;
                    total_sum2=total_sum2+Rout-Rin;
                    tcontin=tcontin+Cinr;
                    tcontout=tcontout+Coutr;
                    differ=Rin-Rout;
                    Voltage.setText("     "+differ+" ");
                    Average.setText("     "+total_sum/n_runs+" ");
                    /*                                  if (m_Barrier!=0){
                                                        m_Barrier= (Rin*m_dimImage.width)/(Rin+Rout);
                                                        for (i=0; i<InWater; i++){
                                                        ((OsmParticle)p[i]).MoveMembrane(m_Barrier);
                                                        }
                                                        for (i=MaxWater; i<MaxWater+OutWater; i++){
                                                        ((OsmParticle)p[i]).MoveMembrane(m_Barrier);
                                                        }
                                                        for (i=2*MaxWater; i<2*MaxWater+InIon; i++){
                                                        ((OsmParticle)p[i]).MoveMembrane(m_Barrier);
                                                        }
                                                        for (i=2*MaxWater+MaxIon; i<2*MaxWater+MaxIon+OutIon; i++){
                                                        ((OsmParticle)p[i]).MoveMembrane(m_Barrier);
                                                        }
                                                        ((Nernst)applet).OutBar.setFillPercent(Rin*100.0/(Rin+Rout));
                                                        }
                    */
                    if ((Rin-Rout)<(-99)){
                        ((Nernst)applet).OutBar.setFillPercent(1);
                    }
                    else{    
                        ((Nernst)applet).OutBar.setFillPercent((Rin-Rout)/2+50);
                    }    
                    ImageReady=true;
                    repaint();
                  }else{ResizeImage();}
                }
        }



}


