import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import javax.imageio.ImageIO;
import javax.sound.sampled.*;
import javax.swing.*;

public class SimpleAnimation7 extends JPanel
        implements Runnable {
    public static final int X_LOC = 100, Y_LOC = 100,
                            WIDTH = 600, HEIGHT = 400;
    public static final int DELAY = 33; // 30 FPS

    private Thread runner;          // for animation
    private volatile boolean running; // stop animation
    private Clip clip;

    // Ball variables
    private static final int NUM_BALLS = 2;
    private ArrayList<Ball3> balls;

    public static void main(String[] args) {
        JFrame frame = new JFrame("Animation Demo");
        frame.setDefaultCloseOperation(
            JFrame.EXIT_ON_CLOSE);

        SimpleAnimation7 sa = new SimpleAnimation7();
        frame.add(sa);

        frame.setBounds(X_LOC, Y_LOC, WIDTH, HEIGHT);
        frame.setVisible(true);

        sa.startAnimation();
        // Needed for keys to hear
        sa.requestFocusInWindow(); // After visible
    }

    public SimpleAnimation7() {
        addKeyListener(new KeyHandler());
        addMouseListener(new MouseHandler());
        setBackground(Color.WHITE);
        balls = new ArrayList<Ball3>();
        BufferedImage im = loadImage("images/ball.gif");
        for (int i = 0; i < NUM_BALLS; i++) {
            Ball3 b = new Ball3(this, im);
            balls.add(b);
        }
        // Add sounds
        try {
            File file = new File("sounds/blip.wav");
            AudioInputStream stream =
                AudioSystem.getAudioInputStream(file);
            clip = AudioSystem.getClip();
            clip.open(stream);
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (UnsupportedAudioFileException ex) {
            ex.printStackTrace();
        } catch (LineUnavailableException ex) {
            ex.printStackTrace();
        }
    }

    private BufferedImage loadImage(String fileName) {
        BufferedImage im = null;
        try {
            im = ImageIO.read(getClass().getResource(fileName));
        } catch (IOException e) {
            System.out.println("Error loading " + fileName);
        }
        return im;
    }

    // Initialise and start the animation
    public void startAnimation() {
        if (runner == null || !running) {
            runner = new Thread(this);
            runner.start();
        }
    }

    // Called to stop execution
    public void stopAnimation() {
        running = false;
    }

    // Repeatedly update, render, sleep
    public void run() {
        running = true;
        while (running) {
            update();  // update position
            repaint(); // render
            try {
                Thread.sleep(DELAY); // pause
            } catch(InterruptedException ie) {
                running = false;
            }
        }
    }

    // Update the animation state
    public void update() {
        for (int i = 0; i < balls.size(); i++) {
            Ball3 b = balls.get(i);
            b.update();
        }
    }

    // Render the animation
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // paint background
        for (int i = 0; i < balls.size(); i++) {
            Ball3 b = balls.get(i);
            b.draw(g);
        }
    }

    // Play sound clip
    public void playSound() {
        clip.setFramePosition(0);
        clip.start();
    }

    private class KeyHandler extends KeyAdapter {
        public void keyPressed(KeyEvent e) {
            int keyCode = e.getKeyCode();
            if (keyCode == KeyEvent.VK_ESCAPE) {
                stopAnimation();
                System.out.println("Goodbye!");
                System.exit(0); // so enclosing JFrame exits
            }
        }
    }

    private class MouseHandler extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            if (running) {
                stopAnimation();
            } else {
                startAnimation();
            }
        }
    }
}

