//  Turtle.java
//      Extremely primitive graphics class for drawing lines
//  by: John Zelle

//      The GraphWin Helper class is based on a TurtleCanvas class written by
//      Tim Hickey at Brandeis.

import java.awt.*;
import javax.swing.JPanel;
import java.awt.image.BufferedImage;

public class Turtle{
  
  private double _x; 
  private double _y; 
  private double _angle; 
  private java.awt.Color _color = Color.BLACK; // color of the turtle
  
  // Create a turtle at (x,y) with given direction and color
  //     (x,y) is computed with (0,0) at center of window
  //     Direction is an angle in degrees where 0 is East
  public Turtle(double x, double y, double direction, Color color){
    _x = x;
    _y = y;
    _angle = direction;
    _color = color;
  }
  
  // Move the turtle the specified distance and draw a line in the process.
  public void move(double dist) {
    // Compute position
    double x1 = _x + Math.cos(_angle/360.0*Math.PI*2) * dist;
    double y1 = _y + Math.sin(_angle/360.0*Math.PI*2) * dist;
    
    // Draw Line
    Turtle.setColor(_color);
    Turtle.drawLine(_x,_y,x1,y1);
    
    // Update turtle
    _x = x1;
    _y = y1;
  }
  
  
  // Turn turtle clockwise the specified number of degrees
  public void turn(double b) {
    _angle += b;
  }
  
  
  public String toString() {
    return "<Turtle: "+  _x+","+ _y +","+ _angle+">";
  }
  
  
  /* ************** STATIC METHODS ***********************/
  
  private static final Color BACKGROUND_COLOR = Color.WHITE;
  private static GraphWin win = new GraphWin(400,400, "Turtle Window");
  
  
  // Display the graphics window with the given dimenstions
  // Note: There is one window shared by all turtles.
  
  public static void showWindow(int w, int h){
    showWindow(w,h, "Turtle Window");
  }
  
  public static void showWindow(int w, int h, String title) {
    //win = new GraphWin(w,h,title);
    win.win.setVisible(true);
    win.win.setSize(new java.awt.Dimension(w,h));
    win.win.validate();
    //win.win.setResizable(false);
    Turtle.clear();
  }
  
  // Draw a line from (x,y) to (newx, newy) in the graphics window
  public static void drawLine(double x, double y, double newx, double newy) {
    win.graphics.drawLine((int)(x+win.width/2), 
                          (int)(win.height/2-y), 
                          (int) (newx+win.width/2), 
                          (int) (win.height/2-newy));
    win.repaint();
    win.win.repaint();
  }
  
  // Clear the graphics window
  public static void clear() {
    win.setBuffers(); 
    Turtle.sleep(1.0);
    win.graphics.setColor(BACKGROUND_COLOR); 
    win.graphics.fillRect(0,0,win.width,win.height);
    win.repaint();
    win.win.repaint();
  }
  
  
  // Change the drawing color for calls to drawLine
  public static void setColor(Color c) {
    win.graphics.setColor(c);
  }
  
  // Pause for the specified number of seconds
  public static void sleep(double seconds) {
    try {java.lang.Thread.sleep((long)(1000*seconds));} catch(Exception e) {;};     
  }
    public static void main(String[] args)
  {  Turtle t=new Turtle(150,150,0,Color.blue);
	  t.showWindow(1000,1000, "Turtle");
	  t.move(100);
	  t.turn(90);
	  t.move(100);
	  t.turn(90);
	  t.move(100);
  }
}


class GraphWin extends JPanel {
  public javax.swing.JFrame win;
  
  public BufferedImage buffer;
  public Graphics graphics;
  public int width,height;
  int bufferwidth,bufferheight;
  
  Dimension size;
  
  
  public GraphWin(int w, int h, String title) 
  {
    super();
    width = bufferwidth = w; 
    height = bufferheight = h;
    size = new Dimension(width,height);
    win = new javax.swing.JFrame(title);
    win.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
    win.getContentPane().add(this);
  }

  
  public Dimension getPreferredSize() {return size;}
  
  /* if new window needs larger buffer then expand image buffer */
  private void resizeSchemeCanvas(Dimension s) {
    int w=s.width;
    int h=s.height;
    boolean resize= ((w>bufferwidth)||(h>bufferheight));
    width=w; height=h;
    bufferwidth  = (w<bufferwidth) ?bufferwidth: w;
    bufferheight = (h<bufferheight)?bufferheight:h;
    if (resize) {
      BufferedImage buffer2 = buffer;
      Graphics graphics2 = graphics;
      buffer = (BufferedImage) this.createImage(bufferwidth,bufferheight);
      graphics = buffer.getGraphics();
      graphics.drawImage(buffer2,0,0,this);
    }
  }
  
  public void update(Graphics g) {
    paint(g);
  }
  
  public void setBuffers() {
    if (buffer==null) buffer = (BufferedImage) this.createImage(width,height);
    if (graphics==null) graphics = buffer.getGraphics();
  }
  
  public void paint(Graphics g) {
    setBuffers();
    if (!(size.equals(this.getSize()))) resizeSchemeCanvas(this.getSize());
    if (buffer!=null)
      ((Graphics2D) g).drawImage(buffer,0,0,this);
  }

}
