import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.io.*;
import java.util.Random;
import javax.imageio.*;
import javax.swing.*;

/**
 * An example of animation with user interaction
 *
 * @author  Prof. David Bernstein, James Madison University
 * @version 1.0
 */
public class WhackADuke extends    JComponent 
                        implements ActionListener, MouseListener
{
    private Image              head;    
    private int                direction, hits, speed, steps, x, y;
    private Random             rng;
    private Rectangle2D.Float  base;
    private Timer              timer;

    private final Color GOLD       = new Color(0xc2,0xa1,0x4d);

    private final Font  SCORE_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 20);

    private final int HEAD_HEIGHT  = 70;
    private final int HEAD_WIDTH   = 70;
    private final int HIDDEN_STEPS = 10;

    /**
     * Default Constructor
     */
    public WhackADuke()
    {
       // Construct a random number generator
       rng = new Random();

       // Read the Madison head
       try
       {
          head = ImageIO.read(new File("madison.png"));
       }
       catch (IOException ioe)
       {
          head = null;          
       }

       // Construct the base
       base = new Rectangle2D.Float(0f, 400f, 500f, 100f);
       
       // Initialize
       direction = 0;
       x         = 0;
       y         = (int)base.getY();
       speed     = 2;

       // Make this object a MouseListener on itself
       addMouseListener(this);

       // Construct and start the timer
       timer = new Timer(10, this);
       timer.start();
    }

    /**
     * Handle actionPerformed messages (required by ActionListener)
     *
     * @param  event   The ActionEvent that generated the message
     */
    public void actionPerformed(ActionEvent event)
    {
       if (direction == 0) // The head isn't moving
       {
          steps++;
          if (steps > HIDDEN_STEPS) 
          {
             x = rng.nextInt(400);
             y = (int)base.getY();
             steps = 0;
             direction = -1;
          }
       }
       else if (direction == -1) // The head is moving up
       {
          y += direction * speed;

          if (y <= ((int)base.getY() - HEAD_HEIGHT))
          {
             direction = 1;
          }
       }
       else if (direction == 1) // The head is moving down
       {
          y += direction * speed;

          if (y >= (int)base.getY())
          {
             direction = 0;
          }
       }

       repaint();
    }

    /**
     * Handle mouseClicked messages (requried by MouseListener)
     *
     * @param event  The MouseEvent that generated the message
     */
    public void mouseClicked(MouseEvent event)
    {
       int       mouseX, mouseY;
       
       // Get the position of the mouse
       mouseX = event.getX();
       mouseY = event.getY();

       // Check for a whack
       if ((direction != 0) && 
           (mouseX >= x) && (mouseX <= x+HEAD_WIDTH) &&
           (mouseY >= y) && (mouseY<=  y+HEAD_HEIGHT))
       {
          hits++;
       }
    }

    /**
     * Handle mouseEntered messages (requried by MouseListener)
     *
     * @param event  The MouseEvent that generated the message
     */
    public void mouseEntered(MouseEvent event)
    {
    }

    /**
     * Handle mouseExited messages (requried by MouseListener)
     *
     * @param event  The MouseEvent that generated the message
     */
    public void mouseExited(MouseEvent event)
    {
    }


    /**
     * Handle mousePressed messages (requried by MouseListener)
     *
     * @param event  The MouseEvent that generated the message
     */
    public void mousePressed(MouseEvent event)
    {
    }

    /**
     * Handle mouseReleased messages (requried by MouseListener)
     *
     * @param event  The MouseEvent that generated the message
     */
    public void mouseReleased(MouseEvent event)
    {
    }

    /*
     * Render this JComponent
     *
     * @param g   The rendering engine to use
     */
    public void paint(Graphics g)
    {
       float                height, width;       
       Graphics2D           g2;
       Rectangle2D          background;
       

       g2 = (Graphics2D)g;

       // Clear the screen
       background = getBounds();
       width      = (float)background.getWidth();       
       height     = (float)background.getHeight();       
       g2.setColor(Color.WHITE);
       g2.fill(background);
       
       // Render the head
       g2.drawImage(head, x, y, null);
       
       // Render the base
       g2.setColor(GOLD);
       g2.fill(base);

       // Render the score
       g2.setColor(Color.BLACK);
       g2.setFont(SCORE_FONT);       
       g2.drawString("Score: "+hits, 300, 100);
    }
}
