//import DiffusionCanvas;
import java.applet.Applet;
import java.awt.*;
/*
 *
 * OsmCanvas
 *
 */
public class OsmCanvas2 extends DiffusionCanvas
{
  public int 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, Cinr=0, Coutr=0;
        
//-------------------------------------------------------------------------
  public OsmCanvas2(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);

      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()
        {
          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;
                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));
                }

                ImageReady=true;
                repaint();
              }else{ResizeImage();}
            }
        }



    }

  

