import java.applet.Applet;                                                    
import java.awt.*;
//import gjt.*;

/*
 *
 * Nernst
 *
 */
public class Fick extends Applet
{
        DiffusionCanvas1 CDiff;
        RBox bR_in, bR_out, bB_in, bB_out, bVoltage, bInside, bOutside, bAverage;
        Choice Num_Particles;
        Panel p;
        Button Start_Stop, Plot, Fit2, Fit, Rst;
        ThreeDBorder tdbDisplay,graph;
        ReportPanel1 pReport;
        ControlPanel1 pControl;
        boolean running=false, frun=true, prun=false, rst=true;
        int Particles[] = {50,100,200,300,400,500};
        protected BarChart OutBar=new BarChart(Color.red);
        GraphFickCanvas Gr;
        Thread t;
        int i, PLOT_REAL=0, ERR=0, PLT=0, PLT2=0, is=0, it=0, lines[][]=new int[7][5], xs[]=new int[3000], ys[]= new int[3000], zs[]=new int[3000];
        float SX, SY, SXY, SX2, X1, Y1, a, b;

        public void init(){
                //obsolete.applet.JavaConsole.init(this);
                Panel pnl=new Panel();
                Panel pnl2=new Panel();
             Gr=new GraphFickCanvas(this);
           tdbDisplay=new ThreeDBorder(pnl2,5);
           pnl2.setLayout(new BorderLayout());
           CDiff=new DiffusionCanvas1(this);
           pnl2.add("Center",CDiff);
           pnl2.add("South", OutBar);
           tdbDisplay.inset();
           pReport=new ReportPanel1(this);
           pControl=new ControlPanel1(this);
           setLayout(new BorderLayout());
           add("Center",new ThreeDBorder(pnl));
           pnl.setLayout(new BorderLayout());
           pnl.add("Center",tdbDisplay);
           pnl.add("North", pReport);
           pnl.add("South", pControl);
           Gr.resize(300,300);
           graph= new ThreeDBorder(Gr,5);
           add("East", graph);
           t= new PThread1(this);
//          t.start();
//           t.suspend();
           OutBar.stop();
     }

        public void destroy()
        {
                //obsolete.applet.JavaConsole.flushClasses(this);
        }


        public void start(){
                CDiff.init();
//                CDiff.start();
        }

        public void stop(){
                CDiff.stop();
        }

        public boolean action(Event event, Object what){
                if(event.target==Start_Stop){
                        if (running){
                                CDiff.stop();
                                OutBar.stop();
                                running=false;
                                Start_Stop.setLabel("Start");
                                Plot.setLabel("StartPlot");
                                if(prun){
                                        t.suspend();
                                        prun=false;
                                }
                              //  t.suspend();
                        }else{
                                CDiff.start();
                                OutBar.start();
                                running=true;
                                Start_Stop.setLabel("Stop");
                        }
                }else if (event.target==Num_Particles){
                        int NewNum=Particles[Num_Particles.getSelectedIndex()];
                        if (running){ 
                                CDiff.stop();
                                if(prun){
                                        t.suspend();
                                }
                                rst=true;
                        }
                        CDiff.NUM_PARTICLE=NewNum;
                        CDiff.init();
                        if (running){ 
                                CDiff.start();
                                if(prun){
                                        t.resume();
                                }
                        }
                }else if (event.target==Rst){
                        if (running){ 
                                CDiff.stop();
                        }
                        if(prun){
                                t.suspend();
                        }
                        rst=true;
                        CDiff.init();
                        is=0;
                        for(i=0;i<7;i++){
                                lines[i][0] = 0;
                        }
                        Gr.Str0=" ";
                        Gr.Str1=" ";
                        Gr.Str2=" ";
                        Gr.repaint();
                        if (running){ 
                                CDiff.start();
                        }
                        if(prun){
                                t.resume();
                        }
                }else if (event.target==Plot){
                        if(prun){
                                prun=false;
                                t.suspend();
                                Plot.setLabel("StartPlot");
                        }
                        else{
                                if(frun){
                                        t.start();
                                        frun=false;
                                        prun=true;
                                }else{
                                        prun=true;
                                        t.resume();
                                }
                                Plot.setLabel("StopPlot");
                        }
                }else if (event.target==Fit){
                                it=0;
                                SX=0;
                                SY=0;
                                SXY=0;
                                SX2=0;
                                for (i=0;i<is;i++){
                                        if (zs[i] == Num_Particles.getSelectedIndex()){        
                                                SX=(float)(SX+xs[i]);
                                                SY=(float)(SY+ys[i]);
                                                SXY=(float)(SXY+xs[i]*ys[i]);
                                                SX2=(float)(SX2+xs[i]*xs[i]);
                                                //     SY2=SY2+Y[i]*Y[i];
                                                it++;
                                        }
                                }
                                if (it < 2){
                                         ERR=1;
                                }else{
                                        X1=(float)SX/(float)it;
                                        Y1=(float)SY/(float)it;
                                        b=((float)SXY-(float)it*X1*Y1)/((float)SX2-(float)it*X1*X1);
                                        a=Y1-b*X1;
                                        PLT=1;
                                }
                        Gr.repaint();
                }else if (event.target==Fit2){
                                SX=0;
                                SY=0;
                                SXY=0;
                                SX2=0;
                                for (i=0;i<is;i++){
                               //         if (zs[i] == Num_Particles.getSelectedIndex()){        
                                                SX=(float)(SX+xs[i]);
                                                SY=(float)(SY+ys[i]);
                                                SXY=(float)(SXY+xs[i]*ys[i]);
                                                SX2=(float)(SX2+xs[i]*xs[i]);
                                                //     SY2=SY2+Y[i]*Y[i];
                                //                it++;
                                //        }
                                }
                                if (is < 2){
                                         ERR=1;
                                }else{
                                        X1=(float)SX/(float)is;
                                        Y1=(float)SY/(float)is;
                                        b=((float)SXY-(float)is*X1*Y1)/((float)SX2-(float)is*X1*X1);
                                        a=Y1-b*X1;
                                        PLT=1;
                                        PLT2=1;
                                }
                        Gr.repaint();
                }

                return true;

        }

}


class ReportPanel1 extends Panel{
        Fick app;

        public ReportPanel1(Applet applet){
                app=(Fick)applet;
                Panel pIn=new Panel();
                Label inside=new Label("Inside",Label.CENTER);
                app.bInside= new RBox(pIn,inside);
                pIn.setLayout(new BorderLayout());
                pIn.add("Center",app.CDiff.R_in);
                // pIn.add("East",app.CDiff.B_in);

                Panel pOut=new Panel();
                Label outside=new Label("Outside",Label.CENTER);
                app.bOutside= new RBox(pOut,outside);
                pOut.setLayout(new BorderLayout());
                pOut.add("Center",app.CDiff.R_out);
                // pOut.add("East",app.CDiff.B_out);

                app.bVoltage= new RBox(app.CDiff.Voltage,"ChangeRate");

                setLayout(new GridLayout(1,3,10,10));

                add(new ThreeDBorder(app.bInside));
                add(new ThreeDBorder(app.bVoltage));
                add(new ThreeDBorder(app.bOutside));
        }

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

}

class ControlPanel1 extends Panel{

        Fick app;

        public ControlPanel1(Applet applet){
                app=(Fick)applet;
                app.p=new Panel();
                app.Num_Particles= new Choice();
                // app.Num_Particles.addItem("1 Particle");
                // app.Num_Particles.addItem("2 Particles");
                // app.Num_Particles.addItem("5 Particles");
                // app.Num_Particles.addItem("10 Particles");
                // app.Num_Particles.addItem("20 Particles");
                app.Num_Particles.addItem("50 Particles");
                app.Num_Particles.addItem("100 Particles");
                app.Num_Particles.addItem("200 Particles");
                app.Num_Particles.addItem("300 Particles");
                app.Num_Particles.addItem("400 Particles");
                app.Num_Particles.addItem("500 Particles");
                app.Num_Particles.select(2);

                app.Start_Stop= new Button("Start");
                app.Plot = new Button("StartPlot");
                app.Fit = new Button("Fit");
                app.Fit2 = new Button("FitTotal");
                app.Rst = new Button("Rst");
                GridBagLayout gbl= new GridBagLayout();
                app.p.setLayout(gbl);
                GridBagConstraints c= new GridBagConstraints();
                c.gridwidth=1;
                c.gridheight=1;
                c.fill= GridBagConstraints.BOTH;
                c.weightx=1;
                c.weighty=1;
                ThreeDBorder b1= new ThreeDBorder(app.Start_Stop);
                gbl.setConstraints(b1,c);
                app.p.add(b1);
                ThreeDBorder b2= new ThreeDBorder(app.Num_Particles);
                gbl.setConstraints(b2,c);
                app.p.add(b2);
                ThreeDBorder b3= new ThreeDBorder(app.Plot);
                gbl.setConstraints(b3,c);
                app.p.add(b3);
                ThreeDBorder b4= new ThreeDBorder(app.Fit);
                gbl.setConstraints(b4,c);
                app.p.add(b4);
                ThreeDBorder b5= new ThreeDBorder(app.Fit2);
                gbl.setConstraints(b5,c);
                app.p.add(b5);
                ThreeDBorder b6= new ThreeDBorder(app.Rst);
                gbl.setConstraints(b6,c);
                app.p.add(b6);
                setLayout(new BorderLayout());
                add("North",new ThreeDBorder(app.p));              
        }

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

}
class GraphFickCanvas extends Canvas {

        Fick app1;        

        static final int POSX = 525;
        static final int NEGX = 25;
        static final int POSY = 15;
        static final int NEGY = 10;
        
        int a,b,N,x1,x2,y1,y2,ind;

          String Str0=" ";
        String Str1=" ";
        String Str2=" ";
        Color C0,C;
        Color C1 = Color.black; 
        Color C2 = Color.black;
        
        double xstep;
        double ystep;

        public GraphFickCanvas (Applet a){
                app1=(Fick)a;
        }
        
        public synchronized void paint (Graphics g) {
                Dimension dm=size();
                int x,y,i,j;
                xstep=(double)dm.width/(double)(POSX+NEGX);
                ystep=(double)dm.height/(double)(POSY+NEGY);
                int xax=(int)Math.round(ystep*POSY);
                int yax=(int)Math.round(xstep*NEGX);
                g.setColor(Color.blue);
                g.drawLine(yax,0,yax,dm.height);
                g.drawLine(0,xax,dm.width,xax);
                for(i=0;i<(NEGX+POSX+1);i+=25){
                        x=(int)Math.round(i*xstep);
                        g.drawLine(x,xax-2,x,xax+2);
                }
                for(i=0;i<(NEGY+POSY+1);i++){
                        y=(int)Math.round(xax+i*ystep);
                        g.drawLine(yax-2,y,yax+2,y);
                }         
                for(i=0;i<(POSY+1);i++){
                        y=(int)Math.round(xax-i*ystep);
                        g.drawLine(yax-2,y,yax+2,y);
                } 
                g.setColor(Color.black);
                Font f = new Font("TimesRoman",Font.PLAIN,11);
                g.setFont(f);
                 for(i=0;i<500;i+=50){
                        g.drawString(" "+i,yax+(int)Math.round(i*xstep)-10,xax+12);      
                 }
//                g.drawString("5",yax+(int)Math.round(5*xstep)-2,xax+12);      
//                g.drawString("8",yax+(int)Math.round(8*xstep)-2,xax+12);
//                g.drawString("10",yax+(int)Math.round(10*xstep)-4,xax+12);
//                g.drawString("-10",yax+(int)Math.round(-10*xstep)-9,xax+12);
//                g.drawString("-20",yax+(int)Math.round(-20*xstep)-9,xax+12);
                f = new Font("TimesRoman",Font.PLAIN+Font.BOLD,12);
                g.setColor(Color.blue);
                g.drawString("dC",dm.width-13,xax+13);
                g.drawString("R",yax-12,12);
                f = new Font("TimesRoman",Font.PLAIN,11);
                g.setColor(Color.black);
                for(i=15;i>(-NEGY);i-=2){
                        g.drawString(" "+i,yax+6,(int)Math.round((POSY-i)*ystep)+5);
                }
         /*       if(app1.PLOT_AV == 1){                
                        a=10-app1.Particles[app1.Num_Particles.getSelectedIndex()];
                        b=(int)Math.round(app1.CDiff.total_sum/app1.CDiff.n_runs);
                        app1.xs[app1.is]=a;
                        app1.ys[app1.is]=b;
                        app1.zs[app1.is]=1;
                        app1.is++;
                        app1.PLOT_AV=0;  
                }  */
                if(app1.PLOT_REAL == 1){
                        a=app1.CDiff.Rin-app1.CDiff.Rout;
                        b=app1.CDiff.rate;
                        app1.xs[app1.is]=a;
                        app1.ys[app1.is]=b;
                        app1.zs[app1.is]=app1.Num_Particles.getSelectedIndex();
                        app1.is++;
             //           g.drawString("Calc",2,30);
                        app1.PLOT_REAL=0;
                }
             if(app1.ERR != 1){
                for(i=0;i<(app1.is);i++){
                        a=app1.xs[i];
                        b=app1.ys[i];
                        N=4;
                        int hit=0;
                        for(j=i;j>=0;j--){
                                if (a == app1.xs[j]){
                                        if(b == app1.ys[j]){
                                                if(j != i){
                                                        hit++;
                                                        if(hit == 3){
                                                                N++;
                                                                hit=0;
                                                        }        
                                                }       
                                        }
                                }
                        }     
                        // g.setColor(Color.black);
                        if(app1.zs[i] == 0){
                                g.setColor(Color.black);
                                C=Color.black;
                        }
                        if(app1.zs[i] == 1){
                                g.setColor(Color.red);
                                C=Color.red;
                        }
                        if(app1.zs[i] == 2){ 
                                g.setColor(Color.green);
                                C=Color.green;
                        }
                        if(app1.zs[i] == 3){
                                g.setColor(Color.cyan);
                                C=Color.cyan;
                        }
                        if(app1.zs[i] == 4){
                                g.setColor(Color.yellow);
                                C=Color.yellow;
                        }
                        if(app1.zs[i] == 5){
                                g.setColor(Color.magenta);
                                C=Color.magenta;
                        }
           //             g.drawString("oval",2,15);
                        g.fillOval((int)Math.round((NEGX+a)*xstep),(int)Math.round((POSY-b)*ystep),N,N);
                }
               }else{
                        g.setColor(Color.black);
                        g.drawString("Not enough data",dm.width-95,12);
                        app1.ERR=0;        
                }
  //              if(app1.PLT2 == 1){
  //                      C=Color.white;
  //                      C0=C;
  //                      app1.PLT=1;
  //                      app1.PLT2=0;
  //              }
                if(app1.PLT == 1){
                     //   g.setColor(Color.black);
                        Str2=Str1;
                        C2=C1;
                        Str1=Str0;
                        C1=C0;
                        C0=C;
                        g.setColor(C0);
                        ind=app1.Num_Particles.getSelectedIndex();
                        if (app1.PLT2 == 1) {
                                C0=Color.white;
                                g.setColor(Color.white);
                                ind=6;
                                app1.PLT2=0;
                        }
                        if (app1.b<0){
                                Str0="R="+(float)((float)Math.round(app1.a*100)/(float)100.0)+"-"+(float)((float)Math.abs(Math.round(app1.b*100))/(float)100.0)+"dC";                                
                        }else{        
                                Str0="R="+(float)((float)Math.round(app1.a*100)/(float)100.0)+"+"+(float)((float)Math.round(app1.b*100)/(float)100.0)+"dC";
                        }
                        x1=(int)Math.round((NEGX-25)*xstep);
                        y1=(int)Math.round((POSY-(app1.a+app1.b*(-25)))*ystep);
                        x2=(int)Math.round((NEGX+500)*xstep);
                        y2=(int)Math.round((POSY-(app1.a+app1.b*500))*ystep);
                        g.drawLine(x1,y1,x2,y2);
                        app1.lines[ind][0]=1;
                        app1.lines[ind][1]=x1;
                        app1.lines[ind][2]=y1;
                        app1.lines[ind][3]=x2;
                        app1.lines[ind][4]=y2;
                        app1.PLT=0;
                }        
                g.setColor(C0);
                g.drawString(Str0,dm.width-95,dm.height-45);
                g.setColor(C1);
                g.drawString(Str1,dm.width-95,dm.height-30);
                g.setColor(C2);
                g.drawString(Str2,dm.width-95,dm.height-15);
                for(i=0;i<7;i++){
                        if(app1.lines[i][0] == 1){
                                if(i == 0){
                                        g.setColor(Color.black);
                                }
                                if(i == 1){
                                        g.setColor(Color.red);
                                }
                                if(i == 2){ 
                                         g.setColor(Color.green);
                                }
                                if(i == 3){
                                        g.setColor(Color.cyan);
                                }
                                if(i == 4){
                                        g.setColor(Color.yellow);
                                }
                                if(i == 5){
                                        g.setColor(Color.magenta);
                                }
                                if(i == 6){
                                        g.setColor(Color.white);
                                }   
                                g.drawLine(app1.lines[i][1],app1.lines[i][2],app1.lines[i][3],app1.lines[i][4]);           
                        }              
                 }
        }
}
class PThread1 extends Thread{
        Fick a;
        
        public PThread1(Applet a){
                this.a=(Fick)a;
        }

      public void run(){
                int c=0, d=0;
//                while(a.CDiff.rate == 0){
//                }
//                while(c<5){
//                        if((a.CDiff.Rin-a.CDiff.Rout)!=d){
//                                d=a.CDiff.Rin-a.CDiff.Rout;
//                                a.PLOT_REAL=1;
//                                a.Gr.repaint();
//                                c++;
//                        }
//                } 
//                try{
//                        sleep(2000);
//                }
//                catch(InterruptedException e) {};
                while(true){
                       if (a.rst == true){
                                c=0; d=0;
//                                while(a.CDiff.rate == 0){
//                                }
                                while(c<5){
                                        if((a.CDiff.Rin-a.CDiff.Rout)!=d){
                                                d=a.CDiff.Rin-a.CDiff.Rout;
                                                a.PLOT_REAL=1;
                                                a.Gr.repaint();
                                                c++;
                                        }
                                  //       a.Gr.repaint();
                                 
                                          try{
                                               sleep(1500);
                                          }
                                          catch(InterruptedException e) {};
                                          a.rst=false;
                                }
                        }   
                        a.PLOT_REAL=1;
                        a.Gr.repaint();
                        try{
                                sleep(5000);
                        }
                        catch(InterruptedException e) {};
                }
        }    
}



        




        
