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

package rec.fun;

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

public class TextBox extends VisibleWidget
{
  int x;
  int y;
  int h;
  int w;
  boolean set = false;
  Image buff;

  String txt;

  Surface surf = null;

  public TextBox( Surface surf, VisibleWidget targ )
  {
    this.surf = surf;

    Rectangle r = targ.getBounds();
    
    x = r.x;
    y = r.y;
    h = r.height;
    w = r.width;

    loadText( "empty.txt" );
  }


  public TextBox( Surface surf, int x, int y, int w, int h )
  {
    this.surf = surf;

    this.x = x;
    this.y = y;
    this.h = h;
    this.w = w;

    loadText( "empty.txt" );
  }


  public void setText( String txt )
  {
    this.txt = txt;
    set = false;
    buff = null;
  }


  /**
   * Load the text in the file of the given name.  Looks in Classpath
   * for these files.
   */
  public void loadText( String filename )
  {
    txt = "";
    String nextLine = null;
    try {
      BufferedReader rd = RecIniFile.grabStream( filename );

      while( (nextLine = rd.readLine()) != null )
	txt += nextLine + "\n";
    }
    catch ( Exception e )
      {
	e.printStackTrace();
      }

    set = false;
    buff = null;
  }


  public void draw( Graphics graph )
  {
    Graphics2D g = (Graphics2D)graph;

    Font of = g.getFont();
    Stroke ostk = g.getStroke();
    Color ooc = g.getColor();

    // calc and make buff
    intdraw( g, true );

    /*
    Graphics2D gg = (Graphics2D)buff.getGraphics();
    gg.setStroke( new BasicStroke( 4 ) );
    Color tc = Colors.getBackground();
    tc = new Color( tc.getRed(), tc.getGreen(), tc.getBlue(), 150 );
    gg.setBackground( tc );
    intdraw( gg, false );
    gg.dispose();
    */

    // draw the faded rectangle
    // faded rectangle
    Color tc = Colors.getBackground();
    tc = new Color( tc.getRed(), tc.getGreen(), tc.getBlue(), 190 );
    g.setColor( tc );
    g.fillRect( x - 5, y - 5, w + 19, h + 19 );

    // draw us out.
    //    g.drawImage( buff, x, y, tc, null );
    g.setFont( of );
    g.setStroke( ostk );
    g.setColor( ooc );

    intdraw( g, false );

    g.setFont( of );
    g.setStroke( ostk );
    g.setColor( ooc );
  }

  /**
   * Assume upper left is 0,0 (since we will be drawing into buffer)
   *
   * draws a box, text inside box:
   *   ---
   *   10 pix
   *   top of text
   *   10 pix
   *   ---
   *   10 pix
   *   ---
   */
  protected void intdraw( Graphics g, boolean draw_fade )
  {
    //    int y = 10;
    //    int x = 10;

    if ( draw_fade && set )
      return;

    //    Console.writeln( "Drawing text box" );

    //    Stroke bk_st = g.getStroke();
    Color lcolor = g.getColor();

    int dx, dy;

    String nn = txt.toString();

    Font f = g.getFont();
    AffineTransform af = AffineTransform.getScaleInstance(1.4, 1.2);    
    f = f.deriveFont( Font.BOLD, af );

    Font of = f;
    g.setFont( f );
    FontMetrics fms = g.getFontMetrics();

    g.setColor( Colors.getColor( "text" ) );

    int curx, cury;
    int maxx, maxy;

    cury = y + fms.getAscent();
    maxx = -1;
    maxy = -1;
    boolean done = false;
    StringTokenizer st = new StringTokenizer( nn, "\n ", true );
    
    while( !done && ( cury < (y + h) ) )
      {
	String ln = "";

	boolean spacy = false;
	boolean done2 = false;
	int ddx = -1;
	while( !done2 && ( ddx < w ) )
	  {
	    // new line
	    if ( !st.hasMoreTokens() )
	      done2 = true;
	    else
	      {
		String tl = st.nextToken();
		if ( tl.equals( "\n" ) )
		  {
		    done2 = true;
		  }
		else if ( tl.equals( "\t" ) )
		  ln += "     ";
		else if ( tl.equals( " " ) )
		  {
		    if ( !spacy && ln.equals("") )
		      spacy = true;
		    else 
		      {
			if ( ln.equals( "" ) )
			  ln += "  "; // 2 spaces to make up for lost time
			else
			  ln += " "; //single space.
		      }
		  }
		else
		  ln += tl;
	      }

	    Rectangle2D r2d = fms.getStringBounds( ln, g );

	    // width of the writing
	    ddx = (int) r2d.getWidth();
	  }
	
	if ( ddx > maxx )
	  maxx = ddx;

	//	Console.writeln( "Writing \"" + ln + "\". = " + ddx );
	if ( !draw_fade )
	  g.drawString( ln, x, cury );

	cury += fms.getHeight();

	maxy = cury;

	done = !st.hasMoreTokens();
      }
    
    maxy -= y + fms.getAscent();

    //    Console.writeln( "Final bounds: " + x + "," + y + "  " + maxx + "," + maxy );
    int sx = x - 5;
    int sy = y - 5;
    int tw = maxx + 10;
    int th = maxy + fms.getDescent() + 10;

    if ( draw_fade )
      {
	w = maxx + 1;
	h = maxy + 1;
	set = true;
	// the +10s is to give space for shadow lines and thickness of stroke.
	buff = surf.createImage( tw + 10, th + 10 );

	return;
      }

    g.drawRect( sx, sy, tw, th );

    // add shadow lines
    sx += 5;
    sy += 5;
    tw += 5;
    th += 5;
    g.drawLine( sx, sy + th, sx + tw, sy + th );
    g.drawLine( sx + tw, sy, sx + tw, sy + th );

    g.setFont( of );
  } // end draw



  public Object clone()
  {
    TextBox e = new TextBox( surf, this );

    return e;
  }




  public boolean includes( GPoint p, double offset )
  {
    if ( (p.x >= x) && (p.y > y) && (p.x <= (x + w)) && (p.y <=(y+h)))
      return true;

    return false;
  }

  public boolean contains( GPoint p )
  {
    if ( (p.x >= x) && (p.y > y) && (p.x <= (x + w)) && (p.y <=(y+h)))
      return true;

    return false;
  }

  public void move( GPoint p )
  {
    Rectangle r = getBounds();
    x = (int) ( p.x - r.width / 2);
    y = (int) ( p.y - r.height / 2);
    //    set = false;
    //    buff = null;
  }

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

  public double size() 
  {
    Assert.error( "size not implemented." );
    
    return -1;
  }

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


  public Location getLocation()
  {
    return( new Location( new Rectangle( x, y, w, h ) ) );
  }

  public Rectangle getBounds()
  {
    return( new Rectangle( x, y, w, h) );
  }

}






