import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.text.DecimalFormat;


/*
 * Created on Jan 26, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */

/**
 * @author User
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class HW8_Q2_GUI extends JFrame {
    
    // Default values provided in the problem statement
    double s = 0.0002;
    double n = 0.03;
    double w = 20.0;
    double Q = 5.0;
    double eps = 1.0e-10;
    
    double d = 0.0;
    double v = 0.0;
    int numIters = 0;
    double err = 0.0;
    
    JTextField sText = new JTextField(String.valueOf(s));
    JTextField nText = new JTextField(String.valueOf(n));
    JTextField wText = new JTextField(String.valueOf(w));
    JTextField qText = new JTextField(String.valueOf(Q));
    JTextField eText = new JTextField(String.valueOf(eps));
    JComboBox  rPane = new JComboBox();
    
    JButton CalculateButton = new JButton("Calculate");
    JButton CancelButton = new JButton("Cancel");
    
    JTextField dText = new JTextField(String.valueOf(d));
    JTextField vText = new JTextField(String.valueOf(v));
    JTextField iText = new JTextField(String.valueOf(numIters));
    JTextField erText = new JTextField(String.valueOf(err));
    
    ChannelPanel mChannelPanel = new ChannelPanel();
    
    public HW8_Q2_GUI()
    {
        InitializeVariables();
        
        // Rest of the constructor builds the GUI
        getContentPane().setLayout(new BorderLayout());
        CreateLeftPanel();
        CreateActionListeners();
        mChannelPanel.ratio = 0.0;
        getContentPane().add(mChannelPanel,"Center");
        
    }
    
    // Resets the values of the input and output parameters
    private void InitializeVariables()
    {
        s = 0.0002;
        n = 0.03;
        w = 20.0;
        Q = 5.0;
        eps = 1.0e-10;
        
        d = 0.0;
        v = 0.0;
        numIters = 0;
        err = 0.0;
        
        sText.setText(String.valueOf(s));
        nText.setText(String.valueOf(n));
        wText.setText(String.valueOf(w));
        qText.setText(String.valueOf(Q));
        dText.setText(String.valueOf(d));
        vText.setText(String.valueOf(v));
        nText.setText(String.valueOf(n));
        erText.setText(String.valueOf(err));
    }
      
    private void CreateLeftPanel()
    {
        JPanel InputPanel = new JPanel();
        InputPanel.setLayout(new GridLayout(6,2,10,5));
               
      
        rPane.addItem("Bisection");
        rPane.addItem("Newton-Raphson");
        
        InputPanel.add(new JLabel("Slope"));InputPanel.add(sText);
        InputPanel.add(new JLabel("Roughness"));InputPanel.add(nText);
        InputPanel.add(new JLabel("Flow Rate"));InputPanel.add(wText);
        InputPanel.add(new JLabel("Width"));InputPanel.add(qText);
        InputPanel.add(new JLabel("Tolerance"));InputPanel.add(eText);
        InputPanel.add(new JLabel("Solver"));InputPanel.add(rPane);
           
        
        JPanel ButtonPanel = new JPanel();
        ButtonPanel.setLayout(new GridLayout(1,2,10,5));
        ButtonPanel.add(CalculateButton);
        ButtonPanel.add(CancelButton);
        
        JPanel OutputPanel = new JPanel();
        
        OutputPanel.setLayout(new GridLayout(4,2,10,5));
        dText.setEditable(false);
        vText.setEditable(false);
        iText.setEditable(false);
        erText.setEditable(false);
        
        OutputPanel.add(new JLabel("Depth"));OutputPanel.add(dText);
        OutputPanel.add(new JLabel("Velocity"));OutputPanel.add(vText);
        OutputPanel.add(new JLabel("Iterations"));OutputPanel.add(iText);
        OutputPanel.add(new JLabel("Solver Error"));OutputPanel.add(erText);
        
        JPanel BigInputPanel = new JPanel();
        BigInputPanel.setLayout(new BoxLayout(BigInputPanel, BoxLayout.Y_AXIS));
        BigInputPanel.add(InputPanel);
        BigInputPanel.add(Box.createRigidArea(new Dimension(10,10)));
        BigInputPanel.add(ButtonPanel);
        BigInputPanel.add(Box.createRigidArea(new Dimension(10,10)));
        BigInputPanel.add(new JSeparator());
        BigInputPanel.add(Box.createRigidArea(new Dimension(10,10)));
        BigInputPanel.add(OutputPanel);
        
        getContentPane().add(BigInputPanel,"East");
    }
    
    private void CreateActionListeners()
    {
        // Do the easy one first
        CancelButton.addActionListener(new ActionListener()
                {
            		public void actionPerformed(ActionEvent e)
            		{
            		    InitializeVariables();
            		    repaint();
            		}
                }
                );
        
        // Now handle the tough part
        CalculateButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e)
            {
                try{
                    s = Double.parseDouble(sText.getText());
                    n = Double.parseDouble(nText.getText());
                    w = Double.parseDouble(wText.getText());
                    Q = Double.parseDouble(qText.getText());
                    eps = Double.parseDouble(eText.getText());
                    
                    if(s < 0.0 || n < 0.0 || w < 0.0 || Q < 0.0 || eps < 0.0)
                        throw new NumberFormatException("Only positive values for the input are allowed.");
                    
                    FlowFunction mFlowFunction = new FlowFunction(s,n,w,Q);
                    if(((String)(rPane.getSelectedItem())).equals("Bisection")){
                        d = RootFinder.rtbis(mFlowFunction, 0.0, w, eps);
                        numIters = RootFinder.j;
                    }else {
                        d = Newton.newt(mFlowFunction, 0.0, w, eps);
                        numIters = Newton.j;
                    }
                    err = mFlowFunction.f(d);
                    v = mFlowFunction.velocity(d);
                    
                    DecimalFormat df = new DecimalFormat("###.##########");
                    dText.setText(String.valueOf(df.format(d)));
                    vText.setText(String.valueOf(df.format(v)));
                    iText.setText(String.valueOf(numIters));
                    erText.setText(String.valueOf(df.format(err)));
                    mChannelPanel.ratio = d/w;
                    repaint();
                    
                    // Ouput the results to the command line
                    System.out.println("Solver    : "+rPane.getSelectedItem());
                    System.out.println("Depth     : "+d);
                    System.out.println("Velocity  : "+v);
                    System.out.println("Iterations: "+numIters);
                    System.out.println("Error     : "+err);
                    
                }catch(NumberFormatException ex1){
                    JOptionPane.showMessageDialog(null,"Invalid input:"+ex1.getMessage(),"Error",JOptionPane.ERROR_MESSAGE);
                }
            }
        });
    }
    
    public static void main(String[] args) 
    { 
     
        HW8_Q2_GUI mSolution = new HW8_Q2_GUI();
        mSolution.setTitle("Flow Solver");
        mSolution.setPreferredSize(new Dimension(650,370));
           
        mSolution.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e)
            {
                System.exit(0);
            }
        });
        mSolution.pack();
        mSolution.setVisible(true);
  
    }
}
