import java.awt.*;
import java.net.*;
import java.util.StringTokenizer;
import java.util.Vector;
import java.applet.AudioClip;

class Critter {
	public	Point	p_;
	public	Critter() {
		p_ = new Point(0,0);
	}
	public	Critter(int x, int y) {
		if (x < 1) x = 1;
		if (y < 1) y = 1;
		p_ = new Point(x, y);
	}
}

public class NN extends java.applet.Applet implements Runnable {
    Thread	thread;
    int		speed;
    public	Image	nnImage;
	public	Vector	critters;
	boolean	bJustStarted;
	int		startCount;
	public	AudioClip snd_ding, snd_hit, snd_new, snd_miss, snd_won;
	NNCanvas	canvas;
	NNControls controls;

    public void init() {
		String att = getParameter("speed");
		speed = (att == null) ? 2000 : (1000 * Integer.valueOf(att).intValue());
		att = getParameter("start_count");
		startCount = (att == null) ? 1 : Integer.valueOf(att).intValue();
		nnImage = getImage(getDocumentBase(), "images/dotblue.gif");
		critters = new Vector();
		bJustStarted = true;
		try {
			snd_hit = getAudioClip(new URL(getDocumentBase(), "audio/joy.au"));
			snd_new = getAudioClip(new URL(getDocumentBase(), "audio/drip.au"));
			snd_miss=getAudioClip(new URL(getDocumentBase(),"audio/return.au"));
			snd_won =getAudioClip(new URL(getDocumentBase(),"audio/whoopy.au"));
			snd_ding = getAudioClip(new URL(getDocumentBase(),"audio/ding.au"));
		} catch (MalformedURLException e){}
		setLayout(new BorderLayout());
		canvas = new NNCanvas(this);
		controls = new NNControls(this);
		add("Center", canvas);
		add("South", controls);
    }
    public boolean handleEvent(Event e) {
		if (e.id == Event.WINDOW_DESTROY) {
			System.exit(0);
		}
		return false;
    }
    
	public void clearDots() {
		synchronized(critters) {
			int	i;
			for (i = critters.size()-1; i >= 0; i--) {
				critters.removeElementAt(i);
			}
		}
		canvas.repaint();
	}
    public void start() {
		thread = new Thread(this);
		thread.start();
    }
    public void stop() {
		thread.stop();
    }
	public void addCritter() {
		synchronized(critters) {
			Dimension	dim = canvas.size();
			if (dim.width != 0 && dim.height != 0) {
				int count = bJustStarted ? startCount : 1;
				while (count-- > 0) {
					int x = (int)(Math.random()*(dim.width-1-nnImage.getWidth(this)));
					int y = (int)(Math.random()*(dim.height-1-nnImage.getHeight(this)));
					critters.addElement(new Critter(x, y));
				}
				if (controls.sound.getState()) snd_new.play();
				bJustStarted = false;
			}
			canvas.repaint();
		}
	}
    public void run() {
		while (true) {
			addCritter();
			try {
				Thread.currentThread().sleep(speed);
			} catch (InterruptedException e){}
		}
    }
}

class NNControls extends Panel {
    NN		app_;
	public	Checkbox	sound;
	public	Button		button;

    public NNControls(NN app) {
		app_ = app;
		add(button = new Button("Clear"));
		add(sound = new Checkbox("Sound"));
		sound.setState(true);
    }

    public boolean action(Event ev, Object arg) {
		if (ev.target instanceof Button) {
			String label = (String)arg;
			if (arg == "Clear") {
				app_.clearDots();
			}

			return true;
		}

		return false;
	}
}

class NNCanvas extends Canvas {
	NN		app_;
	int		prevw, prevh;
	Image	offimage;

    public NNCanvas(NN app) {
		app_ = app;
    }
    
	public void paint(Graphics g) {
		update(g);
	}
	public synchronized void update(Graphics g) {
		Dimension d = size();
		try {
			if (offimage == null || d.width != prevw || d.height != prevh) {
				prevw = d.width;
				prevh = d.height;
				offimage = createImage(d.width, d.height);
			}
			Graphics	offg = offimage.getGraphics();
			offPaint(offg);
			offg.dispose();
			g.drawImage(offimage, 0, 0, this);
		} catch (java.lang.OutOfMemoryError e) {
			System.out.println("Applet Banner ran out of memory");
			System.exit(1);
		}
	}
	void offPaint(Graphics g) {
		Dimension d = size();
		g.clearRect(0, 0, d.width, d.height);
		g.setColor(Color.red);
		g.drawLine(0, 0, d.width-1, 0);
		g.drawLine(d.width-1, 0, d.width-1, d.height-1);
		g.drawLine(d.width-1, d.height-1, 0, d.height-1);
		g.drawLine(0, d.height-1, 0, 0);
		int	i;
		synchronized(app_.critters) {
			for (i = 0; i < app_.critters.size(); i++) {
				Critter	critter = (Critter)app_.critters.elementAt(i);
				int x = critter.p_.x;
				int y = critter.p_.y;
				g.drawImage(app_.nnImage, critter.p_.x, critter.p_.y, this);
			}
		}
		//app_.controls.repaint();
	}
    public boolean keyDown(Event evt, int key) {
		if (key == ' ') {
			app_.addCritter();
			repaint();
		}
		return true;
	}
    public boolean mouseUp(Event evt, int x, int y) {
		int w = app_.nnImage.getWidth(this);
		int h = app_.nnImage.getHeight(this);
		boolean	found = false;
		int	i;
		synchronized(app_.critters) {
			for (i = app_.critters.size()-1; !found && i >= 0; i--) {
				Critter	critter = (Critter)app_.critters.elementAt(i);
				int px = critter.p_.x;
				int py = critter.p_.y;
				if (x > px && x < px+w && y > py && y < py+h) {
					app_.critters.removeElementAt(i);
					found = true;
				}
			}
		}
		if (found) {
			if (app_.critters.size() == 0) {
				if (app_.controls.sound.getState()) app_.snd_won.play();
			} else {
				if (app_.controls.sound.getState()) app_.snd_hit.play();
			}
		} else {
			if (app_.controls.sound.getState()) app_.snd_miss.play();
		}
	    repaint();
	    return true;
	}
}
