import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.geom.*;
 
 
public class DrawCurrent extends Canvas{
	private static final Color bgcolor = new Color(255,255,255);
        private Image im;
        public int imax, is_new;
        private MemoryImageSource mis;
	private int rgbPixels[];
	private int new_width;
	private Color colorArray[]; 
	private static final int width=606;
	private static final int height=606;
	private static final int palette_width=20, palette_height=500;
	private static final int LeftImageIndent=5;
        private Graphics buf;
        private int Nx = 273;
        private int Ny = 248;
        private int Nratio = 1; // Since Nt = 6000, Nratio can be 10, 15, 20, 24
        public double previous = 0.0;
        private double w[][];
        
        private int go = 0;
        
        private int Npoints;
        private double ymax, ymin, xmax, xmin, ypmax, ypmin;
        private double[] x, y, v;
        private int[] xx, yy, yen;
        
	private Trans_State state;
	private boolean DirtyFlag;
	
        public DrawCurrent(Trans_State state){
		super();
		this.state = state;
                setBackground(bgcolor);
		new_width = (int)(width);
		rgbPixels = new int[(width+1) * (height+1)];
		colorArray = new Color[1024];
                
		DirtyFlag = true;
                
                xmin = 0.0;
                ymax = 1.0;
                ymin = -1.0;
                ypmax = 1.0;
                ypmin = 0.0;
                
                Npoints = state.Nt/Nratio + 1;
                
                try{
                    x = new double[Npoints];
                    y = new double[Npoints];
                    xx = new int[Npoints];
                    yy = new int[Npoints];
                    yen = new int[Npoints];
                }
                catch(Exception e){e.printStackTrace();}
                for(int i = 0; i < x.length; i++){
                    x[i] = (double)i;
                    y[i] = state.pulse[i*Nratio];
                }

                w = new double[Nx+1][Ny+1];
                
                //Initialize the color palette
                
                imax = state.palettereference;
                
                if(state.IsThreshold){
                
                    for(int i = 0; i < 247; i++) {
                       colorArray[i] = new Color(0,0,255);
                    }

                    for(int i = 247; i < 503; i++) {
                       colorArray[i] = new Color((i-247)/16*16,(i-247)/16*16,255);
                    }

                    for(int i = 503; i < 520; i++) {
                       colorArray[i] = new Color(255,255,255);
                    }

                    // red
                    for(int i = 520; i < 778; i++) {
                        colorArray[i] = new Color(255,240-(((i-520)/16)*16),240-(((i-520)/16)*16));
                    }

                    for(int i = 778; i < 1025; i++) {
                       colorArray[i] = new Color(255,0,0);
                    }

                    //for(int s=0; s<1024;s++){
                        //System.out.println(s+"   "+colorArray[s]);
                    //}
                }
                else{
                
                    // blue
                    for(int i = 0; i < 256; i++) {
                       colorArray[i] = new Color(0,0,255);
                    }

                    for(int i = 256; i < 512; i++) {
                       colorArray[i] = new Color((i-256),(i-256),255);
                    }

                    // red
                    for(int i = 512; i < 768; i++) {
                        colorArray[i] = new Color(255,255-((i-512)),255-((i-512)));
                    }

                    for(int i = 768; i < 1024; i++) {
                       colorArray[i] = new Color(255,0,0);
                    }
                }
                //updatePixels();
		//mis = new MemoryImageSource(new_width,height,rgbPixels,0,new_width);
		//mis.setAnimated(true);
		//mis.setFullBufferUpdates(false);
		//im = createImage(mis);
	}
        
        public void paint(Graphics g){
	if(im == null){
	    im = createImage(getSize().width,getSize().height);
	    buf = im.getGraphics();
	    updatePixels(buf);
	}
	else{
            updatePixels(buf);
	}
	g.drawImage(im,0,0,null);
        //repaint();
    }
	//public synchronized void paint(Graphics g){
	//    updatePixels(g);
	//}   
	
	private synchronized void updatePixels(Graphics g){
                Graphics2D g2d = (Graphics2D)g;
                
                //clear
                g.setColor(Color.white);              
                g.fillRect(10,10,getSize().width-20,getSize().height-20);
                        
                Color charge_colorA = new Color(255,255,255);
                Color charge_colorB = new Color(255,255,255);
                
                double distance = (double)Nx* 4.0/30.0;
                
                double distance_current = - distance * state.Dipole_Current;
                double centerx = (double)Nx/2;
                double centery = (double)Nx/2;
                double charge_radius = Nx*25.0/300.0;
                double charge_center_A = centery - distance - charge_radius - 7;
                double charge_center_B = centery + distance + charge_radius + 7;
                
                // draw legends
                g.setColor(Color.black);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
                
                g.drawLine((int)centerx*13/10,(int)charge_center_A,(int)centerx*15/10,(int)charge_center_A);
                g.drawLine((int)centerx*13/10,(int)charge_center_B,(int)centerx*15/10,(int)charge_center_B);
                g.drawLine((int)centerx*14/10,(int)charge_center_A,(int)centerx*14/10,(int)charge_center_B);
            
                MaestroG.drawArrow((int)centerx*14/10,(int)charge_center_A+10,5,g);
                MaestroG.drawArrow((int)centerx*14/10,(int)charge_center_B-10,6,g);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
                
                // CLEAR 1
                //g.setColor(Color.white);              
                //g.fillRect((int)centerx*15/10-10,(int)(charge_center_A+charge_center_B)/2-30, 60, 50);
                
                g.setFont(new Font("Serif",Font.ITALIC,24));
                g.setColor(Color.black);
                g.drawString("l",(int)centerx*15/10,(int)(charge_center_A+charge_center_B)/2);
                
                // CLEAR 2
                //g.setColor(Color.white);              
                //g.fillRect((int)centerx*40/100-10,(int)(charge_center_A+charge_center_B)/2-30, 60, 50);
                
                g.setColor(Color.black);
                g.setFont(new Font("Serif",Font.ITALIC,24));
                g.drawString("I ( t )",(int)centerx*40/100,(int)(charge_center_A+charge_center_B)/2);
                
                // CLEAR 3
                //g.setColor(Color.white);  
                //MaestroG.fillCircleThick(g, centerx, charge_center_A, charge_radius+5, 2, charge_colorA);
                //MaestroG.fillCircleThick(g, centerx, charge_center_B, charge_radius+5, 2, charge_colorB);
                
                //------------------------------------
                // draw charges
                if(state.Dipole_Charge >= 0.0){
                     charge_colorA = new Color(255,255*(100-(int)(state.Dipole_Charge*100.0))/100,255*(100-(int)(state.Dipole_Charge*100.0))/100);
                     charge_colorB = new Color(255*(100-(int)(state.Dipole_Charge*100.0))/100,255*(100-(int)(state.Dipole_Charge*100.0))/100,255);
                }
                if(state.Dipole_Charge < 0.0){
                     charge_colorB = new Color(255,255*(100+(int)(state.Dipole_Charge*100.0))/100,255*(100+(int)(state.Dipole_Charge*100.0))/100);
                     charge_colorA = new Color(255*(100+(int)(state.Dipole_Charge*100.0))/100,255*(100+(int)(state.Dipole_Charge*100.0))/100,255);
                }
                     
                    MaestroG.fillCircleThick(g, centerx, charge_center_A, charge_radius, 2, charge_colorA);
                    MaestroG.fillCircleThick(g, centerx, charge_center_B, charge_radius, 2, charge_colorB);
                    
                    MaestroG.drawCircleThick(g, centerx, charge_center_A, charge_radius, 2, Color.gray);
                    MaestroG.drawCircleThick(g, centerx, charge_center_B, charge_radius, 2, Color.gray);
                    
                    int xshift = 40;
                            
                    if(state.Dipole_Charge > 0){
                        if(go==0){
                            MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_A,centerx+5-xshift, charge_center_A, 6, Color.white);
                            MaestroG.drawLineThick(g,centerx-xshift,charge_center_A-5,centerx-xshift, charge_center_A+5, 6, Color.white);
                            MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_B,centerx+5-xshift, charge_center_B, 6, Color.white);
                            MaestroG.drawLineThick(g,centerx-xshift,charge_center_B-5,centerx-xshift, charge_center_B+5, 6, Color.white);
                        }
                        MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_A,centerx+5-xshift, charge_center_A, 3, Color.black);
                        MaestroG.drawLineThick(g,centerx-xshift,charge_center_A-5,centerx-xshift, charge_center_A+5, 3, Color.black);
                        MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_B,centerx+5-xshift, charge_center_B, 3, Color.black);
                        go = 1;
                    }
                    if(state.Dipole_Charge == 0){
                       
                            MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_A,centerx+5-xshift, charge_center_A, 6, Color.white);
                            MaestroG.drawLineThick(g,centerx-xshift,charge_center_A-5,centerx-xshift, charge_center_A+5, 6, Color.white);
                            MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_B,centerx+5-xshift, charge_center_B, 6, Color.white);
                            MaestroG.drawLineThick(g,centerx-xshift,charge_center_B-5,centerx-xshift, charge_center_B+5, 6, Color.white);
                     
                    }
                    else if(state.Dipole_Charge < 0){
                        if(go==1){
                            MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_A,centerx+5-xshift, charge_center_A, 6, Color.white);
                            MaestroG.drawLineThick(g,centerx-xshift,charge_center_A-5,centerx-xshift, charge_center_A+5, 6, Color.white);
                            MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_B,centerx+5-xshift, charge_center_B, 6, Color.white);
                            MaestroG.drawLineThick(g,centerx-xshift,charge_center_B-5,centerx-xshift, charge_center_B+5, 6, Color.white);
                        }
                        MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_B,centerx+5-xshift, charge_center_B, 3, Color.black);
                        MaestroG.drawLineThick(g,centerx-xshift,charge_center_B-5,centerx-xshift, charge_center_B+5, 3, Color.black);
                        MaestroG.drawLineThick(g,centerx-5-xshift,charge_center_A,centerx+5-xshift, charge_center_A, 3, Color.black);
                        go = 0;
                    }
                // CLEAR 4   
                //g.setColor(Color.white);
                //g.fillRect((int)centerx-10, (int)centery - (int)distance -5, 20, 2*(int)distance+10);
                
                // draw current
                if(state.Dipole_Current > 0.0){
                     charge_colorA = new Color(255,255*(1-(int)state.Dipole_Charge),255*(1-(int)state.Dipole_Charge));
                     charge_colorB = new Color(255*(1-(int)state.Dipole_Charge),255*(1-(int)state.Dipole_Charge),255);
                     
                    if(Math.abs(state.Dipole_Current) < 0.25){
                        MaestroG.drawLineThick(g,centerx,centery-distance_current,centerx, centery+distance_current, 3, Color.red);
                        if(Math.abs(state.Dipole_Current) > 0.05){
                            MaestroG.drawLineThick(g,centerx,centery+distance_current,centerx-2, centery+distance_current+4, 3, Color.red);
                            MaestroG.drawLineThick(g,centerx,centery+distance_current,centerx+2, centery+distance_current+4, 3, Color.red);
                        }
                    }
                    else{
                        MaestroG.drawLineThick(g,centerx,centery-distance_current,centerx, centery+distance_current, 5, Color.red);
                        MaestroG.drawLineThick(g,centerx,centery+distance_current,centerx-4, centery+distance_current+8, 5, Color.red);
                        MaestroG.drawLineThick(g,centerx,centery+distance_current,centerx+4, centery+distance_current+8, 5, Color.red);
                    }
                }
                else{
                    if(Math.abs(state.Dipole_Current) < 0.25){
                        MaestroG.drawLineThick(g,centerx,centery-distance_current,centerx, centery+distance_current, 3, Color.blue);
                        if(Math.abs(state.Dipole_Current) > 0.05){
                            MaestroG.drawLineThick(g,centerx,centery+distance_current,centerx-2, centery+distance_current-4, 3, Color.blue);
                            MaestroG.drawLineThick(g,centerx,centery+distance_current,centerx+2, centery+distance_current-4, 3, Color.blue);
                        }
                    }
                    else{
                        MaestroG.drawLineThick(g,centerx,centery-distance_current,centerx, centery+distance_current, 5, Color.blue);
                        MaestroG.drawLineThick(g,centerx,centery+distance_current,centerx-4, centery+distance_current-8, 5, Color.blue);
                        MaestroG.drawLineThick(g,centerx,centery+distance_current,centerx+4, centery+distance_current-8, 5, Color.blue);        
                    }
                }
                
                previous = - distance*state.Dipole_Current;
            
            //mis = new MemoryImageSource(new_width,height,rgbPixels,0,new_width);
	    //mis.setAnimated(true);
	    //mis.setFullBufferUpdates(true);
            //im = createImage(mis);
            //g.drawImage(im,LeftImageIndent,(getSize().height-height)/2,this);
	}
        
	public synchronized void setDirtyFlag(boolean DirtyFlag){
	    this.DirtyFlag = DirtyFlag;
	}
	
	public synchronized void setWidth(double ratio){
	    this.new_width=(int)(width/ratio);
	    this.rgbPixels=new int[(int)(width/ratio*height)];
	}
	
	public synchronized void update(Graphics g){
		
                paint(g);
	}
		
}	

