import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class RandomWalk extends JFrame {
	private static final int WIDTH = 640;
	private static final int HEIGHT = 480;
	private static final Dimension PLOT_SIZE = new Dimension(WIDTH, HEIGHT);

	private final JTextField countField_ = new JTextField(8);
	private final JButton startButton_ = new JButton(new AbstractAction("開始") {
		public void actionPerformed(ActionEvent e) { start(); }
	});
	private final JButton stopButton_ = new JButton(new AbstractAction("停止") {
		public void actionPerformed(ActionEvent e) { stop(); }
	});
	private final JButton endButton_ = new JButton(new AbstractAction("終了") {
		public void actionPerformed(ActionEvent e) { dispose(); }
	});

	private final Random random_ = new Random();

	private volatile boolean walking_ = false;
	private final List<Point> points_ = new ArrayList<Point>();

	public RandomWalk() {
		super("2次元ランダムウォーク");
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setResizable(false);

		configure();

		Box main = Box.createVerticalBox();
		main.add(createOperationArea());
		main.add(createPlotArea());
		this.add(main);

		Timer timer = new Timer();
		timer.schedule(new TimerTask() {
			public void run() {
				repaint();
			};
		}, 0, 100L);
	}
	private void configure() {
		countField_.setText("1000");

		startButton_.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			}
		});
		stopButton_.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			}
		});
	}

	private JComponent createPlotArea() {
		plotArea_.setBackground(Color.WHITE);
		plotArea_.setPreferredSize(PLOT_SIZE);
		return plotArea_;
	}
	private JComponent createOperationArea() {
		JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		panel.add(new JLabel("N="));
		panel.add(countField_);
		panel.add(Box.createHorizontalGlue());
		panel.add(startButton_);
		panel.add(stopButton_);
		panel.add(endButton_);
		return panel;
	}


	public void start() {
		initialize();
		walking_ = true;
	}
	public void stop() {
		walking_ = false;
	}


	private void initialize() {
		int count = 1;
		try {
			count = Integer.parseInt(countField_.getText());
		} catch (NumberFormatException e) {
		}
		points_.clear();
		points_.add(new Point(WIDTH / 2, HEIGHT / 2));
		for (int index = 1; index < count; index++) {
			points_.add(new Point(random_.nextInt(WIDTH), random_.nextInt(HEIGHT)));
		}
	}

	private final JPanel plotArea_ = new JPanel() {
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);

			if (walking_) {
				for (Point p: points_) {
					nextStep(p);
					g.drawRect(p.x, p.y, 1, 1);
				}
			}
		}
		private void nextStep(Point p) {
			switch (random_.nextInt(4)) {
				case 0:
					p.x--;
					break;
				case 1:
					p.x++;
					break;
				case 2:
					p.y--;
					break;
				case 3:
					p.y++;
					break;
			}
		}
	};


	public static void main(String[] args) {
		RandomWalk frame = new RandomWalk();
		frame.pack();
		frame.setVisible(true);
	}
}
