/*
 * Copyright (C) 2005   Robert Nowotniak
 *
 * Diffusion Limited Aggregation
 * -----------------------------
 *
 */
import java.lang.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.image.*;
import javax.imageio.*;

public class Dla {

	public static void main(String[] args) {
		Okno1 o = new Okno1("Diffusion Limited Aggregation");
		o.setVisible(true);
	}
}



class Okno1 extends Frame
	implements ActionListener, ItemListener, MouseListener, WindowListener {
	
	static final int WIDTH = 500;
	static final int HEIGHT = 500;
	static final int DELAY = 500;

	private BufferedImage image;
	private boolean DataArray[][];
	private int max_x, max_y;

	public Okno1() {
		this("Okno");
	}

	public Okno1(String title) {
		super(title);
		addWindowListener(this);
		addMouseListener(this);

		image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
		DataArray = new boolean[HEIGHT][WIDTH];

		Thread thr = new DrawingThread(image);
		thr.start();

		setSize(WIDTH, HEIGHT);
	}

	private class DrawingThread extends Thread {
		private BufferedImage image;
		private WritableRaster rast;

		public DrawingThread(BufferedImage image) {
			this.image = image;
			this.rast = image.getRaster();
		}

		public void run() {
			Graphics2D g = image.createGraphics();
			g.setColor(Color.BLACK);
			g.fillRect(0, 0, WIDTH, HEIGHT);

			//putCell(WIDTH / 2, HEIGHT / 2, 255, 255, 255);
			for (int x = 10; x < WIDTH - 10; x++) {
				putCell(x, 10, 255, 255, 255);
				putCell(x, HEIGHT - 10, 255, 255, 255);
			}
			for (int y = 0; y < HEIGHT - 10; y++) {
				putCell(10, y, 255, 255, 255);
				putCell(WIDTH - 10, y, 255, 255, 255);
			}

			int n = 0;
			int x, y;
			max_x = 20;
			max_y = 20;
			for (;;) {

				x = WIDTH / 2;
				y = HEIGHT / 2;

				/*
				switch ((int) (4.0 * Math.random())) {
					case 0:
						y -= max_y;
						x -= (int) (2 * max_x * Math.random()) - max_x;
						break;
					case 1:
						y += max_y;
						x -= (int) (2 * max_x * Math.random()) - max_x;
						break;
					case 2:
						x -= max_x;
						y -= (int) (2 * max_y * Math.random()) - max_y;
						break;
					case 3:
						x += max_x;
						y -= (int) (2 * max_y * Math.random()) - max_y;
						break;
				}
				*/
				doBrown(x, y);

				if (n++ % 1000 == 0)
					Okno1.this.repaint();
			}
		}

		private void doBrown(int x, int y) {
			boolean makeCell = false;

			while (!makeCell) {
				if (x < 0 || x >= WIDTH)
					break;
				if (y < 0 || y >= HEIGHT)
					break;

				if (x > 0 && DataArray[y][x - 1]) {
					makeCell = true;
				}
				else if (x < WIDTH - 1 && DataArray[y][x + 1]) {
					makeCell = true;
				}
				else if (y > 0 && DataArray[y - 1][x]) {
					makeCell = true;
				}
				else if (y < HEIGHT - 1 && DataArray[y + 1][x]) {
					makeCell = true;
				}
				else
					switch ((int) (4.0 * Math.random())) {
						case 0:
							x++;
							break;
						case 1:
							x--;
							break;
						case 2:
							y++;
							break;
						case 3:
							y--;
							break;
					}
			}

			if (makeCell) {
				putCell(x, y, 255, 255, 255);
				if (Math.abs(x) > Math.abs(max_x)) {
					max_x = Math.abs(x - WIDTH / 2) + 10;
				}
				if (Math.abs(y) > Math.abs(max_y)) {
					max_y = Math.abs(y - HEIGHT / 2) + 10;
				}
				if (max_y > max_x) {
					max_x = max_y;
				}
				else if (max_x > max_y) {
					max_y = max_x;
				}
			}
		}

		private void putCell(int x, int y, int r, int g, int b) {
			DataArray[y][x] = (r | g | b) != 0;
			rast.setPixel(x, y, new float[] {r, g, b});
		}
	}

	public void update(Graphics g) {
		paint(g);
	}

	public void paint(Graphics g) {
		g.drawImage(image, 0, 0, this);
	}

	public void actionPerformed(ActionEvent event) {
		if (event.getSource() == null) {
			
		}
	}
	public void itemStateChanged(ItemEvent event) {
		if (event.getSource() == null) {
			
		}
	}

	public void mouseClicked(MouseEvent e) {
		String prefix = "DLA-";
		String filename = null;
		String number;
		File file = null;
		for (int i = 1; i < 10000 && (file == null || file.exists()); i++) {
			filename = prefix;
			number = "" + i;
			for (int j = 0; j < 4 - number.length() + 2; j++) {
				number = "0" + number;
			}
			filename += number + ".png";
			file = new File(filename);
		}
		System.out.println(filename);
		try {
			ImageIO.write(image, "png", file);
		} catch (IOException ex) {
			System.out.println("Error during writing");
		}
	}
	public void mouseEntered(MouseEvent e) { }
	public void mouseExited(MouseEvent e) { }
	public void mousePressed(MouseEvent e) { }
	public void mouseReleased(MouseEvent e)  { }

	public void windowActivated(WindowEvent e) { }
	public void windowClosed(WindowEvent e) { }
	public void windowDeactivated(WindowEvent e) { }
	public void windowDeiconified(WindowEvent e) { }
	public void windowIconified(WindowEvent e) { }
	public void windowOpened(WindowEvent e) { }
	public void windowClosing(WindowEvent e) {
		System.exit(0);
	}
}
