import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

;
/**
 * MathProgram contains two panels, one for inputs, a second for results.
 */
public class MathProgram
{
    // declare all of the fields to be used in MathProgram
    private JFrame frame;
    private JPanel leftPanel,centerPanel,southPanel,rightPanel;
    private JButton resultButton;
    private JTextArea resultArea;
    private JTextField inputField1,inputField2,inputField3;
    private JList mathList;
    private JLabel label1,label2,label3;
    private JSlider slider1,slider2,slider3;
    private int sliderValue1,sliderValue2,sliderValue3;
    
    /**
     * Create a math program and show it on the screen.
     */
    public MathProgram()
    {
        makeFrame();
    }
    
    /**
     * Create the Swing frame and its content.
     */
    private void makeFrame()
    {
        frame = new JFrame("Math Program");
        makeMenuBar(frame);
        
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        

        leftPanel = new JPanel();
        leftPanel.setLayout(new GridLayout(5,1));
        centerPanel = new JPanel();
        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();
        centerPanel.setLayout(gridbag);
        southPanel = new JPanel();
        rightPanel = new JPanel();

        //LEFT Panel Contents
        inputField1 = new JTextField("Input 1",30);
        leftPanel.add(inputField1);
        
        inputField2 = new JTextField("Input 2",30);
        leftPanel.add(inputField2);
        
        inputField3 = new JTextField("Input 3",30);
        leftPanel.add(inputField3);
        
        
        resultButton = new JButton("compute");
        leftPanel.add(resultButton);
        
        
         resultButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { computeResults(); }
         });

         //CENTER Panel Contents
         // JList will let you choose the calculation that is
         // performed whent the calculate button is hit.
         // add the list of operations
         c.gridheight = 14;
         c.weighty = 1.0;
         String[] math = {"Add","Subtract","Multiply","Divide",
             "Mod","Integer Division","Ceil","Sqrt","Log","Sin",
             "Cos","Power","Circle Area","Triangle Area"};
         mathList = new JList(math);
         gridbag.setConstraints(mathList,c);
         centerPanel.add(mathList);
         
         // JRadioButtons perform the operation when they are selected.
         // add the radiobuttons to choose from
         JRadioButton addButton = new JRadioButton("Add");
         addButton.setSelected(true);
         JRadioButton subtractButton = new JRadioButton("Subtract");
         JRadioButton multiplyButton = new JRadioButton("Multiply");
         JRadioButton divideButton = new JRadioButton("Divide");
         JRadioButton modButton = new JRadioButton("Mod");
         JRadioButton integerDivisionButton = new JRadioButton("Integer Division");
         JRadioButton ceilButton = new JRadioButton("Ceil");
         JRadioButton sqrtButton = new JRadioButton("Sqrt");
         JRadioButton logButton = new JRadioButton("Log");
         JRadioButton sinButton = new JRadioButton("Sin");
         JRadioButton cosButton = new JRadioButton("Cos");
         JRadioButton powerButton = new JRadioButton("Power");
         JRadioButton circleAreaButton = new JRadioButton("Circle Area");
         JRadioButton triangleAreaButton = new JRadioButton("Triangle Area");
         
         // put the radio buttons into a group
         ButtonGroup group = new ButtonGroup();
         group.add(addButton);
         group.add(subtractButton);
         group.add(multiplyButton);
         group.add(divideButton);
         group.add(modButton);
         group.add(integerDivisionButton);
         group.add(ceilButton);
         group.add(sqrtButton);
         group.add(logButton);
         group.add(sinButton);
         group.add(cosButton);
         group.add(powerButton);
         group.add(circleAreaButton);
         group.add(triangleAreaButton);
         
         // add the radio buttons to the panel and make them operational
         c.gridheight = 1;
         c.gridwidth = GridBagConstraints.REMAINDER;
         gridbag.setConstraints(addButton,c);
         addButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { add(); }
         });
         centerPanel.add(addButton);
         gridbag.setConstraints(subtractButton,c);
         subtractButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { subtract(); }
         });
         centerPanel.add(subtractButton);
         gridbag.setConstraints(multiplyButton,c);
         multiplyButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { multiply(); }
         });
         centerPanel.add(multiplyButton);
         gridbag.setConstraints(divideButton,c);
         divideButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { divide(); }
         });
         centerPanel.add(divideButton);
         gridbag.setConstraints(modButton,c);
         modButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { mod(); }
         });
         centerPanel.add(modButton);
         gridbag.setConstraints(integerDivisionButton,c);
         integerDivisionButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) { integerDivision(); }
         });
         centerPanel.add(integerDivisionButton);
         gridbag.setConstraints(ceilButton,c);
         ceilButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { ceil(); }
         });
         centerPanel.add(ceilButton);
         gridbag.setConstraints(sqrtButton,c);
         sqrtButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { sqrt(); }
         });
         centerPanel.add(sqrtButton);
         gridbag.setConstraints(logButton,c);
         logButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { log(); }
         });
         centerPanel.add(logButton);
         gridbag.setConstraints(sinButton,c);
         sinButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { sin(); }
         });
         centerPanel.add(sinButton);
         gridbag.setConstraints(cosButton,c);
         cosButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { cos(); }
         });
         centerPanel.add(cosButton);
         gridbag.setConstraints(powerButton,c);
         powerButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { power(); }
         });
         centerPanel.add(powerButton);
         gridbag.setConstraints(circleAreaButton,c);
         circleAreaButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { circleArea(); }
         });
         centerPanel.add(circleAreaButton);
         gridbag.setConstraints(triangleAreaButton,c);
         triangleAreaButton.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { triangleArea(); }
         });
         centerPanel.add(triangleAreaButton);
         
         //SOUTH Panel Contents
         label1 = new JLabel("Input 1");
         southPanel.add(label1);
         slider1 = new JSlider(0,100,50);
         slider1.addChangeListener(new ChangeListener() {
             public void stateChanged(ChangeEvent e) {
                 inputField1.setText("" + slider1.getValue());
             }
         });
         southPanel.add(slider1);
         
         label2 = new JLabel("Input 2");
         southPanel.add(label2);
         slider2 = new JSlider(0,100,50);
         slider2.addChangeListener(new ChangeListener() {
             public void stateChanged(ChangeEvent e) {
                 inputField2.setText("" + slider2.getValue());
             }
         });
         southPanel.add(slider2);
         
         label3 = new JLabel("Input 3");
         southPanel.add(label3);
         slider3 = new JSlider(0,100,50);
         slider3.addChangeListener(new ChangeListener() {
             public void stateChanged(ChangeEvent e) {
                 inputField3.setText("" + slider3.getValue());
             }
         });
         southPanel.add(slider3);

         //RIGHT Panel Contents
         resultArea = new JTextArea("Result Area",20,20);
         rightPanel.add(resultArea);

         // add all of the panels to the contentPane
         contentPane.add(leftPanel,BorderLayout.WEST);
         contentPane.add(centerPanel,BorderLayout.CENTER);
         contentPane.add(southPanel,BorderLayout.SOUTH);
         contentPane.add(rightPanel,BorderLayout.EAST);
        
         // building is done - arrange the components and show        
         frame.setSize(800,450);
         frame.setVisible(true);
    
    }
    
    /**
     * Make the menubar for the frame.
     */
    public void makeMenuBar(JFrame frame)
    {
        JMenuBar menuBar = new JMenuBar();
        frame.setJMenuBar(menuBar);
        
        JMenu menu;
        JMenuItem item;
        
        // create the Math menu
        menu = new JMenu("Math");
        menuBar.add(menu);
        
        item = new JMenuItem("Add");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { add(); }
        });
        menu.add(item);
        
        item = new JMenuItem("Subtract");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { subtract(); }
         });
        menu.add(item);
        
        item = new JMenuItem("Multiply");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { multiply(); }
         });
        menu.add(item);
        
        item = new JMenuItem("Divide");
            item.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) { divide(); }
             });
        menu.add(item);
        
        item = new JMenuItem("Mod");
            item.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) { mod(); }
             });
        menu.add(item);
        
        item = new JMenuItem("Integer Division");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { integerDivision(); }
         });
        menu.add(item);

        // create the Functions menu
        menu = new JMenu("Functions");
        menuBar.add(menu);
        
        item = new JMenuItem("Ciel");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { ceil(); }
         });
        menu.add(item);
        
        item = new JMenuItem("Sqrt");
        item.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) { sqrt(); }
        });
        menu.add(item);
        
        item = new JMenuItem("Log");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { log(); }
         });
        menu.add(item);
        
        item = new JMenuItem("Sin");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { sin(); }
        });
        menu.add(item);
        
        item = new JMenuItem("Cos");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { cos(); }
         });
        menu.add(item);
        
        item = new JMenuItem("Power");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { power(); }
         });
        menu.add(item);
        
        item = new JMenuItem("Circle Area");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { circleArea(); }
         });
        menu.add(item);
        
        item = new JMenuItem("Triangle Area");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { triangleArea(); }
        });
        menu.add(item);
    }
    
    // ---- Menu Bar Functions ----
    
    // Math functions
    
    /**
     * Add function adds two numbers.
     */
    private void add()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        try {
            double x = Double.parseDouble(xString);
            double y = Double.parseDouble(yString);
            double z = x + y;
            String results = "\n    " + x + " + " + y + " = " + z;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("Number is not formatted properly.");
        }
    }
    
    /**
     * Subtract two numbers.
     */
    private void subtract()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        try {
            double x = Double.parseDouble(xString);
            double y = Double.parseDouble(yString);
            double z = x - y;
            String results = "\n    " + x + " - " + y + " = " + z;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("Number is not formatted properly.");
        }
    }
    
    /**
     * Multiply two numbers.
     */
    private void multiply()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        try {
            double x = Double.parseDouble(xString);
            double y = Double.parseDouble(yString);
            double z = x * y;
            String results = "\n    " + x + " * " + y + " = " + z;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("Number is not formatted properly.");
        }
    }
    
    /**
     * Divide two numbers.
     */
    private void divide()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        try {
            double x = Double.parseDouble(xString);
            double y = Double.parseDouble(yString);
            double z = x / y;
            String results = "\n    " + x + " / " + y + " = " + z;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("Number is not formatted properly.");
        }
    }
    
    /**
     * Apply the mod function to two numbers.
     */
    private void mod()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        try {
            int x = Integer.parseInt(xString);
            int y = Integer.parseInt(yString);
            int z = (int) ( x - Math.floor( x / y ) * y );
            String results = "\n    " + x + " mod " + y + " = " + z;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("Number is not formatted properly.");
        }
    }
    
    /**
     * Does integer division.
     */
    private void integerDivision()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        try {
            int x = Integer.parseInt(xString);
            int y = Integer.parseInt(yString);
            int z = (int)Math.floor( x / y );
            int r = (int)Math.round( x - Math.floor( x / y ) * y );
            String results = "\n    " + x + " / " + y + " = " + z + " r" + r;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("Number is not formatted properly.");
        }
    }
    
    // Function functions
    
    /**
     * Ciel applies the ceiling function
     */
    private void ceil()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        
        // find the ceiling of the first number
        try {
            double x = Double.parseDouble(xString);
            int ceil = (int)Math.ceil( x );
            String results = "\n    Ciel " + x + " = " + ceil;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
        
        // find the ceiling of the second number
        try {
            double y = Double.parseDouble(yString);
            int ceil = (int)Math.ceil( y );
            String results = "\n    Ciel " + y + " = " + ceil;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
    }
    
    /**
     * Sqrt applies the square root function.
     */
    private void sqrt()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        
        // take the square root of the first text field
        try {
            double x = Double.parseDouble(xString);
            double sqrt = Math.sqrt( x );
            String results = "\n    Sqrt " + x + " = " + sqrt;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
        
        // take the square root of the second text field
        try {
            double y = Double.parseDouble(yString);
            double sqrt = Math.sqrt( y );
            String results = "\n    Sqrt " + y + " = " + sqrt;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
    }
    
    /**
     * Log applies the logorithm function
     */
    private void log()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        
        // apply the function to the text fields.
        try {
            double x = Double.parseDouble(xString);
            double y = Double.parseDouble(yString);
            double log = Math.log( x ) / Math.log( y );
            String results = "\n    Log " + x + " (base " + y + ") = " + log;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
    }
    
    /**
     * Sin applies the sine wave function.
     */
    private void sin()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        
        // apply the function to the first text field.
        try {
            double x = Double.parseDouble(xString);
            double sin = Math.sin( Math.toRadians( x ));
            String results = "\n    Sin " + x + " = " + sin;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }

        // apply the function to the second text field.
        try {
            double y = Double.parseDouble(yString);
            double sin = Math.sin( Math.toRadians( y ));
            String results = "\n    Sin " + y + " = " + sin;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
    }
    
    /**
     * Cos applies the cosine wave function.
     */
    private void cos()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        
        // apply the function to the first text field.
        try {
            double x = Double.parseDouble(xString);
            double cos = Math.cos( Math.toRadians( x ));
            String results = "\n    Cos " + x + " = " + cos;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }

        // apply the function to the second text field.
        try {
            double y = Double.parseDouble(yString);
            double cos = Math.cos( Math.toRadians( y ));
            String results = "\n    Cos " + y + " = " + cos;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
    }
    
    /**
     * Power applies the power function.
     */
    private void power()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        
        // take the first value to the power of the second value
        try {
            double x = Double.parseDouble(xString);
            double y = Double.parseDouble(yString);
            double z = Math.pow( x , y );
            String results = "\n    " + x + " ^ " + y + " = " + z;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
    }
    
    /**
     * Circle Area calculates the area of a circle of a given radius.
     */
    private void circleArea()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        
        // apply the function to the first text field.
        try {
            double x = Double.parseDouble(xString);
            double circle = Math.PI * x * x;
            String results = "\n    pi * " + x + " ^ 2 = " + circle;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }

        // apply the function to the second text field.
        try {
            double y = Double.parseDouble(yString);
            double circle = Math.PI * y * y;
            String results = "\n    pi * " + y + " ^ 2 = " + circle;
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
    }
    
    /**
     * Calculate the area of a triangle given the length of its three sides.
     */
    private void triangleArea()
    {
        String xString = inputField1.getText();
        String yString = inputField2.getText();
        String zString = inputField3.getText();
        
        // find the area of a triangle with the three sides given.
        try {
            double x = Double.parseDouble(xString);
            double y = Double.parseDouble(yString);
            double z = Double.parseDouble(zString);
            legalTriangle( x, y, z );
            double s = ( x + y + z ) / 2;
            double triangle = Math.sqrt( s * ( s - x ) * ( s - y ) * ( s - z ));
            String results = "\nThe triangle is " + triangle + " units ^ 2";
            resultArea.append(results);
        }
        catch(NumberFormatException e) {
            resultArea.append("\nNumber is not formatted properly.");
        }
        catch(TriangleException e) {
            resultArea.append("\nNot a legal triangle in euclidea space.");
        }
    }
    
    /**
     * Checks to make sure the triangle is a legal triangle. If any one side 
     * is longer than the other two put together it throws a TriangleException.
     */
    public void legalTriangle(double x, double y, double z) throws TriangleException
    {
        if( x > y + z || y > x + z || z > x + y ) { 
            throw new TriangleException();
        }
    }            
    
    /**
     * Calculate the results of the computation. Result calculated is 
     * based on the item selected from the JList. If no item is selected 
     * a message is displayed in the results area.
     */
    private void computeResults()
    {
        int operation = mathList.getSelectedIndex();
        if(operation == 0) { add(); }
        else if(operation == 1) { subtract(); }
        else if(operation == 2) { multiply(); }
        else if(operation == 3) { divide(); }
        else if(operation == 4) { mod(); }
        else if(operation == 5) { integerDivision(); }
        else if(operation == 6) { ceil(); }
        else if(operation == 7) { sqrt(); }
        else if(operation == 8) { log(); }
        else if(operation == 9) { sin(); }
        else if(operation == 10) { cos(); }
        else if(operation == 11) { power(); }
        else if(operation == 12) { circleArea(); }
        else if(operation == 13) { triangleArea(); }
        else {
            resultArea.append("\nPlease select an operation from the list");
        }
    }
}
    
    
    


