import java.awt.*;
import java.util.*;
import java.util.List;

/**
 * This class implements a simple visual programming language. It models a
 * point moving inside a square, obeying commands such as turn and move.
 * The square is just a Canvas, restrained to be 300x300 pixels in size.
 *
 * @author Weiqi Gao, Object Computing, Inc.
 * @version $Id: Turtle.java,v 1.3 2003/07/26 13:28:24 weiqi Exp $
 */
public class Turtle extends Canvas {
    // The heading of the point, defaults to 0, which is eastwards
    private double h;

    // The current position of the point
    private int x;
    private int y;

    // A list of all the points travelled by the point
    private List l = new ArrayList();

    // An off screen image used for double buffering
    private Image i;

    /**
     * Build the GUI and hook up the listeners
     */
    public Turtle() {
        setBackground(Color.white);
        setSize(300, 300);
        reset();
    }

    /**
     * Create the off screen buffer when the canvas is first realized
     */
    public void addNotify() {
        super.addNotify();
        Dimension size = getSize();
        i = createImage(size.width, size.height);
    }

    /**
     * Redraw the screen
     *
     * @param g The graphics context
     */
    public void paint(Graphics g) {
        Graphics gi = i.getGraphics();
        gi.setColor(Color.white);
        gi.fillRect(0, 0, i.getWidth(this), i.getHeight(this));
        gi.setColor(Color.black);
        Point p0 = null;
        ListIterator li = l.listIterator();
        while (li.hasNext()) {
            Point p = (Point) li.next();
            System.out.print("[" + p.x + "," + p.y + "], ");
            if (p0 != null) {
                gi.drawLine(p0.x, p0.y, p.x, p.y);
            }
            p0 = p;
        }
        g.drawImage(i, 0, 0, this);
    }
                
            
    //Commands for the Turtle language
    /**
     * Reset
     */
    public void reset() {
        l.clear();
        h = 0;
        x = getSize().width / 2;
        y = 3 * getSize().height / 4;
        l.add(new Point(x, y));
        invalidate();
        repaint();
    }

    /**
     * Move
     *
     * @param amount The amount to move along the direction of the current
     * heading, in pixels
     */
    public void move(int amount) {
        // The heading in radians
        double r = h * Math.PI / 180;
        x += (int) (amount * Math.cos(r));
        y -= (int) (amount * Math.sin(r));
        // Add the new point to the list
        l.add(new Point(x, y));
        invalidate();
        repaint();
    }

    /**
     * Turn
     *
     * @param angle The degrees to turn, positive degrees turns the heading
     * counterclockwise
     */
    public void turn(double angle) {
        h += angle;
    }

    public static void main(String[] args) {
        Frame f = new Frame();
        Turtle t = new Turtle();
        f.add(t);
        f.pack();
        f.setVisible(true);
    }
            
}
