
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import javax.swing.JFileChooser;


/**
 * Word binary search
 * @author mitsunori ogihara
 *
 */
public class BinSearch {

	final static int AREA_WIDTH=70;
	final static int AREA_HEIGHT=40;
	
	/**
	 * Read all words and numbers appearing in a selected text file
	 */
	public static String[] getArr() {
		// let the user select a file suing file chooser
		JFileChooser jfc = new JFileChooser();
		if (jfc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
			File f1 = jfc.getSelectedFile();
			try {
				// use a buffered reader
				BufferedReader bf = new BufferedReader(new FileReader(f1));
				System.out.println("Opening file");
				// the words are initially placed in a linked list of Strings
				LinkedList<String> ll = new LinkedList<String>();
				while (true) {
					// read a line
					String line = bf.readLine();
					if (line==null) break;
					//System.out.println(line);
					StringBuilder sb = new StringBuilder();
					for (int i=0; i<line.length(); i++) {
						char c = line.charAt(i);
						// so long as the characters are a-z, A-Z, or 0-9, append to form a word
						if ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9')) {
							sb.append(c);
						}
						// when any other type character is encountered, save the word
						// and reset the string builder 
						else {
							if (sb.length()>0) {
								System.out.println("Word is "+sb.toString());
								ll.add(sb.toString());
								sb.delete(0,sb.length());
							}
						}
					}
					// at the end of file
					if (sb.length()>0) {
						System.out.println("Word is "+sb.toString());
						ll.add(sb.toString());
						sb.delete(0,sb.length());
					}
				}
				// create an array out of the list
				String[] arr = new String[ll.size()];
				ll.toArray(arr);
				HeapSort.sort(arr);
				return arr;
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
	/**
	 * Search main part
	 * @param w	the word to be searched
	 * @param arr	the array in which the owrd is stored
	 */
	public static void executeSearch(String w, String[] arr) {
		StringBuilder sb = new StringBuilder("Searching for " + w + "\n");
		
		int low = 0;	// the lower end point of the range, inclusive
		int high = arr.length;	// the higher end point of the range, exclusive
		boolean found = false;	// boolean value to indicate whether word is found
		while (!found && low+1<high) {
			int mid = (low+high)/2;
			sb.append("Range is ["+low+", "+high+"), probe:"+mid+"; word=" + arr[mid] + "\n");
			int res = arr[mid].compareTo(w);
			if (res==0) found = true;
			else if (res>0) high = mid;
			else low = mid+1;
		}
		if (found) sb.append("The word " + w + " was found.\n");
		else sb.append("The word " + w + " was not found.\n");
		JTextArea jta = new JTextArea(AREA_HEIGHT,AREA_WIDTH);
		jta.append(sb.toString());
		JScrollPane sp = new JScrollPane(jta);
		JOptionPane.showMessageDialog(null, sp);
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		String[] arr = getArr();
		while (true) {
			String w = JOptionPane.showInputDialog("Type a word for search. Empty word to quit.");
			if (w==null) break;
			if (w.length()==0) break;
			executeSearch(w, arr);
		}
	}

}
