/**
 * TransGraphCanvas.java
 * Graphs specific for the transmission lines
 */

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.lang.*;


public class TransGraphCanvas extends Canvas implements ComponentListener{
    private static final Color bgcolor = new Color(236,236,221); // kaki
       
    private double ymax, ymin, xmax, xmin;
    private boolean IsYRangeMaxSet, IsYRangeMinSet, IsXRangeMaxSet, IsXRangeMinSet; 
    private int LeftMargin, RightMargin, TopMargin, BottomMargin;
    private int WIDTH, HEIGHT;
    private String X1, X2, Y1, Y2, Y3, Y4, TITLE;
    private Image im;
    private Graphics buf;
    private int VPos = 0;
    private Font TitleFont;
    private Font LabelFont;
    private double[] x, y;
    protected double xpos;
    private int[] xx, yy;
    private int[] xx_old, yy_old;
    private int N;
    private int Flag;
    private boolean IsTraceOn, IsCleanUpOn, IsDynamic;
    Trans_State state;
    
    public TransGraphCanvas(Trans_State state){
	super();
        this.state = state;
        
        TitleFont = new Font("SanSerif",Font.PLAIN,state.font11);
        LabelFont = new Font("SanSerif",Font.PLAIN,state.font11);
        
        LeftMargin = state.s65;
        RightMargin = state.s35;
        TopMargin = state.s20;
        BottomMargin = state.s20;
        
	N = 100;
	Flag = 0;
	setBackground(bgcolor);
	xmax = 1.0;
	xmin = 0.0;
	ymax = 2.0;
	ymin = -2.0;
	X1 = "l";
	X2 = "0";
	Y1 = "  ";
	Y2 = "  ";
	TITLE = "  ";
	IsYRangeMaxSet = false;
	IsYRangeMinSet = false;
	IsXRangeMaxSet = false;
	IsXRangeMinSet = false;
	IsTraceOn = false;
	IsCleanUpOn = false;
	IsDynamic = false;
	try{
	    x = new double[N];
	    y = new double[N];
	    xx = new int[N];
	    yy = new int[N];
	    xx_old = new int[N];
	    yy_old = new int[N];
	}
	catch(Exception e){e.printStackTrace();}
	for(int i = 0; i < x.length; i++){
	    x[i] = (double)i;
	    y[i] = 0.0;
	}
	//Listeners
	this.addComponentListener(this);
    }
    
    public void paint(Graphics g){
	if(im == null){
	    im = createImage(getSize().width,getSize().height);
	    buf = im.getGraphics();
	    drawGraph(buf);
	}
	else{
	 drawGraph(buf);
	}
	g.drawImage(im,0,0,null);
    }
    
    
    public void drawGraph(Graphics g){
	if(!IsDynamic){
	    g.clearRect(0,0,getSize().width-1,getSize().height-1);
	}
	drawAxis(g);
	labelDetect();
	drawLabels(g);
	drawZeroLine(g);
	drawPoints(g,1);
	drawRef(g);
        drawAxis(g);
    }
    
    private void ignition(){
	N = x.length;
	//Find the boundaries for data
    	if(!IsYRangeMaxSet){ ymax = MaestroA.getMax(y);}
	if(!IsYRangeMinSet){ ymin = MaestroA.getMin(y);}
	
	if(!IsXRangeMaxSet){ xmax = x[x.length-1];}
	if(!IsXRangeMinSet){ xmin = x[0]; }
	
	//Confine data
	MaestroA.confiner(x,xmax,xmin);
	MaestroA.confiner(y,ymax,ymin);
	if(ymax==0.0 && ymin==0.0){ymax=0.001;}
	
	//Reverse Mapping
	for(int i = 0; i < xx.length; i++){
	    xx[N-1-i] = (int)MaestroA.mapper(x[i],(double)LeftMargin+1,(double)(getSize().width-RightMargin),xmax,xmin);
	    yy[N-1-i] = (int)MaestroA.mapper(y[i],(double)TopMargin+1,(double)(getSize().height-BottomMargin)-1,ymax,ymin);
	   
	}
    }
    
    private void drawPoints(Graphics g, int tipo){
        Graphics2D g2d = (Graphics2D)g;
	switch(tipo){
	    case 1:
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

		if(IsTraceOn){
		    //g.setColor(Color.yellow);
		    g.setColor(Color.green);
		    g.drawPolyline(xx,yy,xx.length-1);
		    //g.setColor(Color.black);
                    g.setColor(Color.gray);
		    g.drawPolyline(xx_old,yy_old,xx_old.length-1);
		}
		else{
		    //g.setColor(Color.black);
                    g.setColor(Color.gray);
		    //g.drawPolyline(xx,yy,xx.length);
		    for(int i = 0; i < xx.length-2; i++){
			    g.drawLine(xx[i],yy[i],xx[i+1],yy[i+1]);
		    }
		}
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);

		break;
	    case 2:
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		g.setColor(bgcolor);
		g.drawPolyline(xx_old,yy_old,xx_old.length-1);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);

		break;
	}
    }
       
    private void drawAxis(Graphics g){
	//VPos = getSize().height - BottomMargin;
	//WIDTH = getSize().width - LeftMargin -RightMargin;
	//HEIGHT = VPos - TopMargin;
	//g.setColor(Color.black);
	//g.drawLine(LeftMargin,VPos,getSize().width-RightMargin,VPos);
	//g.drawLine(LeftMargin,TopMargin,LeftMargin,VPos);
	//g.drawLine(getSize().width-RightMargin,TopMargin,getSize().width-RightMargin,VPos);
	
        VPos = getSize().height - BottomMargin;
        WIDTH = getSize().width - LeftMargin -RightMargin;
        HEIGHT = VPos - TopMargin;
        g.setColor(Color.black);
        g.drawLine(LeftMargin-state.s5,VPos,getSize().width-RightMargin,VPos);
        g.drawLine(LeftMargin,TopMargin,LeftMargin,VPos+state.s5);
        g.drawLine(getSize().width-RightMargin,TopMargin,getSize().width-RightMargin,VPos+state.s5);
        
    }
    
    private void labelDetect(){
	
	if(ymax==0.0){
	    Y1 = "0.0";
	}
	else if(Math.abs(ymax)>=1.0){
	    Y1 = String.valueOf(MaestroA.rounder(ymax,2))+" ";
	}
	else if(Math.abs(ymax)<1.0 && Math.abs(ymax)>0.0){
	    Y1 = String.valueOf(MaestroA.rounder(ymax,5))+" ";
	}
	
	if(ymin==0.0){
	    Y2 = "0.0";
	}
	else if(Math.abs(ymin)>=1.0){
	    Y2 = String.valueOf(MaestroA.rounder(ymin,2))+" ";
	}
	else if(Math.abs(ymin)<1.0 && Math.abs(ymin)>0.0){
	    Y2 = String.valueOf(MaestroA.rounder(ymin,5))+" ";
	}
	
	Y3 = "_";
	Y4 = "|";

    }
    
    public void drawRef(Graphics g){
	   
   	  if(xpos <=xmax && xpos >= xmin){
		int tx1, ty1, tx2, ty2;
		tx1 = (int)MaestroA.mapper(xpos,(double)LeftMargin+1,(double)(getSize().width-RightMargin),xmax,xmin);
		ty1 = TopMargin;
		tx2 = tx1;
		ty2 = getSize().height-BottomMargin;
		
		if(xpos == 0.0){
		    g.setColor(Color.black);
		}
		else{
		    g.setColor(Color.green.darker());
		}
		g.drawLine(tx1,ty1,tx2,ty2);
          }
    }	
    
    private void drawLabels(Graphics g){
        Font symbolfont=new Font("Symbol",Font.PLAIN,12);
        Font normalfont=new Font("SanSerif",Font.PLAIN,11);
        Font Lfont=new Font("Serif",Font.ITALIC,state.s12);
        
        String alpha, Ohm, lambda, infinity, Gamma, epsilon;
	
		alpha="\u03b1";
		lambda="\u03bb";
		Ohm="\u03a9";
		infinity="\u221e";
		Gamma="\uu0393"; 
		epsilon="\u03b5";
		
	String tmp;
	g.setFont(LabelFont);
	g.clearRect(0,0,LeftMargin-state.s1,getSize().height-state.s1);
	g.clearRect(0,0,getSize().width-state.s1,TopMargin-state.s1);
	FontMetrics fm = g.getFontMetrics();
	
        tmp = X1;
        g.setFont(Lfont);
        fm = g.getFontMetrics();
	g.drawString(tmp,LeftMargin,VPos+fm.getHeight());
	g.setFont(LabelFont);
        fm = g.getFontMetrics();
        
        tmp = X2;
	g.drawString(tmp,getSize().width-RightMargin-fm.stringWidth(tmp)/2+state.s1,VPos+fm.getHeight()+state.s2);
	
        tmp = Y1;
	g.drawString(tmp,LeftMargin-fm.stringWidth(tmp)-state.s10,TopMargin);
	
        tmp = Y2;
	g.drawString(tmp,LeftMargin-fm.stringWidth(tmp)-state.s10,VPos);
	
	tmp = Y3;
	//g.drawString(tmp,LeftMargin-state.s5,VPos-state.s1);
	//g.drawString(tmp,LeftMargin-state.s5, TopMargin);
	//g.drawString(tmp,getSize().width-RightMargin,VPos-state.s1);
	//g.drawString(tmp,getSize().width-RightMargin,TopMargin);
        
        g.drawLine(LeftMargin-state.s5, TopMargin, LeftMargin, TopMargin);
        
        tmp = Y4;
	//g.drawString(tmp,LeftMargin,VPos+state.s4);
	//g.drawString(tmp,getSize().width-RightMargin-fm.stringWidth(tmp)/2+state.s1,VPos+state.s4);
	
	tmp = TITLE;
	g.setFont(TitleFont);
	g.drawString(tmp,LeftMargin+state.s2,TopMargin-state.s2);
	if(Flag == 1){
	    //g.setFont(new Font("Serif",Font.PLAIN,state.font12));
	    //g.drawString(""+Ohm,LeftMargin+fm.stringWidth(tmp)-state.s12,TopMargin-state.s2);
	    //g.setFont(new Font("SanSerif",Font.PLAIN,state.font12));  
	}
	else if(Flag == 2){
	    //g.setFont(new Font("Serif",Font.PLAIN,state.font12));
	    //g.drawString(""+Gamma,LeftMargin+state.s21,TopMargin-state.s2);
	    //g.setFont(new Font("SanSerif",Font.PLAIN,state.font12));
	}
    }
    
    private void drawZeroLine(Graphics g){
	int myY;
	myY = (int)MaestroA.mapper(0,(double)TopMargin,(double)VPos,ymax,ymin);
	g.setColor(Color.red);
	if(ymin==0.0 || ymax ==0.0 || (ymax>0.0 && ymin <0.0)){
	    g.drawLine(LeftMargin+1,myY,getSize().width-RightMargin-1,myY);
	}
    }
    
    
    public synchronized void reset(){
	IsYRangeMaxSet = false;
	IsYRangeMinSet = false;
	IsXRangeMaxSet = false;
	IsXRangeMinSet = false;
	IsTraceOn = false;
	IsCleanUpOn = false;
    }
    
    public synchronized void cleanUp(){
	IsCleanUpOn=true;
    }
    
    public synchronized void setYRangeMax(double ymax){
	this.ymax = ymax;
	IsYRangeMaxSet = true;
    }
    
    public synchronized void setYRangeMin(double ymin){
	this.ymin = ymin;
	IsYRangeMinSet = true;
    }
    
    public synchronized void setXRangeMax(double xmax){
	this.xmax = xmax;
	IsXRangeMaxSet = true;
    }
    
    public synchronized void setXRangeMin(double xmin){
	this.xmin = xmin;
	IsXRangeMinSet = true;
    }
    
    public synchronized void setTrace(boolean IsTraceOn){
	this.IsTraceOn = IsTraceOn;
	this.clean_memory();
    }
    
    public synchronized void setDynamics(boolean IsDynamic){
	this.IsDynamic = IsDynamic;
    }
    
/*
    public void update(Graphics g){
	if(!IsDynamic){
	    super.update(g);
	    return;
	}
	if(IsDynamic && IsTraceOn){g.clipRect(LeftMargin+1,TopMargin+1,WIDTH-1,HEIGHT-1);}
	if(IsCleanUpOn){
	    //g.clearRect(0,0,getSize().width-1,getSize().height-1);
	    g.clearRect(LeftMargin+1,TopMargin+1,WIDTH-1,HEIGHT-1);
	    IsCleanUpOn = false;
	}
	drawZeroLine(g);
	if(!IsTraceOn){
	    drawPoints(g,2);//This cleans the previous graph
	}
	drawPoints(g,1);//This draws the new graph
	push();
    }
  */  
    
    public void update(Graphics g){		// added to avoid clearing
	paint(g);
    }


    public void plot(double xdata[], double ydata[]){
	N = xdata.length;
	x = new double[N];
	y = new double[N];
	xx = new int[N];
	yy = new int[N];
	for(int i = 0; i < N; i++){
	    x[i] = xdata[i];
	    y[i] = ydata[i];
	}
	ignition();
	repaint();
    }
    
    private void push(){
	if(xx.length != xx_old.length){
	    xx_old = new int[xx.length];
	    yy_old = new int[xx.length];
	}
    
	for(int i = 0; i < xx.length; i++){
	    xx_old[i] = xx[i];
	    yy_old[i] = yy[i];
	}
    }
    
     private void clean_memory(){
	if(xx.length != xx_old.length){
	    xx_old = new int[xx.length];
	    yy_old = new int[xx.length];
	}
    
	for(int i = 0; i < xx.length; i++){
	    xx_old[i] = xx[i];
	    yy_old[i] = 0;
	}
    }
    
    
    
    
    public synchronized void setTitle(String TITLE){
	this.TITLE = TITLE;
    }
    public synchronized void setFlag(int number){
	this.Flag = number;
    }
    public void setXpos(double xpos){
	this.xpos = xpos;   
    }
    
    public void componentHidden(ComponentEvent evt){/*cleanUp();*/}
    public void componentMoved(ComponentEvent evt){/*cleanUp();*/}
    public void componentResized(ComponentEvent evt){/*cleanUp();*/}
    public void componentShown(ComponentEvent evt){/*cleanUp();*/}
     
}
