//Mod3Input.java
/*
 * Panel with all input operations for Module1.1
 * Using null layout - positions of elements hard-coded
 * authors: Umberto Ravaioli, Janice Richards
 * version 1.0 - Copyright: Amanogawa.com - All Rights Reserved
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.text.*;
import java.io.IOException;
import javax.swing.*;
import javax.swing.event.*;

public class Mod3Input extends Panel {
    private Mod3State state;
    private static final Color bgcolor = new Color(236,236,236);
    public Choice ch;
    public TextField textA, textB, textM, textN;
    private Label labA, labB, labM, labN;
    //private Label ulabA, ulabB, ulabM, ulabN;
    public JSlider sliderA, sliderB, sliderM, sliderN,
        sliderM_other, sliderN_other, sliderM_sin, sliderN_sin;
    public int ScrollMax = 200;
    //public int ScrollMax_2 = 10; // was 60 -3.0 - +3.0 by .1
    public int ScrollMax_2 = 5; // 0 - 5 (ScrollMax_2+1)
    public int ScrollMax_3 = 10; // -5 - 5 (ScrollMax_3+1)
    public int ScrollMax2;  // either ScrollMax_2 or ScrollMax_3 if sinusoidal

    //private String functionString = "";
    private String gradientString = "";
    //private BufferedImage x, check, mark;
    private String nullString = "NULL";

    private static Font tinyfont, boldTinyfont,
        labfont, boldLabfont, boldfont, normalfont;
    DecimalFormat dec = new DecimalFormat("###.#");
    DecimalFormat dec2 = new DecimalFormat("##");

    int vPos, vHeight;


    public Mod3Input(Mod3State state){
	super();
	setLayout(null);
	setBackground(bgcolor);
	this.state = state;

        tinyfont = state.sanSerifFont.deriveFont(10F);
        boldTinyfont = state.sanSerifFont.deriveFont(Font.BOLD,10F);
        //boldTinyfont = state.sanSerifFont.deriveFont(10F);
        labfont = state.sanSerifFont.deriveFont(12F);
        boldLabfont = state.sanSerifFont.deriveFont(Font.BOLD,12F);
        //boldLabfont = state.sanSerifFont.deriveFont(12F);
        normalfont = state.sanSerifFont.deriveFont(14F);
        boldfont = state.sanSerifFont.deriveFont(Font.BOLD,14F);
        //boldfont = state.sanSerifFont.deriveFont(12F);

	
        Label chLabel = new Label("Select function: ",Label.LEFT);
        chLabel.setFont(boldLabfont);
	ch = new Choice();
        //ch.setFont(TheFonts.sanSerif14);
        ch.setFont(boldfont);
	ch.addItem(" polynomial");
	ch.addItem(" exponential");
	ch.addItem(" sinusoidal");

        


	labA = new Label("x coefficent ",Label.RIGHT);
        labA.setFont(boldfont);
        labA.setForeground(state.color1);

	labB = new Label("y coefficent ",Label.RIGHT);
        labB.setFont(boldfont);
        labB.setForeground(state.color2);

	labM = new Label("x exponent ",Label.RIGHT);
        labM.setFont(boldfont);
        labM.setForeground(state.color3);

	labN = new Label("y exponent ",Label.RIGHT);
        labN.setFont(boldfont);
        labN.setForeground(state.color4);
		
        textA = new TextField(5);
        textA.setFont(boldLabfont);
        textA.setForeground(state.color1);

        textB = new TextField(5);
        textB.setFont(boldLabfont);
        textB.setForeground(state.color2);
		
        textM = new TextField(2);
        //textM.setFont(tinyfont);
        textM.setForeground(state.color3);

        textN = new TextField(2);
        //textN.setFont(tinyfont);
        textN.setForeground(state.color4);

	sliderA = new JSlider(0,ScrollMax+1);
	sliderB = new JSlider(0,ScrollMax+1);
	sliderM_other = new JSlider(0,ScrollMax_2+1);
	sliderN_other = new JSlider(0,ScrollMax_2+1);
        sliderM_sin = new JSlider(0,ScrollMax_3+1);
        sliderN_sin = new JSlider(0,ScrollMax_3+1);
	/*
	sliderA = new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,ScrollMax+1);
	sliderB = new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,ScrollMax+1);
	sliderM_other = 
            new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,ScrollMax_2+1);
	sliderN_other =
            new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,ScrollMax_2+1);
        sliderM_sin = 
            new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,ScrollMax_3+1);
        sliderN_sin = 
            new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,ScrollMax_3+1);
	*/
        sliderM_sin.setVisible(false);
        sliderN_sin.setVisible(false);


	add(chLabel);
        add(ch);
        add(labA);
        add(labB);
        add(labM);
        add(labN);
        add(textA);
        add(textB);
        add(textM);
        add(textN);
        add(sliderA);
        add(sliderB);
        add(sliderM_other);
        add(sliderN_other);
        add(sliderM_sin);
        add(sliderN_sin);

        // TEMPORARY?? 7/26/14 try to get rid of "..." on macs
        //chLabel.setBounds(20,35,100,20);
        //ch.setBounds(120,35,120,20);
        chLabel.setBounds(20,35,120,20);
        ch.setBounds(140,35,140,20);

	//int vPosInit = 107, vPos, dvPos = 8, vHeight = 20; 
        int vPosInit = 107, dvPos = 8;
        vHeight = 20;
	vPos = vPosInit;
	
	labA.setBounds(20,vPos,120,vHeight);
	sliderA.setBounds(142,vPos+2,196,vHeight);
	/*
	Panel ps1 = new Panel();
            ps1.setBackground(Mod3State.color1);
	    add(ps1);
	    ps1.setBounds(141,vPos+1,198,vHeight+2);
	    
	Panel ps2 = new Panel();
	    ps2.setBackground(Color.black);
	    add(ps2);
	    ps2.setBounds(140,vPos,200,vHeight+4);
	*/
	vPos += vHeight + dvPos; 
	
	labB.setBounds(20,vPos,120,vHeight);
	sliderB.setBounds(142,vPos+2,196,vHeight);
	/*
	Panel ps3 = new Panel();
            ps3.setBackground(Mod3State.color2);
	    add(ps3);
	    ps3.setBounds(141,vPos+1,198,vHeight+2);
	    
	Panel ps4 = new Panel();
	    ps4.setBackground(Color.black);
	    add(ps4);
	    ps4.setBounds(140,vPos,200,vHeight+4);
	*/
	vPos += vHeight + dvPos; 
	
	labM.setBounds(20,vPos,120,vHeight);
	sliderM_other.setBounds(142,vPos+2,196,vHeight);
	sliderM_sin.setBounds(142,vPos+2,196,vHeight);
	/*
	Panel ps5 = new Panel();
            ps5.setBackground(Mod3State.color3);
	    add(ps5);
	    ps5.setBounds(141,vPos+1,198,vHeight+2);
	    
	Panel ps6 = new Panel();
	    ps6.setBackground(Color.black);
	    add(ps6);
	    ps6.setBounds(140,vPos,200,vHeight+4);
	*/
	vPos += vHeight + dvPos; 
	
	labN.setBounds(20,vPos,120,vHeight);
	sliderN_other.setBounds(142,vPos+2,196,vHeight);
	sliderN_sin.setBounds(142,vPos+2,196,vHeight);
	/*
	Panel ps7 = new Panel();
            ps7.setBackground(Mod3State.color4);
	    add(ps7);
	    ps7.setBounds(141,vPos+1,198,vHeight+2);
	    
	Panel ps8 = new Panel();
	    ps8.setBackground(Color.black);
	    add(ps8);
	    ps8.setBounds(140,vPos,200,vHeight+4);
	*/
            vPos += 2*(vHeight + dvPos); 

            //System.out.println("vPos = "+vPos);
        layoutPolynomialEqn();
        
        // textM, textN, sliderM, and sliderN intialized in the 
        //   layout...() functions:
	textA.setText(""+dec.format(state.aVal));
	sliderA.setValue((int)((state.aVal-state.aMin)*
                               ScrollMax/(state.aMax-state.aMin)));
	textB.setText(""+dec.format(state.bVal));
	sliderB.setValue((int)((state.bVal-state.bMin)*
                               ScrollMax/(state.bMax-state.bMin)));
        
        /*
        // Initialize textfields and sliders:
	textA.setText(""+dec.format(state.aVal));
	sliderA.setValue((int)((state.aVal-state.aMin)*
                               ScrollMax/(state.aMax-state.aMin)));
	textB.setText(""+dec.format(state.bVal));
	sliderB.setValue((int)((state.bVal-state.bMin)*
                               ScrollMax/(state.bMax-state.bMin)));
        textM.setText(""+dec.format(state.mVal));
	sliderM.setValue((int)((state.mVal-state.mMin)*
                               ScrollMax2/(state.mMax-state.mMin)));
        textN.setText(""+dec.format(state.nVal));
	sliderN.setValue((int)((state.nVal-state.nMin)*
                               ScrollMax2/(state.nMax-state.nMin)));
        */
        //repaint();
    }


    public void layoutPolynomialEqn() {
        ScrollMax2 = ScrollMax_2;
        sliderM_sin.setVisible(false);
        sliderN_sin.setVisible(false);
        sliderM_other.setVisible(true);
        sliderN_other.setVisible(true);
        state.mMin = state.mnMin;
        state.mMax = state.mnMax;
        state.nMin = state.mnMin;
        state.nMax = state.mnMax;
        sliderM = sliderM_other;
        sliderN = sliderN_other;

        labA.setText("x coefficent ");
        labB.setText("y coefficent ");
        labM.setText("x exponent ");
        labN.setText("y exponent ");
        textM.setFont(boldTinyfont);
        textN.setFont(boldTinyfont);
        //textA.setBounds(70,vPos,40,vHeight);
        textA.setBounds(60,vPos,35,vHeight);
        //textM.setBounds(125,vPos-10,32,vHeight-5);
        textM.setBounds(110,vPos-10,18,vHeight-5);
        //textB.setBounds(177,vPos,40,vHeight);
        textB.setBounds(162,vPos,35,vHeight);
        //textN.setBounds(232,vPos-10,32,vHeight-5);
        textN.setBounds(212,vPos-10,18,vHeight-5);
        fixMandNValues();

        recalcDivergenceStuffA();        
        recalcDivergenceStuffB();        
    }


    private void fixMandNValues() {
        // M and N current values may no longer be valid
        //  (e.g. from sinusoidal to polynomial); also need to
        //  update sliders since they can be different:
        if (state.mVal < state.mMin) state.mVal = state.mMin;
        else if (state.mVal > state.mMax) state.mVal = state.mMax;
        if (state.nVal < state.nMin) state.nVal = state.nMin;
        else if (state.nVal > state.nMax) state.nVal = state.nMax;

        textM.setText(""+dec2.format(state.mVal));
	sliderM.setValue((int)((state.mVal-state.mMin)*
                               ScrollMax2/(state.mMax-state.mMin)));
        textN.setText(""+dec2.format(state.nVal));
	sliderN.setValue((int)((state.nVal-state.nMin)*
                               ScrollMax2/(state.nMax-state.nMin)));
    }


    public void layoutExponentialEqn() {
        ScrollMax2 = ScrollMax_2;
        sliderM_sin.setVisible(false);
        sliderN_sin.setVisible(false);
        sliderM_other.setVisible(true);
        sliderN_other.setVisible(true);
        state.mMin = state.mnMin;
        state.mMax = state.mnMax;
        state.nMin = state.mnMin;
        state.nMax = state.mnMax;
        sliderM = sliderM_other;
        sliderN = sliderN_other;

        labA.setText("x coefficent ");
        labB.setText("y coefficent ");
        labM.setText("x exponent ");
        labN.setText("y exponent ");
        textM.setFont(boldTinyfont);
        textN.setFont(boldTinyfont);
        //textA.setBounds(70,vPos,40,vHeight);
        textA.setBounds(60,vPos,35,vHeight);
        //textM.setBounds(125,vPos-5,32,vHeight-5);
        textM.setBounds(110,vPos-5,18,vHeight-5);
        //textB.setBounds(186,vPos,40,vHeight);
        textB.setBounds(171,vPos,35,vHeight);
        //textN.setBounds(240,vPos-5,32,vHeight-5);
        textN.setBounds(221,vPos-5,18,vHeight-5);
        fixMandNValues();

        recalcDivergenceStuffA();        
        recalcDivergenceStuffB();        
    }


    public void layoutSinusoidalEqn() {
        ScrollMax2 = ScrollMax_3;
        sliderM_sin.setVisible(true);
        sliderN_sin.setVisible(true);
        sliderM_other.setVisible(false);
        sliderN_other.setVisible(false);
        state.mMin = state.mnMinSin;
        state.mMax = state.mnMaxSin;
        state.nMin = state.mnMinSin;
        state.nMax = state.mnMaxSin;
        sliderM = sliderM_sin;
        sliderN = sliderN_sin;

        labA.setText("cos coefficent ");
        labB.setText("sin coefficent ");
        labM.setText("cos parameter ");
        labN.setText("sin parameter ");
        textM.setFont(boldLabfont);
        textN.setFont(boldLabfont);
        //textA.setBounds(70,vPos,40,vHeight);
        textA.setBounds(60,vPos,35,vHeight);
        //textM.setBounds(142,vPos,40,vHeight);
        textM.setBounds(128,vPos,35,vHeight); // 142-14 =  128
        //textB.setBounds(220,vPos,40,vHeight);
        textB.setBounds(215,vPos,35,vHeight);
        //textN.setBounds(289,vPos,40,vHeight);
        textN.setBounds(282,vPos,35,vHeight);
        fixMandNValues();

        recalcDivergenceStuffA();        
        recalcDivergenceStuffB();        
    }



    public void updateParamA() {
        if(sliderA.getValue()>=ScrollMax){
            state.aVal=state.aMax;
            sliderA.setValue((int)((state.aVal-state.aMin)*
                                    ScrollMax/(state.aMax-state.aMin)));
        } else {
            state.aVal = state.aMin + 
                (state.aMax-state.aMin)*
                sliderA.getValue()/ScrollMax;
            //state.aVal = MaestroA.rounder(state.aVal,5);
        }
        
        //textA.setText(""+dec.format(MaestroA.rounder(state.aVal,5)));
        textA.setText(""+dec.format(state.aVal));
        recalcDivergenceStuffA();
    }



    public void updateParamB() {
        if(sliderB.getValue()>=ScrollMax){
            state.bVal=state.bMax;
            sliderB.setValue((int)((state.bVal-state.bMin)*
                                    ScrollMax/(state.bMax-state.bMin)));
        } else {
            state.bVal = state.bMin + 
                (state.bMax-state.bMin)*
                sliderB.getValue()/ScrollMax;
            //state.bVal = MaestroA.rounder(state.bVal,5);
        }
        
        //textB.setText(""+dec.format(MaestroA.rounder(state.bVal,5)));
        textB.setText(""+dec.format(state.bVal));
        recalcDivergenceStuffB();
    }



    public void updateParamM() {
        if(sliderM.getValue()>=ScrollMax2){
            state.mVal=state.mMax;
            sliderM.setValue((int)((state.mVal-state.mMin)*
                                    ScrollMax2/(state.mMax-state.mMin)));
        } else {
            state.mVal = state.mMin + 
                (state.mMax-state.mMin)*
                sliderM.getValue()/ScrollMax2;
            //state.mVal = MaestroA.rounder(state.mVal,5);
        }
        
        //textM.setText(""+dec.format(MaestroA.rounder(state.mVal,5)));
        textM.setText(""+dec2.format(state.mVal));
        recalcDivergenceStuffA();
    }



    public void updateParamN() {
        if(sliderN.getValue()>=ScrollMax2){
            state.nVal=state.nMax;
            sliderN.setValue((int)((state.nVal-state.nMin)*
                                    ScrollMax2/(state.nMax-state.nMin)));
        } else {
            state.nVal = state.nMin + 
                (state.nMax-state.nMin)*
                sliderN.getValue()/ScrollMax2;
            //state.nVal = MaestroA.rounder(state.nVal,5);
        }
        
        //textN.setText(""+dec.format(MaestroA.rounder(state.nVal,5)));
        textN.setText(""+dec2.format(state.nVal));
        recalcDivergenceStuffB();
    }



    public void adjustSliderA() {
        readTextUpdateSlider(textA, sliderA, state.aMin, state.aMax);
        recalcDivergenceStuffA();
    }

    public void adjustSliderB() {
        readTextUpdateSlider(textB, sliderB, state.bMin, state.bMax);
        recalcDivergenceStuffB();
    }

    public void adjustSliderM() {
        readTextUpdateSlider(textM, sliderM, state.mMin, state.mMax);
        recalcDivergenceStuffA();
    }

    public void adjustSliderN() {
        readTextUpdateSlider(textN, sliderN, state.nMin, state.nMax);
        recalcDivergenceStuffB();
    }


    // NEED to recalculate gradient coefficients for BOTH plotpanel and
    //  infopanel to use (plotting arrows, and displaying gradient equation)

    private void  recalcDivergenceStuffA() {
        switch(state.currentFunction) {
        case Mod3State.polynomial:
            state.coeff1 = state.mVal*state.aVal;
            state.exp1 = state.mVal-1.0;
            break;
        case Mod3State.exponential:
            state.coeff1 = state.mVal*state.aVal;
            state.exp1 = state.mVal;
            break;
         case Mod3State.sinusoidal:
            state.coeff1 = -1.0*state.mVal*state.aVal;
            state.coeff2 = state.mVal;
        }   
    }



    private void  recalcDivergenceStuffB() {
        switch(state.currentFunction) {
        case Mod3State.polynomial:
            state.coeff2 = state.nVal*state.bVal;
            state.exp2 = state.nVal-1.0;
            break;
        case Mod3State.exponential:
            state.coeff2 = state.nVal*state.bVal;
            state.exp2 = state.nVal;
            break;
         case Mod3State.sinusoidal:
            state.coeff3 = state.nVal*state.bVal;
            state.coeff4 = state.nVal;
        }   
    }

    
    
    private void readTextUpdateSlider(TextField textF, JSlider slider,
                                     double min, double max) {
        double value = 0;
        int ScrollMax = this.ScrollMax;
        if (textF == textM || textF == textN) {
            int val = 0;
            ScrollMax = this.ScrollMax2;
            // force both m and n to be INTEGRAL: (could also use Math.floor())
            try {
                val = Math.round(Float.valueOf(textF.getText()).floatValue());
            } catch (NumberFormatException e){
                val =  0;
            }
            value = (double) val;
            if (value <= max && value >= min) {
                textF.setText(" "+dec2.format(val));
                slider.setValue((int)(ScrollMax*(value-min)/(max-min)));
            } else if (value > max) {
                value = max;
                textF.setText(" "+dec2.format((int)value));
                slider.setValue(ScrollMax);
            } else if (value < min) {
                value = min;
                textF.setText(""+dec2.format((int)value));
                slider.setValue(0);
            }
        } else {
            try {
                value = Double.valueOf(textF.getText()).doubleValue();
            } catch (NumberFormatException e){
                value =  0.0;
            }
            if (value <= max && value >= min) {
                textF.setText(" "+dec.format(value));
                slider.setValue((int)(ScrollMax*(value-min)/(max-min)));
            } else if (value > max){
                value = max;
                textF.setText(""+dec.format(value));
                slider.setValue(ScrollMax);
            } else if (value < min){
                  value = min;
                  textF.setText(""+dec.format(value));
                  slider.setValue(0);
              }
        }
        setStateValue(textF,value);
        //repaint();
    }




    private void setStateValue(TextField textF, double value) {
        if (textF == textA) state.aVal = value;
        else if (textF == textB) state.bVal = value;
        else if (textF == textM) state.mVal = value;
        else if (textF == textN) state.nVal = value;
    }


    
    public void displayFunction() {
        /*
        switch(state.currentFunction) {
        case 0:
            functionString = "";
            break;
        case Mod3State.polynomial:
            functionString = "f(x,y) = x";
            break;
        case Mod3State.exponential:
            functionString = "f(x,y) = x+y";
            break;
        case Mod3State.sinusoidal:
            functionString = "f(x,y) = x-y";
            break;
        }
        */
        repaint();
    }
    


    /*
    public void displayDivergence() {
        switch(state.currentFunction) {
        case 0:
            gradientString = "";
            break;
        case Mod3State.polynomial:
            gradientString = "g1";
            break;
        case Mod3State.exponential:
            gradientString = "g2";
            break;
        case Mod3State.sinusoidal:
            gradientString = "g3";
            break;
        }
        repaint();
    }
    */

    
    public void paint(Graphics g){
        //Graphics2D g2d = (Graphics2D)g;
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        //                     RenderingHints.VALUE_ANTIALIAS_ON);
	
	g.setColor(bgcolor.darker());
	g.fillRect(0,getSize().height-2,getSize().width,2);
	g.fillRect(getSize().width-2,0,2,getSize().height);
	g.setColor(bgcolor.brighter());
	g.fillRect(0,0,2,getSize().height-1);
	g.fillRect(0,0,getSize().width-2,2);


        int endingX;
        String s;
        g.setColor(Color.black);
        g.setFont(TheFonts.bold16);
        s = "Input";
        endingX = STR.displayString(s,g,10,20);

        //g.setFont(normalfont);
        g.setFont(boldfont);
        g.setColor(Color.black);
        s = STR.BOLDITAL+"f"+STR.ENDBOLDITAL+" = "+STR.XHAT+"x"+STR.ENDXHAT;
        endingX = STR.displayString(s,g,18,262); // 247=vPos
        //endingX = STR.displayString(s1,g,20,247); // 247=vPos

        switch(state.currentFunction) {
        case Mod3State.polynomial:
            //endingX = STR.displayString("x ",g,112,262);
            s = STR.BOLD+"x"+STR.ENDBOLD;
            endingX = STR.displayString(s,g,97,262);
            //endingX = STR.displayString("+ ",g,159,262);
            s = STR.BOLD+"+ "+STR.ENDBOLD+STR.YHAT+"y"+STR.ENDYHAT;
            endingX = STR.displayString(s,g,130,262);
            //endingX = STR.displayString("y ",g,219,262);
            s = STR.BOLD+"y"+STR.ENDBOLD;
            endingX = STR.displayString(s,g,200,262);
            break;
        case Mod3State.exponential:
            //endingX = STR.displayString("e",g,112,262);
            s = STR.BOLD+"e"+STR.ENDBOLD;
            endingX = STR.displayString(s,g,97,262);
            String s2 = STR.BOLD_SUP+"x"+STR.ENDBOLD_SUP+" + "+
                STR.YHAT+"y"+STR.ENDYHAT;
            //endingX = STR.displayString(s2,g,156,262);
            endingX = STR.displayString(s2,g,130,262);
            //endingX = STR.displayString("e",g,229,262);
            s = STR.BOLD+"e"+STR.ENDBOLD;
            endingX = STR.displayString(s,g,208,262);
            String s3 = STR.BOLD_SUP+"y"+STR.ENDBOLD_SUP;
            //endingX = STR.displayString(s3,g,277,262);
            endingX = STR.displayString(s3,g,242,262);
            break;
        case Mod3State.sinusoidal:
            //endingX = STR.displayString("cos(",g,112,262);
            s = STR.BOLD+"cos("+STR.ENDBOLD;
            endingX = STR.displayString(s,g,96,262);
            //endingX = STR.displayString("x) + ",g,184,262);
            s = STR.BOLD+"x) + "+STR.ENDBOLD+STR.YHAT+"y"+STR.ENDYHAT;
            endingX = STR.displayString(s,g,165,262);
            //endingX = STR.displayString("sin(",g,262,262);
            s = STR.BOLD+"sin("+STR.ENDBOLD;
            endingX = STR.displayString(s,g,252,262);
            //endingX = STR.displayString("y)",g,332,262);
            s = STR.BOLD+"y)"+STR.ENDBOLD;
            endingX = STR.displayString(s,g,318,262);
        }
	sliderA.requestFocusInWindow();
	sliderB.requestFocusInWindow();
	if (sliderM != null) sliderM.requestFocusInWindow();
	if (sliderN != null) sliderN.requestFocusInWindow();
        sliderM_other.requestFocusInWindow();
	sliderN_other.requestFocusInWindow();
	sliderM_sin.requestFocusInWindow();
	sliderN_sin.requestFocusInWindow();
    }        
}
