package graphics;

import scheme.lib.mred.mred;
import scheme.lib.htdch.graphics.rename;

public class View {

  private static int viewCount = 0;

  private dynamic frame;
  private dynamic canvas; 
  private dynamic dc;

  private dynamic buffer;

  private String name;
  private boolean visible = false;

  private boolean image = true;

  public View() {
    viewCount += 1;
    this.name = "View-"+viewCount;
  }
  
  //Produces a View with a visible canvas of size x and y
  public View display( int x, int y) {
    if (visible)
      this.hide();

    buffer = rename.newObject(mred.bitmapDcObj, rename.newObject(mred.bitmapObj,x,y));
    buffer.clear();

    class CanvasInner {
      public void callBack(dynamic canvas, dynamic dc) {
			dc.drawBitmap( View.this.buffer.getBitmap(), 0,0);
      }
    }

    frame = rename.newObject(mred.frameObj, name, false, x+15, y+20);
    canvas = rename.newObject(rename.callBackCanvasObj, frame, 
			      rename.styleList,
//			      rename.consL(rename.q(rename.toSymbol("no-autoclear")), rename.emptyList), 
    			      rename.innerToFunction( 2, new CanvasInner()));
    dc = canvas.getDc();

    this.clear();

    frame.show(true);
    visible = true;
    return this;
  }

  //Produces a View without a visible canvas
  public View hide() {
    this.visible = false;
    frame.show(visible);
    return this;
  }

  public View show() {
    this.visible = true;
    frame.show(visible);
    return this;
  }

  //The Image is a equality testable version of the canvas after the drawing command
  public Image draw( Image i) {
    drawToCanvas(i);
    dc.drawBitmap(buffer.getBitmap(), 0 ,0);
    return getBufferCopy();
  }

  //The Image is again an equality testable version of the canvas after applying all commands
  //Issues the commands in reverse order
  public Image drawSequence( CommandSequence commands ) {
    commands.drawAll(this);
    dc.drawBitmap(buffer.getBitmap(), 0 ,0);
    return getBufferCopy();
  }

  //Methods not seen by students

  void allowImage( boolean ok ) {
    this.image = ok;
  }

  private Image getBufferCopy() {
    if (image) {
      dynamic bufferBitmap = buffer.getBitmap();
      dynamic bitmapCopy = rename.newObject(mred.bitmapObj, bufferBitmap.getWidth(), bufferBitmap.getHeight());
      dynamic dcCopy = rename.newObject(mred.bitmapDcObj, bitmapCopy);
      dcCopy.clear();
      dcCopy.drawBitmap(bufferBitmap, 0, 0);
      dcCopy.setBitmap(false);
      return new Image(rename.newObject(mred.imageSnipObj, bitmapCopy, false));
    } else {
      return new Image(false);
    }
  }

  
  void keyCallBack(dynamic curWorld) {
    canvas.setCallback(curWorld);
  }

  //erases the canvas
  void clear() {
    buffer.clear();
    dc.drawBitmap(buffer.getBitmap(), 0 ,0);
  }

  //Issues the drawing command in c, causing it to draw to the canvas
  void drawToCanvas( Image i) {
    if (!visible)
      throw new RuntimeException("View must be displayed in order to draw in it");
    dynamic bitmap = i.getBitmap();
    buffer.drawBitmap(bitmap, 0, 0, rename.toSymbol("solid"), 
                      rename.newObject(mred.colorObj, "white"), bitmap.getLoadedMask());

    //c.issue(buffer);
  }

  void drawToCanvas( Command c) {
    if (!visible)
      throw new RuntimeException("View must be displayed in order to draw in it");
    c.issue(buffer);
   }
} 