import java.awt.*;
import java.applet.*;
import java.util.Date;
import java.util.Random;
public class MicrosoftColorSort extends Applet {
	java.awt.Button sort;
	java.awt.Button reset;
	Ball[] balls;
	int[] colors;
	boolean[] isColorUsed;
	int totalColors = 10;
	int totalBalls = 600;
	int xs[];
	int ys[];
	public void init() {
		setBackground(Color.WHITE);
		add(reset = new java.awt.Button("Reset"));
		add(sort = new java.awt.Button("Sort"));
	}
	public boolean handleEvent(Event event) {
		if (event.target == sort && event.id == Event.ACTION_EVENT) {
			doSort(event);
			return true;
		}
		
		if (event.target == reset && event.id == Event.ACTION_EVENT) {
			doReset(event);
			return true;
		}
		return super.handleEvent(event);
	}
	
	public void paint(Graphics g) {
		drawString("Usage: Click Reset, then Sort", 10, 20);
	}
	
	private void doReset(Event event) {
		int x = 10;
		int y = 10;
		int xOffset = 20;
		int yOffset = 20;
		colors = new int[totalColors];
		isColorUsed = new boolean[totalColors];
		this.getGraphics().clearRect(0, 30, this.getWidth(), this.getHeight());
		
		
		for (int i = 0; i < totalColors; i++) {
			colors[i] = i;
		}
		
		
		int theColor = 0;
		balls = new Ball[totalBalls];
		xs = new int[totalBalls];
		ys = new int[totalBalls];
		
		for (int i = 0; i < totalBalls; i++) {
			x += xOffset;
			
			
			if ((i % 25) == 0) {
				y += yOffset;
				x = 10;
			}
			
			theColor = new Random(new Date().getTime()).nextInt(1000000) % totalColors;
			balls[i] = new Ball(theColor);
			xs[i] = x;
			ys[i] = y;
			
			
			
			
			if (!isColorUsed[theColor]) {
				isColorUsed[theColor] = true;
			}
			
			
			try {
				Thread.sleep(10);
			} catch (Exception e) {
				
			}
			
			balls[i].draw(xs[i], ys[i], this.getGraphics());
		}
	}
	
	private void drawString(String message, int x, int y) {
		this.getGraphics().setColor(Color.black);
		this.getGraphics().drawString(message, x, y);
	}
	
	private void drawBalls() {
		this.getGraphics().clearRect(0, 30, 20 * 25, this.getHeight());
		for (int i = 0; i<totalBalls; i++) {
			balls[i].draw(xs[i], ys[i], this.getGraphics());
		}
		
	}
	void doSort(Event event) {
		int start = 0;
		int yOffset = 40;
		int x = 540;
		drawString("Start indices", 540, yOffset);
		Ball displayBall = null;
		for (int i = 0; i < totalColors; i++) {
			if (isColorUsed[i]) {
				displayBall = new Ball(i);
				
				displayBall.draw(x, (i + 2) * yOffset, this.getGraphics());
				drawString(" - " + ((i == 0) ? 0: start), x + 22, ((i + 2) * yOffset) + 15 );
				start = partition(balls, colors[i], start);
				
				drawBalls();
				
				try {
					Thread.sleep(1000);
				} catch (Exception e) {
					
				}				
			}
		}		
	}
	
	
	public int partition(Ball[] balls, int sortingColor, int startIndex) {
		int i = startIndex;
		int j = balls.length - 1;
		int ithColor = 0;
		int jthColor = 0;
		Ball tmpBall = null;
		while (i <= j) {
			ithColor = balls[i].getBallColor();
			jthColor = balls[j].getBallColor();
			if ((ithColor == sortingColor) && (jthColor == sortingColor)) {
				i++;
			} else if ((ithColor == sortingColor) && (jthColor != sortingColor)) {
				i++;
			} else if ((ithColor != sortingColor) && (jthColor != sortingColor)) {
				j--;
			} else if ((ithColor != sortingColor) && (jthColor == sortingColor)) {
				tmpBall = balls[i];				
				balls[i] = balls[j];				
				balls[j] = tmpBall;
				i++;
				j--;
			}
		}
		
		return i;
	}
}
class Ball {
	private Color ballColor;
	private int colorIndex;
	public Ball(int colorIndex) {
		switch (colorIndex) {
		case 0:
			ballColor = Color.black;
			break;
		case 1:
			ballColor = Color.blue;
			break;
		case 2:
			ballColor = Color.cyan;
			break;
		case 3:
			ballColor = Color.lightGray;
			break;
		case 4:
			ballColor = Color.green;
			break;
		case 5:
			ballColor = Color.magenta;
			break;
		case 6:
			ballColor = Color.orange;
			break;
		case 7:
			ballColor = Color.pink;
			break;
		case 8:
			ballColor = Color.red;
			break;
		case 9:
			ballColor = Color.yellow;
			break;
		}
		this.colorIndex = colorIndex;
	}
	public int getBallColor() {
		return colorIndex;
	}
	public void draw(int x, int y, Graphics g) {
		g.setColor(ballColor);
		g.fillOval(x, y, 20, 20);
		g.setColor(Color.white);
		g.drawString("" + colorIndex, x + 7, y + 14);
	}
}