package curve;

import java.awt.*;
import curve.*;

//Defines a parametric curve class
public class ParametricCurve extends Curve {

  private NumericTextField xText[],yText[],tText;
  private Coordinate aValue[];
  private double tValue;
  private Label equationLabel;
  private Checkbox tShiftCheckbox;
  
  //Set up button panel, initial variables ,etc
  public ParametricCurve(DrawCurve aDrawCurve) {
    int ctr;
    String s;
    Dimension d;
    
    color=Color.black;
    drawCurve=aDrawCurve;
    if(drawCurve!=null) drawCurve.addCurve(this);

    marker=new Coordinate[3];
    aValue=new Coordinate[3];
    
    GridBagLayout layout=new GridBagLayout();
    setBackground(Color.lightGray);
    setLayout(layout);
    GridBagConstraints constraints=new GridBagConstraints();

    //Set some defaults
    constraints.weightx=constraints.weighty=1.0;
    constraints.insets=new Insets(1,1,1,1);
    constraints.fill=GridBagConstraints.NONE;

    //Title row
    titleLabel=new Label("Quadratic Parametric Equation from 3 points");
    titleLabel.setFont(new Font("Dialog",Font.BOLD,12));
    constraints.gridwidth=GridBagConstraints.REMAINDER;
    layout.setConstraints(titleLabel,constraints);
    add(titleLabel);

    //Add listeners
    MyActionListener actionListener=new MyActionListener();
    
    //Numbers to substitute into equation
    xText=new NumericTextField[3];
    yText=new NumericTextField[3];

    for(ctr=0;ctr<3;ctr++) {
      s=new Integer(ctr).toString();
      xText[ctr]=addNewVariable(layout,"x"+s+"=",s,actionListener,true);
      yText[ctr]=addNewVariable(layout,"y"+s+"=",s,actionListener,true);
      switch(ctr) {
        case 0:
          //Add dummy variable
          addNewVariable(layout,"t0=","0",null,true).
            setEnabled(false);
          break;
        case 1:
          tText=addNewVariable(layout,"t1=","0.5",actionListener,true);
          break;
        case 2:
          //Add dummy variable
          addNewVariable(layout,"t2=","1",null,true).
            setEnabled(false);
          break;
      };
    };

    for(ctr=0;ctr<3;ctr++)
      marker[ctr]=new Coordinate(xText[ctr].asDouble(),yText[ctr].asDouble());

    //Get t value for point 1
    tValue=tText.asDouble();
    
    //t-shift checkbox
    tShiftCheckbox=new Checkbox("Mouse drags t-value");
    constraints.gridwidth=GridBagConstraints.REMAINDER;
    layout.setConstraints(tShiftCheckbox,constraints);
    add(tShiftCheckbox);
    
    
    //Equation display
    equationLabel=new Label("y=");
    constraints.gridwidth=GridBagConstraints.REMAINDER;
    layout.setConstraints(equationLabel,constraints);
    add(equationLabel);
    setEquation();
  };
  
  //Set up exercise; assume t1 is 0.5 (half way along curve)
  public void setExercise() {
    int ctr;
    for(ctr=0;ctr<3;ctr++) {
      marker[ctr].x=Math.random()*5;
      marker[ctr].y=Math.random()*5;
    };
  };    
  
  //Get maximum and minimum values of x,y on curve
  public DoubleRect getMinMax() {
    int ctr;
    double t;
    double yMin,yMax;
    Coordinate co;
    DoubleRect returnValue;
    
    //Get first values
    t=0;
    co=getValue(t);
    xMin=xMax=co.x;
    yMin=yMax=co.y;
    for(ctr=1;ctr<=100;ctr++) {
      t+=0.01;
      co=getValue(t);
      if(co.x>xMax) xMax=co.x;
      if(co.x<xMin) xMin=co.x;
      if(co.y>yMax) yMax=co.y;
      if(co.y<yMin) yMin=co.y;
    };
    returnValue=new DoubleRect(xMin,yMin,xMax-xMin,yMax-yMin);
    if(xMax-xMin<0.01) {
      returnValue.x-=0.01;
      returnValue.width+=0.02;
    };
    if(yMax-yMin<0.01) {
      returnValue.y-=0.01;
      returnValue.height+=0.02;
    };
    return returnValue;
  };

  protected void setEquation() {
    Point p;
    String s;
        
    aValue[0]=new Coordinate(marker[0]);
    aValue[2]=new Coordinate(marker[1]);
    aValue[2].sub(marker[0]);aValue[2].div(tValue);
    aValue[2].sub(marker[2]);aValue[2].add(marker[0]);
    aValue[2].div(tValue-1);
    aValue[1]=new Coordinate(marker[2]);aValue[1].sub(marker[0]);
    aValue[1].sub(aValue[2]);
    s="a2="+aValue[2];
    s+=", a1="+aValue[1];
    s+=", a0="+aValue[0];
    equationLabel.setText(s);
    equationLabel.setSize(300,20);
    p=equationLabel.getLocation();
    p.x=0;
    equationLabel.setLocation(p);
    equationLabel.setAlignment(Label.CENTER);    
  };
    
  //for param t 0 to 1, return x and y
  public Coordinate getValue(double t) {
    Coordinate co,co2;
    
    if(t<0) t=0;
    if(t>1) t=1;
    if(t<0.01) setEquation(); //Set up equation
    co=new Coordinate(aValue[2]);
    co.mul(t*t);
    co2=new Coordinate(aValue[1]);
    co2.mul(t);
    co.add(co2);
    co.add(aValue[0]);
    return co;
  };
  
  //fuction to draw markers and construction lines when called
  public void drawConstructs() {
    int ctr;
    if(drawCurve!=null) 
      for(ctr=0;ctr<3;ctr++)
        drawCurve.drawMarker(this,marker[ctr]);
  };

  //Override curve in order to return t-shift
  public int getMarker(double x,double y) {
    int ctr,returnValue;
    double closest,distance;
    returnValue=super.getMarker(x,y);

    if(returnValue==1) //Possible t-shift
      if(tShiftCheckbox.getState()) returnValue+=10;//if t-shift is down
    return returnValue; //Defaults to no marker found
  };  
  
  
  //fuction to set a marker, overrides Curve
  public void setMarker(int i,double x,double y) {
    double t,closest,distance;
    int ctr;
    Coordinate co;
    
    if(marker!=null) //array initialised
    if(i>=0 && i<marker.length) {
      marker[i].x=x;
      marker[i].y=y;
      xText[i].setText(new PrintableDouble(x).asStringSF(2));
      yText[i].setText(new PrintableDouble(y).asStringSF(2));
      setEquation();
    } else if(i==11) { //t-shift
      t=0.01;
      co=getValue(t);
      closest=(co.x-x)*(co.x-x)+(co.y-y)*(co.y-y);
      tValue=t;
      marker[1].x=co.x;
      marker[1].y=co.y;          
      for(ctr=2;ctr<=99;ctr++) { 
        t+=0.01;
        co=getValue(t);
        distance=(co.x-x)*(co.x-x)+(co.y-y)*(co.y-y);
        if(distance<closest) {
          closest=distance;
          tValue=t;
          marker[1].x=co.x;
          marker[1].y=co.y;
        };
      };
      xText[1].setText(new PrintableDouble(marker[1].x).asStringSF(2));
      yText[1].setText(new PrintableDouble(marker[1].y).asStringSF(2));      
      tText.setText(new PrintableDouble(tValue).asStringSF(2));      
//      setEquation();
    };
  };
  
  public void onActionPerformed(java.awt.event.ActionEvent event)
  {
    int ctr;
    for(ctr=0;ctr<3;ctr++)
      marker[ctr]=new Coordinate(xText[ctr].asDouble(),yText[ctr].asDouble());

    //Get t value for point 1
    tValue=tText.asDouble();
    setEquation();
    if(drawCurve!=null) drawCurve.repaint();
  }
  
};
