import java.awt.*;
import java.awt.image.BufferedImage;
import java.applet.*;
import java.util.Random;
import java.util.Scanner;
import java.awt.event.*;

public class CAColorRandomizer extends Applet implements Runnable {
	//Variables
	private boolean[] ruleDigit = {false, true, true, false, true, true, true, false};	//Rule 110
	//private boolean[] ruleDigit = {false, false, false, true, true, true, true, false};		//Rule 30
	private BufferedImage drawing;
	private Graphics2D g;
	private int key;
	private Thread myThread;
	private boolean[] rowInit = {false, false, true, false, false};
	private int bgCount = 1;
	private int numStripes = 12;
	private int incFact = 32 * numStripes;
	private int triSize = 1;
	private int arrayH = 300 / triSize;
	//private int xMax = 20 * 14; //Must be multiple of 14
	private int xMax = 300;
	private int yStart = 40;
	private Random random = new Random();
	
	boolean cellA = false;
	boolean cellB = false;
	boolean cellC = false;
	private boolean[] row = new boolean[xMax];
	//private boolean[] row = {false, true, true, true, true, true, false};
	private boolean[][] array = new boolean[arrayH][xMax];
	private boolean[][] tempArray = new boolean[arrayH][xMax];
	//private int rowLength = row.length;
	private boolean[] tempRow = new boolean[row.length];
	private boolean simple110 = false;
	private int numColors = 7;
	private boolean isUp;
	private boolean isDown;
	public boolean keyDown(Event e, int key) {
		if(key == Event.UP) {
			isUp = true;
		}
		if(key == Event.DOWN) {
			isDown = true;
		}
		return true;
	}

	public boolean keyUp(Event e, int key) {
		if(key == Event.UP) {
			isUp = false;
		}
		if(key == Event.DOWN) {
			isDown = false;
		}
		return true;
	}
	public void keyTyped(KeyEvent e) {

	}
	Scanner scan = new Scanner(System.in);


	// More variables
	
	Color redColor;
	Color weirdColor;
	Color bgColor;
	Color whiteColor;
	Color blackColor;
	Color greenColor;
	Color yellowColor;
	Color orangeColor;
	Color cyanColor;
	Color blueColor;
	Color violetColor;
	Color purpleColor;
	Color redPurple;
	private int[] tDArr = new int[1];
	//private int offset = -300;
	private int xSize = 800;
	private int ySize = 680;
	//private int offset = -(xSize * triSize - xSize);
	private int offset = 100;
	private int stepNumber = 1;
	private int oldTCount = 0;
	int initRowL;
	public void init() 
	{
		
		for(int i = 0; i < row.length; i++) {
			row[i] = random.nextBoolean();
		}
		/*
		for (int i = 0; i < array[0].length - rowInit.length; i++) {
			row[i] = false;
		}
		for (int i = 0; i < rowInit.length; i ++) {
			row [array[0].length - rowInit.length + i] = rowInit[i];
		}
		if (row.length == 5 && row[0] == false && row[1] == false && row[2] == true && row[3] == false && row[4] == false && ruleDigit[0] == false && ruleDigit[1] == true && ruleDigit[2] == true && ruleDigit[3] == false && ruleDigit[4] == true && ruleDigit[5] == true && ruleDigit [6] == true && ruleDigit[7] == false) {
			simple110 = true;
		}
		*/
		//System.out.println(simple110);
		//System.out.println(array.length);
		// set up double buffering
		drawing = new BufferedImage((int) xSize, (int) ySize, BufferedImage.TYPE_4BYTE_ABGR);
		g = drawing.createGraphics();
		resize((int) xSize, (int) ySize);

		// Colors
		initRowL = row.length;
		redColor = Color.red;
		weirdColor = new Color(60,60,122);
		bgColor = Color.black;
		whiteColor = Color.white;
		blackColor = Color.black;
		greenColor = Color.green;
		yellowColor = Color.yellow;
		//orangeColor = Color.orange;
		orangeColor = new Color(255, 128, 0);
		cyanColor = Color.cyan;
		blueColor = Color.blue;
		purpleColor = new Color(128,0,255);
		violetColor = new Color(255, 0, 255);
		redPurple = new Color (255,0,128);

		setBackground(bgColor);
		
		for (int i = 0; i < row.length; i++) {
			array[0][i] = row[i];
		}
	}
	

	public void stop()
	{
		myThread = null;
	}

	public void start() {
		if(myThread == null) {
			myThread = new Thread(this, "curvechange");
			myThread.start();
		}
	}
	//Gets keys and updates graphics
	public void run() {
		while(true) {
			//speed
			try {Thread.sleep(0);}
			catch(Exception e) {}
			update(getGraphics());
			
		}
	}
	public void update(Graphics gr) {
		paint(gr);
	}
	// Draws stuff on screen
	public void paint(Graphics gr) {
		/*
		for(int i = 0; i < row.length; i++) {
			System.out.print(row[i]); 
		}
		System.out.println();
		*/
		
		if (isUp == true) {
			while(isDown == false) {
				Wait.oneSec();
			}
		}
		
		g.setColor(bgColor);
		g.fillRect(0, 0, (int) xSize, (int) ySize);
		//Randomizes center line
		row[(int) row.length / 2] = random.nextBoolean();
		for(int i = 0; i < row.length && i < xMax; i++) {
			array[arrayH - 1][i] = row[i];
			//System.out.print(array[arrayH - 1][i]);
		}
		//System.out.println(stepNumber);
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array[i].length; j++) {
				
				//array[stepNumber - 1][j] = row[j];
				if (array[i][j] == true) {
					g.setColor(blackColor);
					//System.out.print("true");
				}
				else {
					g.setColor(whiteColor);
				}
				//g.drawRect((int) (xSize / 2) + 2 * j - 2 * i, 50 + 2 * i, 0, 0);
				//g.drawRect(450 - array[i].length + j + stepNumber, 100 + array.length, 0, 0);
				
				//finds length of triangle top
				boolean isTrue = true;
				if(j==0){
					}
				if (array[i][j] == false) {
					if(j==0){
						}
					int numTrue = 0;
					while (j + numTrue + 1 < array[i].length && array[i][j + numTrue + 1]) {
						if(j==0){
							}
						numTrue++;
						if (j + numTrue + 1 == array[i].length && (i-1) >= 0 && array[i-1][0] == true) {
							int k = 0;
							while (array[i-1][k]) {
								numTrue++;
								k++;
							}
							
						}
					}
					//System.out.print(numTrue + ", ");
					//Draws triangles
					
					//System.out.println(numTrue);
					
					if (numTrue % numColors  - 2 == 1) {
						g.setColor(redColor);
					}
					if (numTrue % numColors - 2 == 2) {
						//System.out.println("orange");
						g.setColor(orangeColor);
					}
					if (numTrue % numColors - 2 == 3) {
						g.setColor(yellowColor);
					}
					if (numTrue % numColors - 2 == 4) {
						g.setColor(greenColor);
					}
					if (numTrue % numColors - 2 == -2) {
						//System.out.println("cyan");
						g.setColor(cyanColor);
					}
					if (numTrue % numColors - 2 == -1) {
						g.setColor(blueColor);
					}
					if (numTrue % numColors -2 == 0) {
						g.setColor(violetColor);
					}
					/*
					if (numTrue % numColors - 2 == 0) {
						g.setColor(redPurple);
					}
					*/
					//g.setColor(blackColor);
					if (numTrue >= 3) {
						for (int k = triSize * (2 * numTrue - 2) - (triSize * 2 - 1); k > 0; k--) {
							g.drawLine(triSize * 2 - 1 + offset + triSize * 2 * j, yStart + triSize * 2 * i + triSize * 2 * (numTrue - 1) - k, triSize * 2 - 1 + offset + triSize * 2 * j + k - 1, yStart + triSize * 2 * i + triSize * 2 * (numTrue - 1) - k);
						}
					}
					//g.setColor(blackColor);
					if (numTrue >= 3) {
						g.fillRect(offset + triSize * 2 * j, yStart + triSize * 2 * i, triSize * 2 * ((numTrue - 2) + 1), triSize * 2 - 1);
						g.fillRect(offset + triSize * 2 * j, yStart + triSize * 2 * i, triSize * 2 - 1, triSize * 2 * ((numTrue - 2) + 1));
					}
						//g.drawLine((int) (xSize / 2) + 2 * j + 4, 50 + 2 * i + 2 * numTrue - 7 - 2, (int) (xSize / 2) + 2 * j + 7 + 4, 50 + 2 * i + 2 * numTrue - 7 - 2);
						//g.drawLine((int) (xSize / 2) + 2 * j - 2 * i + 3, 50 + 2 * i + 2, (int) (xSize / 2) + 2 * j - 2 * i + 5 + 3 + 2, 50 + 2 * i + 2);
						//g.drawLine((int) (xSize / 2) + 2 * j - 2 * i + 3, 50 + 2 * i + 2, (int) (xSize / 2) + 2 * j - 2 * i + 3, 50 + 2 * i + 2 + 7);
						//System.out.println("numTrue == 5");
					//}
					/*
					if (numTrue == 5) {
						for (int k = 2 * (numTrue - 1) - 2; k > -1; k--) {
							g.drawLine((int) (xSize / 2) + 2 * j - 2 * i + 4, 50 + 2 * i + 5 - k + 4, (int) (xSize / 2) + 2 * j - 2 * i + k + 4, 50 + 2 * i + 5 - k + 4);
						}
						g.drawLine((int) (xSize / 2) + 2 * j - 2 * i + 3, 50 + 2 * i + 2, (int) (xSize / 2) + 2 * j - 2 * i + 5 + 3 + 2, 50 + 2 * i + 2);
						g.drawLine((int) (xSize / 2) + 2 * j - 2 * i + 3, 50 + 2 * i + 2, (int) (xSize / 2) + 2 * j - 2 * i + 3, 50 + 2 * i + 2 + 7);
						//System.out.println("numTrue == 5");
					}
					*/
					//Draws triangle
					/*
					for (int k = 5; k > -1; k--) {
						g.drawLine(0, 5 - k, k, 5 - k);
					}
					*/

				}
				if (i + 1 < array.length) {
					array[i][j] = array[i + 1][j];
				}
			}
			//System.out.println("-");
		}
		g.setColor(bgColor);
		//g.fillRect(0, 50 + 2 * stepNumber, (int) xSize, 100);
		
		//Increases tempArray row number
		//tempArray = new boolean[stepNumber + 1][];
		
		for(int i = 0; i < row.length; i++){
			
			if (i - 1 >=0 && i + 1 < row.length) {
				cellA = row[i - 1];
				cellB = row[i];
				cellC = row[i + 1];
			}
			if (i == row.length - 1) {
				cellA = row[row.length - 2];
				cellB = row[row.length - 1];
				cellC = row[0];
			}
			if (i == 0) {
				cellA = row[row.length - 1];
				cellB = row[0];
				cellC = row[1];
			}
			
			if (cellA == false && cellB == false &&  cellC == false) {
				tempRow[i] = ruleDigit[7];
			}
			if (cellA == false && cellB == false && cellC == true) {
				tempRow[i] = ruleDigit[6];
			}
			if (cellA == false && cellB == true && cellC == false) {
				tempRow[i] = ruleDigit[5];
			}
			if (cellA == false && cellB == true && cellC == true) {
				tempRow[i] = ruleDigit[4];
			}
			if (cellA == true && cellB == false && cellC == false) {
				tempRow[i] = ruleDigit[3];
			}
			if (cellA == true && cellB == false && cellC == true) {
				tempRow[i] = ruleDigit[2];
			}
			if (cellA == true && cellB == true && cellC == false) {
				tempRow[i] = ruleDigit[1];
			}
			if (cellA == true && cellB == true && cellC == true) {
				tempRow[i] = ruleDigit[0];
			}
		}
		/*
		for (int i = 0; i < row.length; i++) {
			tempRow[i] = row[i];
		}
		*/
		//rowLength += 1;
		
		//Increments row length
		//row = new boolean[row.length + 2];
		for (int i = 0; i < tempRow.length; i++) {
			row[i] = tempRow[i];
		}
		tempRow = new boolean[row.length];
		//Increments step number
		stepNumber ++;
		gr.drawImage(drawing, 0,0, this);
	}
}
	
