import java.awt.*;
import java.awt.event.*;
 
public class RectWaveGuideSpectrumCanvas extends Canvas {
	//private static final Color bgcolor = new Color(216,216,191);
	//private static final Color bgcolor = new Color(216,230,230);
	private static final Cursor cursorA = new Cursor(Cursor.DEFAULT_CURSOR);
	private static final Cursor cursorB = new Cursor(Cursor.CROSSHAIR_CURSOR);
	private static final Color bgcolor = Color.black;
	private static final Color acolor = new Color(152,152,152);
	private static final Color ccolor = new Color(236,236,236);
	private Image im;
	private Graphics buf;
	private boolean IsTEmode = true;
	private static final int MaxModes = 11; //Maximum number of modes plotted
	private static final int LeftMargin=10, RightMargin=10, TopMargin=10, BottomMargin=10, Offset=100;
	RectWaveGuide_State state;
	double fMax, fMin; //maximum and miminum frequency range
	private static final int F_AXIS=150, S_AXIS=80; //y coordinates of Frequency and Spectrum axis
	//private static final int F_TE_A=18, F_TE_B=35, F_TE_C=52, F_TE_D=69, F_TE_E=86, F_TE_F=103; //y coordinates of Frequency tiers for TE(m,0), TE(0,n), and TE(m,n)
	//private static final int F_TE_G=120, F_TE_H=137;
	private static final int F_TE_A=137, F_TE_B=120, F_TE_C=103, F_TE_D=86, F_TE_E=69, F_TE_F=52; //y coordinates of Frequency tiers for TE(m,0), TE(0,n), and TE(m,n)
	private static final int F_TE_G=35, F_TE_H=18;
	
	public RectWaveGuideSpectrumCanvas(RectWaveGuide_State state){
		super();
                setBackground(bgcolor);
		this.state = state;
		//fMax=12.0E9;
                fMax=18.0E9;
		fMin=0.0E9;
		
	}
	
	public void paint(Graphics g){
	    if(im == null){
		im = createImage(getSize().width,getSize().height);
		buf = im.getGraphics();
		drawCanvas(buf);
	    }
	    else{
		drawCanvas(buf);
	    }
	    g.drawImage(im,0,0,null);
	}
	
	//Addition to reduce flicker new routine
	public void update(Graphics g){		// added to avoid clearing
	        paint(g);
	}


	public void clear(){
		this.getGraphics().clearRect(0,0,getSize().width,getSize().height);
	        repaint();
	}

	
	private void drawCanvas(Graphics g){
	
	    //Draw the black rectangle
	    g.setColor(Color.black);
	    g.fillRect(0,0,getSize().width,getSize().height);

	    
	    //g.setColor(bgcolor.darker());
	    g.setColor(bgcolor);
	    g.fillRect(0,getSize().height-2,getSize().width,2);
	    g.fillRect(getSize().width-2,0,2,getSize().height);
	    g.setColor(Color.white);
	    g.drawRect(4,4,getSize().width-8,getSize().height-8);
	   
	    
	    drawFrequency(g);
	    drawSpectrum(g);
	}	
	
	private void drawFrequency(Graphics g){
	    int mPos_frequency;
	    mPos_frequency = LeftMargin + (int) (
			    (getSize().width-LeftMargin-RightMargin)* 
			    (state.frequency)/(fMax-fMin) 
	    );	
	    //Draw operational frequency
	    g.setColor(Color.yellow);
	    //g.drawLine(mPos_frequency,getSize().height-45,mPos_frequency,getSize().height-110);
	    g.drawLine(mPos_frequency,getSize().height-10,mPos_frequency,5);
	    //Draw the arrow for operational frequency
	    MaestroG.drawArrow(mPos_frequency,getSize().height-15,5,g); 
	    
            //System.out.println(state.frequency+"   "+fMax+"   "+fMin);
	}
	
	private void drawSpectrum(Graphics g){
	    int mPos, i, j, spacer, spacer1, spacer2;
	    double my_f;
	    //draw axis
	    drawAxis(g);
	    //draw  modes
	   
	    i=0; 
	    j=0;
            spacer = 30; spacer1 = 30; spacer2 = 36;
	    my_f = getModeFrequency(i,j);
            
	    while(my_f < fMax){
		while(my_f < fMax){
		    mPos = LeftMargin + (int) (
			    (getSize().width-LeftMargin-RightMargin)* 
			    (my_f)/(fMax-fMin) 
		    );
		    g.setColor(Color.white);
                    spacer = 30; spacer1 = 30; spacer2 = 36;
		    if(i!=0 && j==0){//Top Tier has TE(n,0) modes
			g.drawLine(mPos,F_TE_A+5,mPos,F_TE_A-10);
                        if(i>9){spacer = spacer2;} else{spacer = spacer1;}
			MaestroG.subscripter("TE",""+i+","+j,"",g,11,mPos-spacer,F_TE_A);
		    }
		    else if(j!=0 && i==0){//Second Tier has TE(0,n) modes
			g.drawLine(mPos,F_TE_B+5,mPos,F_TE_B-10);
                        if(j>9){spacer = spacer2;} else{spacer = spacer1;}
			MaestroG.subscripter("TE",""+i+","+j,"",g,11,mPos-spacer,F_TE_B);
		    }
		    
		  if(IsTEmode){
                       g.setColor(Color.cyan);
                       if(i>=1 && j==1){//Third tier has TE(m,1) modes
                            g.drawLine(mPos,F_TE_C+5,mPos,F_TE_C-10);
                            if(i>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TE",""+i+","+j,"",g,11,mPos-spacer,F_TE_C);
                       }

                        else if(i==1 && j>=2){//Fourth tier has TE(1,n) modes (no TE(1,0));
                            g.drawLine(mPos,F_TE_D+5,mPos,F_TE_D-10);
                            if(j>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TE",""+i+","+j,"",g,11,mPos-spacer,F_TE_D);
                       }

                       else if(i>=2 && j==2){//Fifth tier has TE(m,2) modes
                            g.drawLine(mPos,F_TE_E+5,mPos,F_TE_E-10);
                            if(i>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TE",""+i+","+j,"",g,11,mPos-spacer,F_TE_E);
                       } 
                       else if(i==2 && j>=3 ){//Sixth tier has TE(2,n) modes
                            g.drawLine(mPos,F_TE_F+5,mPos,F_TE_F-10);
                            if(j>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TE",""+i+","+j,"",g,11,mPos-spacer,F_TE_F);
                       }

                       else if(i>=3 && j==3){//Seventh tier has TE(m,2) modes
                            g.drawLine(mPos,F_TE_G+5,mPos,F_TE_G-10);
                            if(i>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TE",""+i+","+j,"",g,11,mPos-spacer,F_TE_G);
                       } 
                       else if(i==3 && j>=4 ){//Eighth tier has TE(2,n) modes
                            g.drawLine(mPos,F_TE_H+5,mPos,F_TE_H-10);
                            if(j>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TE",""+i+","+j,"",g,11,mPos-spacer,F_TE_H);
                       }
		   
                      // else if(i+j>=5 && j!=0 && i!=0){//Rest of modes
                            //g.drawLine(mPos,F_TE_H+5,mPos,F_TE_H-10);
                            //MaestroG.subscripter("TE",""+i+","+j,"",g,11,mPos-30,F_TE_H);
                       //} 
	          }
	          else{
                       spacer = 33; spacer1 = 33; spacer2 = 39;
                       g.setColor(Color.green); 
                       if(i>=1 && j==1){//Third tier has TE(m,1) modes
                            g.drawLine(mPos,F_TE_C+5,mPos,F_TE_C-10);
                            if(i>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TM",""+i+","+j,"",g,11,mPos-spacer,F_TE_C);
                       }

                        else if(i==1 && j>=2){//Fourth tier has TE(1,n) modes (no TE(1,0));
                            g.drawLine(mPos,F_TE_D+5,mPos,F_TE_D-10);
                            if(j>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TM",""+i+","+j,"",g,11,mPos-spacer,F_TE_D);
                       }

                       else if(i>=2 && j==2){//Fifth tier has TE(m,2) modes
                            g.drawLine(mPos,F_TE_E+5,mPos,F_TE_E-10);
                            if(i>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TM",""+i+","+j,"",g,11,mPos-spacer,F_TE_E);
                       } 
                       else if(i==2 && j>=3 ){//Sixth tier has TE(2,n) modes
                            g.drawLine(mPos,F_TE_F+5,mPos,F_TE_F-10);
                            if(j>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TM",""+i+","+j,"",g,11,mPos-spacer,F_TE_F);
                       }

                       else if(i>=3 && j==3){//Seventh tier has TE(m,2) modes
                            g.drawLine(mPos,F_TE_G+5,mPos,F_TE_G-10);
                            if(i>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TM",""+i+","+j,"",g,11,mPos-spacer,F_TE_G);
                       } 
                       else if(i==3 && j>=4 ){//Eighth tier has TE(2,n) modes
                            g.drawLine(mPos,F_TE_H+5,mPos,F_TE_H-10);
                            if(j>9){spacer = spacer2;} else{spacer = spacer1;}
                            MaestroG.subscripter("TM",""+i+","+j,"",g,11,mPos-spacer,F_TE_H);
                       }

                       //else if(i+j>=5 && j!=0 && i!=0){//Rest of modes
                            //g.drawLine(mPos,F_TE_H+5,mPos,F_TE_H-10);
                            //MaestroG.subscripter("TM",""+i+","+j,"",g,11,mPos-30,F_TE_H);
                       //} 
                }   
		    
		    j++;
		    my_f = getModeFrequency(i,j);
		}
		i++;
		j=0;
		my_f = getModeFrequency(i,j);
	    }
	    int mPos_frequency;
	    mPos_frequency = LeftMargin + (int) (
			    (getSize().width-LeftMargin-RightMargin)* 
			    (state.frequency)/(fMax-fMin) 
	    );	
	    g.setColor(Color.yellow);
	    int x = mPos_frequency+10;
	    int y = getSize().height-10;
	    double f_normalized;
            
	//MaestroG.subscripter("Higher order modes are listed in the Mode Properties panel ( use Mode Selector to scan modes )","","",g,10,20, getSize().height-10);
	MaestroG.subscripter("Mode Spectrum","","",g,14,20,25);
        Font normalfont = new Font("SanSerif",Font.PLAIN,12);
        g.setFont(normalfont);
        
	if(state.frequency < 1.0E3){
		    f_normalized = state.frequency;
		    g.drawString(""+MaestroA.rounder(f_normalized,3)+" Hz",x,y);	
		}
		else if(state.frequency < 1.0E6 && state.frequency >= 1.0E3  ){
		    f_normalized = state.frequency/1.0E3;
		    g.drawString(""+MaestroA.rounder(f_normalized,3)+" kHz",x,y);	
		}
		else if(state.frequency < 1.0E9 && state.frequency >= 1.0E6 ){
		    f_normalized = state.frequency/1.0E6;
		    g.drawString(""+MaestroA.rounder(f_normalized,3)+" MHz",x,y);	
		}
		else if(state.frequency < 1.0E12 && state.frequency >= 1.0E9 ){
		    f_normalized = state.frequency/1.0E9;
		    g.drawString(""+MaestroA.rounder(f_normalized,3)+" GHz",x,y);	
		}
		else if(state.frequency < 1.0E15 && state.frequency >=1.0E12 ){
		    f_normalized = state.frequency/1.0E12;
		    g.drawString(""+MaestroA.rounder(f_normalized,3)+" THz",x,y);	
		}
		else{
		    f_normalized = state.frequency/1.0E12;
		    g.drawString(""+MaestroA.rounder(f_normalized,3)+" THz",x,y);
		}
	
	}	
	
	public void drawAxis(Graphics g){
	    g.setColor(Color.white);
	    g.drawLine(7,F_AXIS,getSize().width-15,F_AXIS);
	    MaestroG.drawArrow(getSize().width-15,F_AXIS,7,g);
            
            Graphics2D g2d = (Graphics2D)g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            
            // Print twice or smoothing makes it too faint on Mac - Mac sucks!!!
	    MaestroG.subscripterSer6("","f","","",g,12,getSize().width-24,F_AXIS+16);
	    MaestroG.subscripterSer6("","f","","",g,12,getSize().width-24,F_AXIS+16);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	    
            MaestroG.subscripter("0","","",g,12,7,F_AXIS+18);
            
	    g.drawLine(10,F_AXIS-5,10,F_AXIS+5);
	}
	
	/*public void update(Graphics g){
		g.clearRect(0,0,getSize().width,getSize().height);
		drawCanvas(g);
	}*/
	
	public synchronized void setFmax(double frequency){
	    this.fMax = frequency+0.2*frequency;
	}
	
	public synchronized void setTE(boolean IsTEmode ){
	    this.IsTEmode = IsTEmode;
	}
	
	private double getModeFrequency(int i, int j){
	    double myf;
	    double a, b;
	    a = state.a;
	    b = state.a / state.a_to_b_ratio;
	    myf = (1.0/Math.sqrt(state.epsilon0*state.epsilon_r*state.mu0*state.mu_r))*
		  Math.sqrt(
		    Math.pow((i*Math.PI/a),2.0)+Math.pow((j*Math.PI/b),2.0)
		  )/(2.0*Math.PI);
	    return myf;
	}
	
	
}	

