import static java.lang.System.out; // Lazy
import static java.lang.System.err; // Lazy
import java.io.*; // Lazy
import java.util.Scanner;

/**
 * PalidromeChecker
 * Provides a palidrome checking function.
 * Also a few sample tests available.
 * 
 * By Philip Peng
 * For Mr. Benum
 * 2007/12/05
 */

public class PalindromeChecker {

	public static void main(String[] args) {

		// Intro
		out.println("===================");
		out.println(" Palidrome Checker");
		out.println("===================");
		
		// Debugging
		try {
			File log = new File("debug.log");
			log.createNewFile();
			FileOutputStream os = new FileOutputStream(log);
			PrintStream ps = new PrintStream(os);
			System.setErr(ps);
		} catch (IOException e) {
			err.println("Error: Unable to create debug.log file.");
		}
		
		// Input
		Scanner input = new Scanner(System.in);
		String buffer;
		
		// Keep asking
		while (true) {
			
			// Ask
			out.println("Please input a phrase for checking or \"q\" to exit:");
			out.print("> ");
			buffer = input.nextLine();
			
			/*
			// Note: To use these samples, it'd be a good idea to comment out the "while" loop. 
			
			// Short samples:
			
			buffer = "Now sir, away! A papaya war is won!";
			buffer = "tattarrattat";
			
			// Long sample:
			
			File f;
			
			// Don't even try this one.
			// Will cause a stack overflow; not sure about how big the stack needs to be.
			// From http://norvig.com/pal1txt.html
			f = new File("15139-Word-Palindrome.txt");
			
			// This one is attempt-able.
			// Creates a 232 KB debug.log file.
			// From http://www.demetrimartin.com/index.swf
			f = new File("Dammit-I'm-Mad.txt");
			
			// Add to buffer;
			buffer = "";
			try {
				out.println("Checking with file: " + f.getName());
				Scanner fs = new Scanner(f);
				while (fs.hasNextLine()) {
					buffer += fs.nextLine();
				}
			} catch (java.io.FileNotFoundException e) {
				err.println("Test file \"" + f.getName() + "\" not found.");
			}
			*/
			
			// Quit
			if (buffer.equalsIgnoreCase("q")) {
				out.println("  Exiting...");
				System.exit(0);
			}
			
			// Palidrome check
			else {
				err.println("===================");
				err.println(" Checking: " + buffer);
				err.println("===================");
				if (checkPalidrome(cleanPhrase(buffer))) {
					out.println("  Inputted phrase is a palidrome.");
				} else {
					out.println("  Inputted phrase is not a palidrome.");
				}
			}
			
		} // Inf. loop
		
	} // Main
	
	
	private static String cleanPhrase(String word) {

		// Generate new cleaned String via StringBuilder
		StringBuilder wordClean = new StringBuilder();
		
		// Go through each letter of original word,
		// adding to StringBuilder if it's a character
		for (int i = 0; i < word.length(); i++) {
			if (Character.isLetter(word.charAt(i))) {
				wordClean.append(word.charAt(i));
			}
		}
		
		// Return cleaned String
		return wordClean.toString();
		
	} // cleanPhrase
	
	private static boolean checkPalidrome(String word) {
		
		// Info is printed to error stream for logging
		err.println("> Word: " + word);
		err.println("  Length: " + word.length());
		
		// No phrase or single letter
		if ( (word.length() == 0) || (word.length() == 1) ) {
			err.println("  Return: True");
			return true;
		} else
			
		// Compare both ends
		if ( Character.toUpperCase(word.charAt(0))
				== Character.toUpperCase(word.charAt(word.length()-1)) ) {
			
			err.println("  Comparing: " + Character.toUpperCase(word.charAt(0))
					+ " to "
					+ Character.toUpperCase(word.charAt(word.length()-1))
					);
			
			// Just two matching letters
			if (word.length()==2) {
				err.println("  Return: True");
				return true;
				
			// Recursively call self with word truncated at both ends
			} else {
				err.println("  Call self with: " + word.substring(1,word.length()-1));
				return checkPalidrome(word.substring(1,word.length()-1));
			}
			
		// No match
		} else {
			err.println("  Return: False");
			return false;
		}
		
	} // checkPalidrome

} // PalidromeChecker class
