//import DiffusionCanvas;
import java.applet.Applet;
import java.awt.*;
/*
 *
 * OsmCanvas
 *
 */
public class OsmCanvas 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 OsmCanvas(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();
			  }
		  }
	  }
}
