
import java.applet.*;
import java.awt.*;
import java.util.*;

public class NMApplet
  extends Applet
{
  private TabPan tPan;
  private Panel pUI;
  private Panel pSpec;
  private Panel pFunc;
  private Label lFunc;
  private TextField tfFunc;
  private Panel pXY;
  private Label lX1;
  private TextField tfX1;
  private Label lX2;
  private TextField tfX2;
  private Panel pH;
  private Label lH;
  private TextField tfH;

  private Panel pOper;
  private Panel pView;
  private Panel cmdPan;
  private Button b1;
  private Button b10;
  private Button b100;
  private Button bAnim;
  private Button bStop;
  private Panel pRight;
  
  private SimplexCanvas sCanv;
  private Panel pMsg;
  private Label lMsg;
  private TextArea taMsg;

  private Canvas cPlane;
  private TextField tfValue;

  private NelderMeadMinimizer nmz;

  public NMApplet()
  {
    pFunc = new Panel();
    pFunc.setLayout( new FlowLayout( FlowLayout.LEFT ) );
    lFunc = new Label( "f(x1,x2)=" );
    tfFunc = new TextField( "100*(x2-x1*x1)^2 + (1-x1)^2", 40 );
    pFunc.add( lFunc );
    pFunc.add( tfFunc );
    pXY = new Panel();
    pXY.setLayout( new FlowLayout( FlowLayout.LEFT ) );
    lX1 = new Label( "Start x1" );
    tfX1 = new TextField( "-1.2", 10 );
    lX2 = new Label( "Start x2" );
    tfX2 = new TextField( "1", 10 );
    pXY.add( lX1 );
    pXY.add( tfX1 );
    pXY.add( lX2 );
    pXY.add( tfX2 );
    pH = new Panel();
    pH.setLayout( new FlowLayout( FlowLayout.LEFT ) );
    lH = new Label( "Simplex Edge" );
    tfH = new TextField( "0.5", 10 );
    pH.add( lH );
    pH.add( tfH );

    cPlane = new Canvas();

    pUI = new Panel();
    pUI.setLayout( new BorderLayout() );
    pSpec = new Panel();
    pSpec.setLayout( new BorderLayout() );
    pSpec.add( "North", pFunc );
    pSpec.add( "Center", pXY );
    pSpec.add( "South", pH );
    pUI.add( "North", pSpec );

    pOper = new Panel();
    pOper.setLayout( new BorderLayout() );
    cmdPan = new Panel();
    b1 = new Button( "1 Step" );
    b10 = new Button( "10 Steps" );
    // b100 = new Button( "100 Steps" );
    bAnim = new Button( "Animate" );
    bAnim.disable();
    bStop = new Button( "Stop" );
    bStop.disable();
    cmdPan.add( b1 );
    cmdPan.add( b10 );
    // cmdPan.add( b100 );
    cmdPan.add( bAnim );
    cmdPan.add( bStop );
    sCanv = new SimplexCanvas();
    tfValue = new TextField( 40 );
    pView = new Panel();
    pView.setLayout( new BorderLayout() );
    pView.add( "North", cmdPan );
    pView.add( "Center", sCanv );
    pView.add( "South", tfValue );
    pOper.add( "Center", pView );
    pMsg = new Panel();
    pMsg.setLayout( new BorderLayout() );
    lMsg = new Label( "Details:" );
    taMsg = new TextArea( 20, 40 );
    pMsg.add( "North", lMsg );
    pMsg.add( "Center", taMsg );
    pOper.add( "East", pMsg );

    tPan = new TabPan();
    tPan.addT( "Specification", pUI );
    tPan.addT( "Operation", pOper );

    setLayout( new BorderLayout() );
    add( "Center", tPan );
  }

  public void showResult( Vertex v )
  {
    double val;

    tfValue.setText(
      "f( " + v.coord[0] + ", " + v.coord[1]  + " ) = "  + v.val );
  }

  public void showNMState()
  {
    int i;
    for( i = 0; i <= nmz.dim; i++ )
      taMsg.appendText(
        "f" + nmz.V[i].toString() + "=" + nmz.V[i].val + "\n" );
    taMsg.appendText(
      "Longest Simplex Edge=" + nmz.getLongestEdge() + "\n\n" );
  }

  public void oneStep()
  {
    String oper = nmz.next();

    taMsg.appendText( nmz.nIter + ": " + oper + "\n" );
    nmz.order();
    showNMState();
  }

  public boolean handleEvent( Event evt )
  {
    int i;
    if( evt.id == Event.ACTION_EVENT ) {
      if( evt.target == tPan ) {
        // System.out.println( evt.arg );
        Integer I = (Integer) evt.arg;
        // I = new Integer( 1 );
        if( tPan.getSelectedIndex() == 1 ) {
          taMsg.setText("START:\n");
          nmz = new NelderMeadMinimizer( 2 );
          nmz.init( tfFunc.getText() );
          double h;
          Double D;
          Vertex V0 = new Vertex( 2 );
          D = new Double( tfX1.getText() ); 
          V0.coord[0] = D.doubleValue();
          D = new Double( tfX2.getText() ); 
          V0.coord[1] = D.doubleValue();
          D = new Double( tfH.getText() ); 
          h = D.doubleValue();
          nmz.start( V0, h );
          nmz.order();
          sCanv.setVertices( nmz.V );
          sCanv.repaint();
          showNMState();
        }
      }
      if( evt.target == b1 ) {
        oneStep();
        sCanv.repaint();
      }
      if( evt.target == b10 ) {
        for( i = 0; i < 10; i++ )
          oneStep();
        sCanv.repaint();
      }
      if( evt.target == sCanv ) {
        Vertex vMouse = sCanv.getMouseVertex();
        nmz.eval( vMouse );
        showResult( vMouse );
      }
    }
    if( evt.id == Event.MOUSE_MOVE ) {
    }
    return super.handleEvent( evt );
  }

  public void init() {
  }
}
