import java.applet.Applet;

import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Label;
import java.awt.Choice;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.TextArea;

import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;

/*
 * Applet which implements the Function evaluator excercise.
 */

public class FunctionEvaluator extends Applet implements KeyListener{
  /*
   * The init method builds the user interface. It is also responsible
   * for initializing the event handling.
   */


  // GUI elements

  Choice function_menu = new Choice();
  TextField x_value_prompt = new TextField(8);
  TextField arb_func = new TextField(50);
  TextArea result_area = new TextArea("", 4, 30, TextArea.SCROLLBARS_VERTICAL_ONLY);

  public void init(){
    // BorderLayout is a good choice of LayoutManager for this
    // applet. We use the CENTER to hold the TextArea, and the
    // the NORTH panel to hold the other components, usin
    // GridBagLayout.

    GridBagLayout g = new GridBagLayout();
    GridBagConstraints c = new GridBagConstraints();

    setLayout(new BorderLayout());

    // We put all the components that we want at BorderLayout.NORTH
    // on common panel so that they get positioned properly.
    // This panel uses a GridBagLayout (since it has several
    // logically different components).

    Panel north = new Panel();
    add(north, BorderLayout.NORTH);

    north.setLayout(g);

    // The north panel should start with a message to the user.
    Label l = new Label("Choose function: ");
    c.gridx = 0; c.gridy = 0; c.anchor = GridBagConstraints.EAST;
    g.setConstraints(l, c);
    north.add(l);

    // Build the function menu and add it to the north panel.
    function_menu.add("Arbitrary function");
    function_menu.add("sin");
    function_menu.add("cos");
    function_menu.add("tan");
    function_menu.add("atn");
    function_menu.add("exp");
    function_menu.add("log");
    function_menu.add("sqrt");
    function_menu.add("abs");

    c.gridx = 1; c.gridy = 0; c.anchor = GridBagConstraints.WEST;
    g.setConstraints(function_menu, c);
    north.add(function_menu);

    // Add the label "x=" to the north panel
    // Add the text field where the user enters the x-value.
    // Also activate key events from this text fielf.
    l = new Label("   x=");
    c.gridx = 0; c.gridy = 1; c.anchor = GridBagConstraints.EAST;
    g.setConstraints(l, c);
    north.add(l);

    c.gridx = 1; c.gridy = 1; c.anchor = GridBagConstraints.WEST;
    g.setConstraints(x_value_prompt, c);
    north.add(x_value_prompt);
    x_value_prompt.addKeyListener(this);
    

    //Add the field for arbitraty function evaluation with a proper
    //label.
    l = new Label("Arbitrary function: ");
    c.gridx = 0; c.gridy = 2; c.anchor = GridBagConstraints.EAST;
    g.setConstraints(l, c);
    north.add(l);

    c.gridx = 1; c.gridy = 2; c.anchor = GridBagConstraints.WEST;
    g.setConstraints(arb_func, c);
    north.add(arb_func);
    arb_func.addKeyListener(this);

    // Add the text area to the center panel. We also turn off
    // editing so that the user can read from, but not write to the area.
    result_area.setEditable(false);
    add(result_area, BorderLayout.CENTER);

  } //init

  public void keyPressed(KeyEvent event) {}
  public void keyTyped(KeyEvent event) {}

  public void keyReleased(KeyEvent event){
    // Check that the key-press came from the x_value_prompt,
    // and that the user pressed the enter key. Then get the value
    // and evaluate the function.

    if((event.getKeyCode() == KeyEvent.VK_ENTER) && ((event.getSource() == x_value_prompt) || (event.getSource() == arb_func))){
      
      //Initialize
      double x = 0, y = 0;
      
      // Get x value from the prompt
      try{
	x = Double.valueOf(x_value_prompt.getText()).doubleValue();
      }catch(Exception e){};
	
      // Get function type and Compute y=F(x)
      switch(function_menu.getSelectedIndex()){
        case 0:  //arbitraty function
	  try{
	    y = Interpreter.interpret(arb_func.getText(), x);
	  }
	  catch(InterpreterException e){
	    result_area.append(e.getMessage() + "\n");
	    return;
	  }
	  catch(Exception e){
	    result_area.append(e + "\n");
	    return;
	  }
	  break;
	  
        case 1:
	  y = Math.sin(x); break;
        case 2:
	  y = Math.cos(x); break;
        case 3:
	  y = Math.tan(x); break;
        case 4:
	  y = Math.atan(x); break;
        case 5:
	  y = Math.exp(x); break;
        case 6:
	  y = Math.log(x); break;
        case 7:
	  y = Math.sqrt(x); break;
        case 8:
	  y = Math.abs(x); break;
      }
      
      // Write reslt to text area.
      result_area.append(function_menu.getSelectedIndex() != 0 ? (function_menu.getSelectedItem() + "(" + x + ") = " + y + "\n") : (arb_func.getText() + ", (x := " + x +  ") = " +  y + "\n"));
    } //if
  } //keyReleased
  
} //class FunctionEvaluator
