// (c) MIT 2003.  All rights reserved.

package rec.fun;

import java.awt.*;
import rec.util.*;
import rec.geo.*;
import rec.sys.*;
import rec.core.widgets.*;

public class Grid extends VisibleWidget implements Registerable
{
  int grid_size = 4;

  int x;
  int y;
  int h;
  int w;

  boolean[][] hit;

  Squiggle target;

  Surface surf = null;


  public Grid( Surface surf, Squiggle targ )
  {
    this( surf, 4, targ );
  }
  
  public Grid( Surface surf, int grid_s, Squiggle targ )
  {
    this.grid_size = grid_s;

    this.surf = surf;

    target = targ;

    surf.register( this, targ );

    setBounds();
  }

  void setBounds()
  {
    Rectangle r = target.getBounds();
    
    x = r.x;
    y = r.y;
    h = r.height;
    w = r.width;

    hit = new boolean[grid_size][grid_size];
    //    for ( int i = 0; i < grid_size; i++ )
    //      hit[i] = new boolean[grid_size];

    //    surf.shuffleToTop( target );

    int s = target.getNumberOfPoints();

    for ( int i = 0; i < s; i++ )
      {
	GPoint p = target.getPointAt( i );

	int tx = (int)( ( p.x - x ) * grid_size ) / w;
	int ty = (int)( ( p.y - y ) * grid_size ) / h;
	addHit( tx, ty );
      }
  }


  protected void addHit( int tx, int ty )
  {
    hit[ tx ][ ty ] = true;
  }

  boolean hitAt( int x, int y )
  {
    return hit[x - 1][y - 1];
  }

  boolean missAt( int x, int y )
  {
    return !hitAt( x, y );
  }

  public double density( )
  {
    int tot = 0;
    for (int i = 0; i < hit.length; i++ )
      for ( int j = 0; j < hit[i].length; j++ )
	if ( hit[i][j] ) 
	  tot++;

    return (float)tot / (hit.length * hit[0].length);
  }

  public void draw( Graphics g )
  {
    Stroke os = ((Graphics2D)g).getStroke();
    ((Graphics2D)g).setStroke( new BasicStroke( 1 ) );

    Color oc = g.getColor();

    if ( getColor() != null )
      g.setColor( getColor().brighter().brighter() );
    else
      g.setColor( Colors.SELECTED.brighter().brighter() );

    double dx = w / grid_size;
    double dy = h / grid_size;
    int idx = (int)dx;
    int idy = (int)dy;

    for ( int i = 0; i < grid_size; i++ )
      for ( int j = 0; j < grid_size; j++ )
	{
	  if ( hit[i][j] )
	    {
	      g.fillRect( (int)( x + i * dx),
			  (int)(y + j * dy),
			  idx, idy );
	    }
	}

    g.setColor( Colors.STROKE );

    // to comp for pen width
    //    x -= 2;
    //    y -= 2;

    for ( int i = 0; i < grid_size + 1; i++ )
      {
	g.drawLine( (int)(x + dx * i), y,
		    (int)(x + dx * i), y + h );

	g.drawLine( x,          (int)(y + dy * i),
		    x + w,      (int)(y + dy * i ) );
      }

    ((Graphics2D)g).setStroke( os );
    g.setColor( oc );
  }



  public Object clone()
  {
    Grid e = new Grid( surf, target );

    return e;
  }



  // the register stuff
  public void removed( Widget w )
  {
    surf.removeWidget( this );
  }


  /**
   * Called when ow is replaced by nw.
   */
  public void replaced( Widget ow, Widget nw )
  {
    if ( nw instanceof Squiggle )
      {
	target = (Squiggle)nw;
	setBounds();
      }
    else
      {
	surf.unregister( this, nw );
	surf.removeWidget( this );
      }
  }

  /***
   * Called when w has been altered.
   *
   * @param w  The Widget after it has been altered.
   * @param t  The Transition that affected that Widget.
   */
  public void altered( Widget w, Transition t )
  {
    setBounds();
  }
  



  public boolean includes( GPoint p, double offset )
  {
    return false;
  }

  public boolean contains( GPoint p )
  {
    return false;
  }

  public void move( GPoint p )
  {
    //Console.writeln( "Moving by " + p );
  }

  public void rotate( GPoint p, double angle )
  {
    Assert.note( "rotate in rec.fsm.Grid Not implemented" );
  }

  public double size() 
  {
    return target.size();
  }

  public void resize( double d )
  {
    Assert.note( "resize in rec.fsm.Grid Not implemented" );
  }


  public Location getLocation()
  {
    return( new Location( target.getBounds() ) );
  }

  public Rectangle getBounds()
  {
    return( target.getBounds() );
  }

}
