package curve;

import curve.*;
import java.awt.*;

//Class to derive quadratic curve from three points
public class QuadraticPointCurve extends Curve {

  private NumericTextField xText[],yText[];
  private double aVar,bVar,cVar;
  private Label equationLabel;

  //Set up curve options panel
  public QuadraticPointCurve(DrawCurve aDrawCurve) {
    int ctr;
    String s;

    color=Color.black;
    drawCurve=aDrawCurve;
    if(drawCurve!=null) drawCurve.addCurve(this);

    marker=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(5,5,5,5);
    constraints.fill=GridBagConstraints.NONE;

    //Title row
    titleLabel=new Label("Quadratic equation derived from 3 points");
    titleLabel.setFont(new Font("Dialog",Font.BOLD,12));
    constraints.gridwidth=GridBagConstraints.REMAINDER;
    layout.setConstraints(titleLabel,constraints);
    add(titleLabel);

    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,false);
      yText[ctr]=addNewVariable(layout,"y"+s+"=",s,actionListener,true);
    };

    for(ctr=0;ctr<3;ctr++)
    marker[ctr]=new Coordinate(xText[ctr].asDouble(),yText[ctr].asDouble());

    //Equation display
    equationLabel=new Label("y=");
    constraints.gridwidth=GridBagConstraints.REMAINDER;
    layout.setConstraints(equationLabel,constraints);
    add(equationLabel);
    setEquation();
  };

  //fuction to set a marker, overrides Curve
  public void setMarker(int i,double x,double y) {
    if(marker!=null) //array initialised
    if(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();
    };
  };

  private void setMinMaxX() {
    //get xmin,xmax min
    xMin=Math.min(Math.min(marker[0].x,marker[1].x),marker[2].x);
    xMax=Math.max(Math.max(marker[0].x,marker[1].x),marker[2].x);
  };

  public DoubleRect getMinMax() {
    DoubleRect r;
    double yMin,yMax;
    double yValue;
    double dCtr;
    int ctr;
    Coordinate p;

    //Gets min and max values of x
    setMinMaxX();

    //calculate all the points on y

    dCtr=0;
    yMin=yMax=getValue(dCtr).y;
    for(ctr=0;ctr<=100;ctr++) {
      yValue=getValue(dCtr).y;
      if(yValue<yMin) yMin=yValue;
      if(yValue>yMax) yMax=yValue;
      dCtr+=0.01;
    };
    if(xMin==xMax) {
      xMin-=1;
      xMax+=1;
    };
    if(yMin==yMax) {
      yMin-=1;
      yMax+=1;
    };
    r=new DoubleRect(xMin,yMin,xMax-xMin,yMax-yMin);
    return r;
  };

  //Sets up equation, and shows it in equation Label
  private void setEquation() {
    int ctr;
    String s,sSmall;
    Point p;

    setMinMaxX();

    //Check determinant isn't zero
    if( (marker[1].x*marker[1].x-marker[0].x*marker[0].x)*
    (marker[2].x-marker[0].x) - (marker[1].x-marker[0].x)*
    (marker[2].x*marker[2].x-marker[0].x*marker[0].x) ==0) {
      equationLabel.setText("Determinant is zero");
      return;
    };


    aVar= ( marker[0].x*(marker[1].y-marker[2].y)+
    marker[0].y*(marker[2].x-marker[1].x)+
    marker[1].x*marker[2].y-marker[2].x*marker[1].y ) /
    ((marker[1].x-marker[0].x)*(marker[2].x-marker[0].x)*
    (marker[2].x-marker[1].x));
    bVar=(marker[2].y-marker[0].y)/(marker[2].x-marker[0].x)-
    (marker[2].x+marker[0].x)*aVar;
    cVar=marker[0].y-aVar*marker[0].x*marker[0].x-bVar*marker[0].x;

    s="y=";

    //x Squareds
    sSmall=new PrintableDouble(aVar).asStringSF(2);
    if(sSmall!="0") s+=sSmall+"x^2";

    //x
    sSmall=new PrintableDouble(bVar).asStringSF(2);

    if(sSmall!="0") {
      if(sSmall.charAt(0)=='-') { //Negative
        s+=sSmall+"x"; //-ve sign included
      } else {
        if(s!="y=") s+="+";
        s+=sSmall+"x";
      };
    };

    //Units
    sSmall=new PrintableDouble(cVar).asStringSF(2);
    if(sSmall!="0") {
      if(sSmall.charAt(0)=='-') { //Negative
        s+=sSmall; //-ve sign included
      } else {
        if(s!="y=") s+="+";
        s+=sSmall;
      };
    } else {
      if(s=="y=") s+="0";
    };

    equationLabel.setText(s);
    equationLabel.setSize(300,20);
    p=equationLabel.getLocation();
    p.x=0;
    equationLabel.setLocation(p);
    equationLabel.setAlignment(Label.CENTER);
  };

  //t is always between 0 and 1
  public Coordinate getValue(double t) {
    double x,y,xPow;
    Coordinate p;

    if(t<0.001) { //First call, set min max values
      setMinMaxX();
    };
    if(t<0) x=xMin;
    else if(t>1) x=xMax;
    else x=t*(xMax-xMin)+xMin;

    //Calculate y
    y=0;
    y+=cVar;
    xPow=x;
    y+=bVar*xPow;
    xPow*=x; //x^2
    y+=aVar*xPow;

    p=new Coordinate(x,y);
    return p;
  };

  public void drawConstructs() {
    int ctr;
    if(drawCurve!=null) 
      for(ctr=0;ctr<3;ctr++)
        drawCurve.drawMarker(this,marker[ctr]);
  };

  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());
    setEquation();
    if(drawCurve!=null) drawCurve.repaint();
  }

};