/************************************************************************************
 * Hangman's Noose Server                                                           *
 *  Provides service to let one player join game                                    *
 *  Selects word from a large dictionary                                            *
 *  Monitors game                                                                   *
 *                                                                                  *
 * Charles E. Hughes -- October 14, 2000                                            *
 ************************************************************************************/
import java.io.*;
import java.net.*;
import java.awt.*;

public class Server {
	private ServerSocket server;		// player connect through this socket
	private Socket player;			// socket to communicate with connected player
	private DataInputStream input;	// input stream associated with player socket
	private DataOutputStream output;	// output stream associaeted with player socket

	// Constructor -- starts up service
	public Server() {
		try {
			server = new ServerSocket(6000, 1 );	// port 6000, one player
			player = server.accept();	// await the player; create player socket
			server.close();		// close service since only a one player game
			// create input and output streams for player communication
			input = new DataInputStream(player.getInputStream());
			output = new DataOutputStream(player.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	// select a word randomly for a large dictionary
	public String choose() {
		String word = "";
		try {
			RandomAccessFile wordFile = new RandomAccessFile("words.txt", "r");
			long pos = (long) (Math.random() * (wordFile.length() - 11));
			wordFile.seek(pos);
			wordFile.readLine();
			word = wordFile.readLine().toUpperCase();
			wordFile.close();
		} catch (IOException e) {
			System.out.println("Error -- " + e.toString());
			System.exit(1);
		}
		return word;
	}

	// build coded message sent back to player
	// this tells player where correct guesses belong in word
	// return true if player has won
	public boolean buildCode(String word, char letter, char[] codedWord) {
		boolean ok = false;
		boolean win = true;
		for (int i = 0, j = 2; i < word.length(); i++, j += 2 ) {
			if ((word.charAt(i)) == letter) {
				codedWord[j] = letter;	// fill in correct choice
				ok = true;
			} else if (codedWord[j] == '_') {
			    win = false;				// at least one letter not yet found
			}
		}
		if (ok) System.out.println("Good Guess!!!");
		else System.out.println("Bad Guess!!!");
		return win;
	}

	// this is where the real action occurs
	public void execute() {
		try {
			int badGuesses = 0;		// no bad choices yet
			String word = choose(); 	// the magic word

			// false components of usedChars represent potential new bad guesses
			boolean usedChars[] = new boolean[26];
			// make all componenest false
			for (int i=0; i<26; i++) {
				usedChars[i] = false;
			}
			// change those associated with letters in word to true
			// they're not bad guesses
			for (int i=0; i < word.length(); i++) {
				usedChars[word.charAt(i)-'A'] = true;
			}

			// coded word
			// 	codedWord[0] = 	char version of #of bad guesses
			//	codedWord[1] = 	'P' if continue play
			//				'W' if player has won
			//				'L' is player has lost
			//	rest of codedWord indicates letters guessed correctly
			char[] codedWord = new char[22];
			codedWord[0]='0';
			codedWord[1]='P';
			for (int j = 2; j < 22; j++) {
				codedWord[j]=' ';
			}
			for (int i = 0, j = 2; i < word.length(); i++, j += 2 ) {
				codedWord[j]='_';
			}

			// send string version of coded word to player
			String temp = new String(codedWord, 0, 22);
			System.out.println(temp + " - " + word);
			output.writeUTF(temp);	// actual write on socket

			// play the game
			boolean win = false;
			// game goes until win or loss
			while (!win && (badGuesses < 6)) {
				// get user letter choice, update badGuesses, if needed
				System.out.println("Pick a letter: ");
				char guess = Character.toUpperCase((char) input.readByte());
				if (!usedChars[guess-'A']) {
					usedChars[guess-'A'] = true;
					badGuesses++;
				}
				// build code word, checking for a winner
				win = buildCode(word, guess, codedWord);
				codedWord[0] = (char) ('0'+badGuesses);
				if (win) {
					System.out.println("You win!!!");codedWord[1]='W';
				} else if (badGuesses >= 6) {
					System.out.println("You lose!!!");codedWord[1]='L';
				}
				// send code word back to player
				temp = new String(codedWord, 0 ,22);
				System.out.println(temp + " - "+word);
				output.writeUTF(temp);
			}
			// be a good citizen, closing all open streams and sockets
			input.close();
			output.close(); // this is real important since it flushes stream
			player.close();
		} catch (IOException e) { e.printStackTrace();}
	}


	// create server and start it up
	public static void main(String[] args) {
		Server hangman = new Server();
		hangman.execute();
	}
}
