/**
 * TransGraphCanvas2.java
 * Graphs specific for the transmission lines
 */

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.lang.*;


public class TransGraphCanvas2 extends Canvas implements ComponentListener{
    //private static final Color bgcolor = Color.gray;
    //private static final Color bgcolor = new Color(236,236,221); // kaki
    private static final Color bgcolor = new Color(246,246,246);
    //private static final Color bgcolor = new Color(206,206,181); // kaki2
    //private static final Color bgcolor = new Color(255,255,255);// white
    //private static final Color bgcolor = new Color(216,216,216);// gray
    
    private double ymax, ymin, xmax, xmin;
    private boolean IsYRangeMaxSet, IsYRangeMinSet, IsXRangeMaxSet, IsXRangeMinSet;
    //private int LeftMargin=30, RightMargin=30, TopMargin=20, BottomMargin=20;
    private int LeftMargin=65, RightMargin=34, TopMargin=20, BottomMargin=20;
    private int WIDTH, HEIGHT;
    private String X1, X2, Y1, Y2, Y3, Y4, TITLE;
    private Image im;
    private Graphics buf;
    private int VPos = 0;
    private static final Font TitleFont = new Font("SanSerif",Font.PLAIN,11);
    private static final Font LabelFont = new Font("SanSerif",Font.PLAIN,11);
    private double[] x, y, ySWP, ySWPmin;
    protected double xpos, xposref;
    private int[] xx, yy, yySWP, yySWPmin;
    private int[] xx_old, yy_old;
    private int N;
    private boolean IsTraceOn, IsCleanUpOn, IsDynamic, IsEnvelope;
    public TransGraphCanvas2(){
        super();
        N = 1001;
        xpos = 0.0;
        xposref = 0.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;
        IsEnvelope = true;
        try{
            x = new double[N];
            y = new double[N];
            ySWP = new double[N];
            ySWPmin = new double[N];
            yySWP = new int[N];
            yySWPmin = new int[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;
            ySWP[i] = 0.0;
            ySWPmin[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 redo(Graphics g){
        g.clearRect(0,0,getSize().width-1,getSize().height);
    }
    public void drawGraph(Graphics g){
        if(!IsDynamic){
            g.clearRect(0,0,getSize().width-1,getSize().height);
        }
        drawAxis(g);
        labelDetect();
        drawLabels(g);
        
        drawPoints(g,1);
        //if(!IsDynamic){
        drawRef(g);
        //}
        
        drawZeroLine(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);
            yySWP[N-1-i] = (int)MaestroA.mapper(ySWP[i],(double)TopMargin+1,(double)(getSize().height-BottomMargin)-1,ymax,ymin);
            yySWPmin[N-1-i] = (int)MaestroA.mapper(ySWPmin[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:
                //if(!IsDynamic){g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);}
                if(IsEnvelope){
                
                    g.setColor(Color.magenta);
                    g.drawPolyline(xx,yySWP,xx.length);
                    g.drawPolyline(xx,yySWPmin,xx.length);
                    //for(int i = 0; i < xx.length-2; i++){
                      //  g.drawLine(xx[i],yySWPmin[i],xx[i+1],yySWPmin[i+1]);
                    //}
                }
                
                if(IsTraceOn){
                    //g.setColor(Color.yellow);
                    g.setColor(Color.blue);
                    g.drawPolyline(xx,yy,xx.length-1);
                    //g.setColor(Color.black);
                    g.setColor(Color.gray);
                    g.setColor(new Color(220,220,220));
                    g.drawPolyline(xx_old,yy_old,xx_old.length);
                }
                else{
                    //g.setColor(Color.black);
                    g.setColor(Color.blue);
                    
                    // CHANGE #1 6/18/2017 =====================================
                    // select drawPolyline instead of drawLine loop
                    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:
                //if(!IsDynamic){g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);}
                g.setColor(bgcolor);
                g.drawPolyline(xx_old,yy_old,xx_old.length-1);
                drawZeroLine(g);
                //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);
        
    }
    
    public void drawRef(Graphics g){
        
        if(!IsDynamic){
            xposref = xpos;
        }
        if(xposref <=xmax && xposref > xmin){
            int tx1right,tx1, ty1, tx2, ty2;
            tx1right = (int)MaestroA.mapper(xmin,(double)LeftMargin+1,(double)(getSize().width-RightMargin),xmax,xmin);
            tx1 = (int)MaestroA.mapper(xposref,(double)LeftMargin+1,(double)(getSize().width-RightMargin),xmax,xmin);
            ty1 = TopMargin;
            tx2 = tx1;
            ty2 = getSize().height-BottomMargin;
            //if(xposref == 0.0){
            //g.setColor(Color.black);
            //}
            //else{
            //g.setColor(Color.green);
            //}
            
            g.setColor(Color.green);
            g.drawLine(tx1,ty1,tx2,ty2);
            //g.setColor(Color.black);
            //g.drawLine(tx1right,ty1,tx1right,ty2);
            
        }
        else{
            
        }
    }
    
    private void labelDetect(){
        
        double tempmax=0.0;
        if(ymax>=1.0 && ymax<1.0E3 || ymax==0.0){
            tempmax = ymax;
        }
        else if(ymax<1.0E6 && ymax>=1.0e3){
            tempmax = ymax*1.0E-3;
        }
        else if(ymax>=1.0e6){
            tempmax = ymax*1.0E-6;
        }
        else if(ymax<1.0 && ymax>=1.0e-3){
            tempmax = ymax*1.0E3;
        }
        else if(ymax<1.0E-3 && ymax>=1.0e-6){
            tempmax = ymax*1.0E6;
        }
        else if(ymax<1.0E-6 && ymax>=1.0e-9){
            tempmax = ymax*1.0E9;
        }
        else if(ymax<1.0E-9 && ymax>=1.0E-12){
            tempmax = ymax*1.0E12;
        }
        else if(ymax<1.0E-12 && ymax>=1.0E-15){
            tempmax = ymax*1.0E15;
        }
        else if(ymax<1.0E-15){
            tempmax = ymax*1.0E18;
        }
        
        Y1 = String.valueOf(MaestroA.rounder(tempmax,3))+" ";
        
        if(ymin==0.0){
            Y2 = String.valueOf(MaestroA.rounder(ymin,3))+" ";
        }
        else{
            Y2 = String.valueOf(MaestroA.rounder(-tempmax,3))+" ";
        }
        Y3 = "_";
        Y4 = "|";
        
    }
    
    private void drawLabels(Graphics g){
        String tmp;
        g.setFont(LabelFont);
        g.clearRect(0,0,LeftMargin-1,getSize().height-1);
        g.clearRect(0,0,getSize().width-1,TopMargin-1);
        FontMetrics fm = g.getFontMetrics();
        tmp = X1;
        g.drawString(tmp,LeftMargin-1,VPos+fm.getHeight()+2);
        tmp = X2;
        g.drawString(tmp,getSize().width-RightMargin-fm.stringWidth(tmp)/2+1,VPos+fm.getHeight()+2);
        tmp = Y1;
        //g.drawString(tmp,LeftMargin-fm.stringWidth(tmp),TopMargin+fm.getHeight());
        g.drawString(tmp,LeftMargin-fm.stringWidth(tmp)-10,TopMargin);
        tmp = Y2;
        g.drawString(tmp,LeftMargin-fm.stringWidth(tmp)-10,VPos);
        
        tmp = Y3;
        g.drawString(tmp,LeftMargin-5,VPos-1);
        g.drawString(tmp,LeftMargin-5, TopMargin);
        g.drawString(tmp,getSize().width-RightMargin,VPos-1);
        g.drawString(tmp,getSize().width-RightMargin,TopMargin);
        tmp = Y4;
        g.drawString(tmp,LeftMargin,VPos+4);
        g.drawString(tmp,getSize().width-RightMargin-fm.stringWidth(tmp)/2+1,VPos+4);
        
        tmp = TITLE;
        g.setFont(TitleFont);
        //g.drawString(tmp,LeftMargin+(WIDTH-fm.stringWidth(tmp))/2,TopMargin-fm.getHeight()/2);
        g.drawString(tmp,LeftMargin+2,TopMargin-2);
    }
    
    private void drawZeroLine(Graphics g){
        int myY;
        myY = (int)MaestroA.mapper(0,(double)TopMargin,(double)VPos,ymax,ymin);
        g.setColor(Color.red);
        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 synchronized void setEnvelope(boolean IsEnvelope){
        this.IsEnvelope = IsEnvelope;
    }
    
    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
            //drawRef(g);
        }
        drawPoints(g,1);//This draws the new graph
        
        drawRef(g);
        
        push();
    }
    
    
    public void plot(double xdata[], double ydata[], double ySWPdata[], double ySWPmindata[]){
        N = xdata.length;
        x = new double[N];
        y = new double[N];
        ySWP = new double[N];
        ySWPmin = new double[N];
        yySWP = new int[N];
        yySWPmin = new int[N];
        xx = new int[N];
        yy = new int[N];
        for(int i = 0; i < N; i++){
            x[i] = xdata[i];
            y[i] = ydata[i];
            ySWP[i] = ySWPdata[i];
            ySWPmin[i] = ySWPmindata[i];
            //System.out.println(i+"  "+ySWP[i]+"  "+ySWPmin[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] = -10;
        }
    }
    
    
    
    
    public synchronized void setTitle(String TITLE){
        this.TITLE = TITLE;
    }
    
    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();*/}
    
}
