package DDrawing;


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;


/**
 * DAequiDistPoints represents a special kind of <code>DPointSet</code> with constant x-distance between the points
 */
public class DAequiDistPoints extends DComponent{
  protected double minX;
  protected double distance;
  protected double[] y;
  protected int size = 0;
  protected boolean connected = false;

  /**
   * minX is the start-x-value for the set,
   * distance the constant x-distance
   */
  public DAequiDistPoints( double minX, double distance ){
    this( minX, distance, 10 );
  }

  /**
   * minX is the start-x-value for the set,
   * distance the constant x-distance,
   * initial-capacity of the array
   */
  public DAequiDistPoints( double minX, double distance, int initial_capacity ){
    this.minX = minX;
    this.distance = distance;
    y = new double[ initial_capacity ];
  }

  /**
   * paints the points in the <code>DContainer</code>
   *
   * @param m <code>DMeasures</code> contains information about the current size
   *          of the parent
   */
  public void paint( DMeasures m ){
    Graphics g = m.getGraphics();
    Color old_color = g.getColor();
    if( color != null ) g.setColor( color );
    else g.setColor( DEFAULT_COLOR );
    if( connected && size > 1 ){
      Point p1, p2;
      p1 = m.getPoint( x(0), y[0] );
      for( int i=1; i<size; i++ ){
        p2 = m.getPoint( x(i), y[i] );
        g.drawLine( p1.x, p1.y, p2.x, p2.y );
        p1 = p2;
      }
    }
    else{
      Point p;
      for( int i=0; i<size; i++ ){
        p = m.getPoint( x(i), y[i] );
        g.drawLine(p.x, p.y, p.x, p.y );
      }
    }
    g.setColor( old_color );
  }

  /**
   * adds a new y-value to the existing, calls the parent to repaint
   *
   * @param y a new y-value which should be painted
   */
  public void addValue( double y ){
    if( ++size > this.y.length ){
      int oldL = this.y.length;
      double[] newV = new double[ oldL * 2 ];
      System.arraycopy( this.y, 0, newV, 0, oldL );
      this.y = newV;
    }

    this.y[ size - 1 ] = y;

    if( size == 1 ) rectangle = new DRectangle( minX, y, 0, 0 );
    else rectangle.insert( new DPoint( minX + (size-1) * distance, y ) );

    repaint();
  }

  /**
   * adds a few values to the existing, calls the parent to repaint
   *
   * @param newy new y-values
   */
  public void addValues( double[] newy ){
    if( newy.length == 0 ) return;

    double min = newy[0], max = newy[0];
    for( int i=0; i<newy.length; i++ )
      if( newy[i] < min ) min = newy[i];
      else if( newy[i] > max ) max = newy[i];

    if( size + newy.length > y.length ){
      double[] newV = new double[ size + newy.length ];
      System.arraycopy( y, 0, newV, 0, size );
      y = newV;
    }

    System.arraycopy( newy, 0, y, size, newy.length );

    if( size == 0 ) rectangle = new DRectangle( minX, min, (newy.length-1) * distance, max - min );
    else {
      rectangle.insert( new DPoint( minX, min ) );
      rectangle.insert( new DPoint( minX + (size+newy.length-1) * distance, max ) );
    }

    size += newy.length;

    repaint();
  }

  /**
   * sets the points connected or disconnected, means that either there is a
   * line drawn between them or not
   *
   * @param aFlag if the points are connected by lines
   */
  public void setConnected( boolean aFlag ){
    boolean changed = !( aFlag == connected );
    connected = aFlag;
    if( changed ) repaint();
  }

  /**
   * removes all points of the array
   */
  public void removeAllPoints(){
    size = 0;
    repaint();
    rectangle = DRectangle.getEmpty();
  }

  /**
   * returns the current number of points
   *
   * @return the number of points
   */
  public int size(){ return size; }

  public DPoint getDPoint( int no ){
    if( no >= size ) return null;
    return new DPoint( x(no), y[no] );
  }

  protected double x( int i ){ return minX + distance * i; }
}
