import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;

public class T extends JFrame
{
    static String key;

    public static void main(String[] args)
    {
        T frame = new T();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setResizable(false);
        frame.setLocation(50, 50);
        frame.setVisible(true);

        frame.createBufferStrategy(2);
        BufferStrategy bufferStrategy = frame.getBufferStrategy();

		String wordData = "ace3s2id4ly2re2t1droit2s1ft1ge2ile2o1id3s2l3s2m3s2r3gun3s1kin1le3rt3s2ien3ght4n3t2ms2ter1mid1nd2ew2gel3le2ise2t3i2y1pe3d1rc2e3s2id2k2se4d2t1sh2k1te2om1uto1we3d1ye3s0bar3s1ed3s2lt2nd4s2t1ias2g2n3go3s1led3nd2ond5e2ue1oa3r4s3s2d3e2g2il2ld3e2nd3e4d3g2re2y1ra3s2o3s1ud3s2m3s2n3s2r3s2s3ed2t1ye2re0cad2ke4d2n3opy3t2p3e4d3on2r3e3t2se2t3er3kin2use1ent2rt1hoir3re1ider2nder3e2te1lad3p3use3y2ient2ue4s1ob2d3e2ed2g3ent2ir2l3s2mb4ed3e2n3e3y2p3y2r3e4s2s3h3ier2t2y1rate2eak3d2ied4s2umb5s1ub3s2e3s2m3s2r3b4s3s1yan0daily3s2le2m3s2re4s3t2sh2wn2y1eal3n3r4s2b3s2cal3k2li2mo4b4s2n3s3t3y2rv2w3y1how1ial4s2ce2e2m3s2n3e4r2re3t2s3h3mal1ob2c2e3r3s2g2h2le2me4s2n3e2pe2s3e3h3t2t3e4s3s2ur3se2ve3ish2wel1rat2op3ve2ug2y1ub3s2e3s3t4s2g2n3e4s3g2o3s2st1ye0ear3l3s2sy2t1cho2u3s1go1lan2k2m3s1mbryo2u3s1nd3s2try1on1ra3s2go1uro1vil1xodus0fat3hom1ir2t1oam2p2r3t0gain3t2l3e2te1el3d2n3ial3t2t3s1ilt2n3s2t1lean3n2ib2ob1nu1oat2b3lin2d2er2ld2ne2re4d2t2urd3t1rain3n2in4s2ound1uest2n2sh4er3t4ed2t3s0had2g2il2lt2m2rd3e4d4s2s2t1ead4s3r4d4s2ir2ld2n2r3d4s3o4ic3s2w1id2e2lt2re2s2t1od3s2e3d3s2ld4s3e4d3s2ne4d2p3e4d2se4d2t2use5d2w3l4ed4s1ue3s2g3e4r3s2rl4s0ice3d3s2y1dle4r3y2ol2s1nk2let2to1on2ta1re2k1sm2obar1ts0kale2rt1en3s2y3s1in2p2t1nit0lace4d4s3y2d3s3y2g2id3n2ke2ne2p2rk2te4r3h2y1ead3k3n3p2d2g2nd3t2t2wd1ib2ce2d3o3s2e3d3n2ght2ne3g4o3o3t2on2re2t3e2ve1ob3e4d2ch4s3us2de3ge5r2g2in2ne3g2rd3e2t2ud2ve2w3ed3s1ube2do2re4s2sh4er2te0mad2id4s3l4s2s2t3h1ed2lt2t1id2ld2nus1oat2b2d3e4s5t3s2re2st2te4s3h1ule4s2scle3e3t4er2te4s0nae2g2il3ve2p2ve4s3ies2y1erd4y2t2w1ib3s2ce4r3k2l2mbus2p2t1ob3le2d3e2pe2r2t3e2w3t1ub2de4s2mb4s2t0oaf2r3s2th1bey1ch3er3re1de3s1ft1gle4d2re1hm2s1ik2l3ed3s1ld3e4n4r3ie2e2ive1nce2e1pen2t1rb3s2e3s1sier1uch2r3s2st2t3age3s1ver1we3d2l3ish3s2n0pace4d3k4ed3y2d2l3e4d2n2y1ea3k3l2ck2dal2n2r3k3v1hone5d1ie3r2ke2n3t3y2t3on3y1lace5d2ea4d3d1od2int5y2ke4r3ier2ncy3d3e3y2re4d3k3t2t2ut2w1ro3d3f4it3ve5d1un3t2t0race3k4et2dio2g2id3n2ke2n3g3i2sh2t3e3io1eact3d4s3l2d3o3s2in2nd3t2p2st2v1ib3s2ce3h2d3e2ft2g3s2le4d2nd3g4s2ot4s2p3e2se1oad2b3e3s2d3e2e3s2gue2il4ed2le2pe4d2se2t3a3s2uge5d3nd3st3t4s2ve4d1ub3s2de2e3d3s2g3s2in4g2le4s2m3s2n3g2se3h3t2t3s1ye0sac2d2id3l2ke2le2ne3k2ri2uce2ve2y1cale2ore2rub4m2um1ea3l3r2c2nd2ra3um2t2x1hade3rd4e5d2e3ar3d3rd2od3e4d3uld3w2red3ug1ic2gn2lo2n3e3g2r3e2t1ka2y1lam2id3m2ouch3w2um3r1mote2ut1nake4y2eak5y2ub1oar2b2d2h2il2l3d2me2re3t2u3l3r2w2x1tem2ir2rum2ud1ub2ch2e3d3t2it4or2m2n3bed2re3ge1wig3ng0tack2g2il2ke4r2le3k4er2n3k2r3o1ea3k3l3r2d3s2n3d2rm4s3n1ic3k2e2l3e2n3e3y2p1oad2e3d3s2g3a2il2m3e4s3s2n3e3y2p3i2r3s2ur4s2w3n2y1race4k3d2ek3nd5y2iad3o4s3p2od2ue2y1ub3e2g3s2m3ble3s1wo1ypo2re0ugh1ndo2i3s2to1pon2town1rge4d4s2n1se3d3r2her0vain2n3e4s3s2se1eil3n4s2t3o1ia2e3s2le2ne4s2ol4et2sa3e1oid4s3le2le3t2te0wad3e2n3d3e4d2y1ean2d2ld2nd1ho3le1ig3s2n3g4s3s2sh1oe2n3t2p2t1ring5s0yak3s2nk4s2p2w3ed3n4ed1ea2n3s2r2s2t2w1id2n2p1ob2n0";
		String[] tempWords = new String[1071];
		String word = "";
		int n = 0;
		for (int i = 0; i < 2781; i++) //wordData.length())
		{
			char c = wordData.charAt(i);
			if (c > '9')
			{
				word += String.valueOf(c);
			}
			else
			{
				tempWords[n++] = word;
				word = word.substring(0, c - '0');
			}
		}
		String[] sixes = new String[60];
		String[] words = new String[1071];
		n = 0;
		int m = 0;
		for (int i = 3; i < 7; i++)
		{
			for (int j = 0; j < 1071; j++)
			{
				if (tempWords[j].length() == i)
				{
					words[n++] = tempWords[j];			
					if (i == 6)
					{
						sixes[m++] = tempWords[j];
					}
				}	
			}
		}
		
		Font font = new Font("Monospaced", Font.PLAIN, 20);
		Color blue = new Color(0x8080ff);
		
		String[] answers = new String[200];
		boolean[] found = new boolean[200];
		
		String guess = "";
		String answer = "";
		int numberFound = 0;
		int numberOfAnswers = 0;
		boolean qualified = false;
        int high = 0;
		int score = 0;
		int state = 0;
		int round = 0;
		long deadline = 0;
		int wait = 0;
		key = "";
		
        while(true)
        {
            Graphics2D g = (Graphics2D) bufferStrategy.getDrawGraphics();
			g.setFont(font);

            g.setColor(blue);
            g.fillRect(0, 0, 800, 600);
			
			for (int i = 0; i < 6; i++)
			{
				g.setColor(new Color(0x8080f8 - 3 * i));
				for (int j = 0; j < 8; j++)
				{
					g.fillOval(j * 100 + 5, i * 100 + 5, 90, 90);
				}
			}
			
			if (state == 0) // TITLE SCREEN
			{
				g.setColor(Color.BLACK);
				g.drawString("Word twister", 332, 282);
				g.drawString("Press any key to start", 272, 332);
				g.setColor(Color.WHITE);
				g.drawString("Word twister", 330, 280);
				g.drawString("Press any key to start", 270, 330);
				if (key.length() > 0) // start game on key press
				{
					state = 3;
					round = 0;
					score = 0;

					// shuffle order of sixes
					for (int i = 0; i < 60; i++)
					{
						int j = (int)(Math.random() * 60);
						String temp = sixes[i];
						sixes[i] = sixes[j];
						sixes[j] = temp;
					}
				}
			}
			if (state == 1 || state == 2 || state == 4) // PLAYING or END OF ROUND or GAME OVER
			{
				// time left
				long timeLeft = (deadline - System.currentTimeMillis()) / 1000;
				// game over if no time left
				if (timeLeft <= 0)
				{
					timeLeft = 0;
				}
                
                // time, score and high score
				g.setColor(Color.BLACK);
				g.drawString("Time " + timeLeft, 702, 82);
				g.setColor(Color.WHITE);
				g.drawString("Time " + timeLeft, 700, 80);
				
				// high score
				g.setColor(Color.BLACK);
				g.drawString("High  " + high, 22, 52);
				g.setColor(Color.WHITE);
				g.drawString("High  " + high, 20, 50);

				// score
				g.setColor(Color.BLACK);
				g.drawString("Score " + score, 22, 82);
				g.setColor(Color.WHITE);
				g.drawString("Score " + score, 20, 80);
				
				// draw answers
				for (int i = 0; answers[i] != null; i++)
				{
					int x = 100 + 140 * (i / 12);
					int y = 120 + 24 * (i % 12);
					int l = answers[i].length();
					for (int j = 0; j < l; j++)
					{
						g.setColor(Color.DARK_GRAY);
						g.fillRect(x + j * 20 + 3, y + 3, 20, 20);
						if (found[i])
						{
							g.setColor(Color.ORANGE);
							g.fillRect(x + j * 20, y, 20, 20);
							g.setColor(Color.BLACK);
							g.drawRect(x + j * 20, y, 20, 20);
							g.drawString(answers[i].substring(j, j + 1), x + j * 20 + 4, y + 16);
						}
						else
						{
							g.setColor(Color.WHITE);
							g.fillRect(x + j * 20, y, 20, 20);
							g.setColor(Color.BLACK);
							g.drawRect(x + j * 20, y, 20, 20);
							if (state != 1)
							{
								g.drawString(answers[i].substring(j, j + 1), x + j * 20 + 4, y + 16);
							}
						}
					}
				}
				
				// draw the letters
				for (int j = 0; j < 6; j++)
				{
					String letter = answer.substring(j, j + 1);
					g.setColor(Color.DARK_GRAY);
					g.fillRect(340 + j * 20 + 3, 523, 20, 20);
					if (guess.indexOf(letter) < 0)
					{
						g.setColor(Color.WHITE);
						g.fillRect(340 + j * 20, 520, 20, 20);
						g.setColor(Color.BLACK);
						g.drawString(letter, 340 + j * 20 + 4, 536);
					}
					else
					{
						g.setColor(blue);
						g.fillRect(340 + j * 20, 520, 20, 20);
					}
					g.setColor(Color.BLACK);
					g.drawRect(340 + j * 20, 520, 20, 20);
				}
				
				// draw the current guess
				for (int j = 0; j < guess.length(); j++)
				{
					g.setColor(Color.DARK_GRAY);
					g.fillRect(340 + j * 20 + 3, 493, 20, 20);
					g.setColor(Color.WHITE);
					g.fillRect(340 + j * 20, 490, 20, 20);
					g.setColor(Color.BLACK);
					g.drawRect(340 + j * 20, 490, 20, 20);
					g.drawString(guess.substring(j, j + 1), 340 + j * 20 + 4, 506);
				}
					
				// check for word entry
				while(key.length() > 0)
				{
					String k = key.substring(0, 1);
					if (key.charAt(0) == 10)
					{
						for (int i = 0; answers[i] != null; i++)
						{
							if (!found[i] && guess.equals(answers[i]))
							{
								found[i] = true;
								numberFound++;
								score += 10 * guess.length() * guess.length();
								if (guess.length() == 6)
								{
									qualified = true;
								}
							}
						}
						guess = "";
					}
					else if (key.charAt(0) == 8 && guess.length() > 0)
					{
						// backspace
						guess = guess.substring(0, guess.length() - 1);
					}
					else
					{
						if (guess.indexOf(k) < 0 && answer.indexOf(k) >= 0)
						{
							guess += k;
						}
					}
					key = key.substring(1);
				}
				
				// draw Round number 
				g.setColor(Color.BLACK);
				g.drawString("Round " + round, 367, 52);
				g.setColor(Color.WHITE);
				g.drawString("Round " + round, 365, 50);

				// draw progress bar
				g.setColor(Color.DARK_GRAY);
				g.fillRect(303, 63, 200, 20);
				g.setColor(blue);
				g.fillRect(300, 60, 200, 20);

				g.setColor(Color.ORANGE);
				if (qualified)
				{
					g.setColor(Color.GREEN);
				}
				
				g.fillRect(300, 60, 200 * numberFound / numberOfAnswers, 20);
				g.setColor(Color.BLACK);
				g.drawRect(300, 60, 200, 20);
				
				// end round if all answers found
				if (state == 1 && numberFound == numberOfAnswers)
				{
					state = 2;
					wait = 20;
					score += 10000;
				}
				
				if (state == 1 && timeLeft <= 0)
				{
					state = 4;
					wait = 20;
					if (qualified)
					{
						state = 2; // next round
					}
				}

			}
			if (state == 2) // END OF ROUND
			{
				if (round < 60)
				{
					g.setColor(Color.BLACK);
					g.drawString("Round complete", 317, 452);
					g.drawString("Press any key", 322, 482);
					g.setColor(Color.WHITE);
					g.drawString("Round complete", 315, 450);
					g.drawString("Press any key", 320, 480);
					if (wait-- < 0 && key != "")
					{
						state = 3;
					}
				}
				else
				{
					g.setColor(Color.BLACK);
					g.drawString("You've beaten the game", 272, 452);
					g.drawString("Press any key", 322, 482);
					g.setColor(Color.WHITE);
					g.drawString("You've beaten the game", 270, 450);
					g.drawString("Press any key", 320, 480);
					if (wait-- < 0 && key != "")
					{
						state = 0;
					}
				}
			}
			if (state == 3) // INIT ANSWERS
			{
				round++;
				answer = sixes[round];
				numberOfAnswers = 0;
				for (int i = 0; i < 1071; i++)
				{
					boolean buildable = true;
					for (int j = 0; j < words[i].length(); j++)
					{
						buildable &= answer.indexOf(words[i].substring(j, j + 1)) >= 0;
					}
					if (buildable)
					{
						answers[numberOfAnswers] = words[i];
						found[numberOfAnswers++] = false;
					}
				}
				answers[numberOfAnswers] = null;
				state = 1;
				numberFound = 0;
				deadline = System.currentTimeMillis() + 100000;
				char[] letters = answer.toCharArray();
				for (int i = 0; i < 6; i++)
				{
					int j = (int)(Math.random() * 6);
					char temp = letters[i];
					letters[i] = letters[j];
					letters[j] = temp;
				}
				answer = new String(letters);
                guess = "";
				qualified = false;
			}
			if (state == 4) // GAME OVER
			{
				g.setColor(Color.BLACK);
				g.drawString("Game over", 342, 432);
				g.drawString("Press any key", 322, 462);
				g.setColor(Color.WHITE);
				g.drawString("Game over", 340, 430);
				g.drawString("Press any key", 320, 460);
				if (wait-- < 0 && key != "")
				{
					state = 0;
				}
			}
			key = "";
            if (score > high)
            {
                high = score;
            }

            g.dispose();
            bufferStrategy.show();

            try
            {
                Thread.sleep(50);
            }
            catch (Exception e)
            {
            }
        }
    }

    public void processKeyEvent(KeyEvent e)
    {
        if (e.getID() == java.awt.Event.KEY_RELEASE)
		{
			key += String.valueOf(e.getKeyChar());
		}
    }
}

