/*
 * Dictionary.java
 *
 * Created on October 13, 2002, 12:53 PM * Updated Feb. 11 2003
 *
 * Build a dictionary of words and translations.
 * Reads from file given: default = words.txt
 * File assumed to have following format:
 * <b>
 * word type translation
 * </b><br>
 * 
 * For now, the dictionary is just a sequential list, alphabetically
 * sorted.
 */

/**
 *
 * @author  becker
 * @version 1.0
 */
import java.io.*;
import java.util.*;

public class Dictionary {
   
   public static final int NONE = -1;
   public static final int ANY = 0;
   public static final int ENGLISH = 1;
   public static final int LATIN = 2;   
   /** remembers where in the dictionary the last word was found    *  - this gives us the ability to continue a search from a     *  specified point
    */   int lastLocation = 0;
      /** List containing English words
    */
   Vector EList = new Vector(); // English words
   int ec = 0; // count
   public int englishWordCount() {return ec; }   /** List containing Latin words
    */
   Vector LList = new Vector(); // Latin words
   int lc = 0; // count   public int latinWordCount() {return lc; }

   /** Creates new Dictionary from default file called: "words.txt" */
   public Dictionary()
      throws IOException 
   {
      load("words.txt");
   }

   /** Creates new Dictionary from specified file */
   public Dictionary(String fileName)
      throws IOException 
   {
      load(fileName);
   }

   /** load up the dictionary.
    *  read: word - type - translation 
    *  this will make 2 entries: one entry in each list
    *  We are assuming the file is error free!
    */
   public void load(String fileName)
      throws IOException
   {
      String line, se, st, sl;
      int i,j,count = 0;
      Word w;
            // open the file
      try {
         BufferedReader in =                    new BufferedReader(new FileReader(fileName));
         System.out.print("File " + fileName + " open.\n\n");
         
         // read to end of file         while (true) {
            line = in.readLine();
            if (Debug.isSet())
               System.out.print("Line " + count + " is: " + line + "\n");                  // allows for comments and empty lines in the file      
	         // if this line is empty, we're done
            if (line == null) break;
	         // if this line is a comment, skip it
            if (line.charAt(0) == '/') {
               if (Debug.isSet())
                  System.out.print("     skipping this line\n");
               continue;
            }
            // get English word: Assume it's first on the line
            i = 0; j = line.indexOf(' ');
            se = line.substring(i,j);
            // get the type
            i = j+1;
            j = line.indexOf(' ',i);
            st = line.substring(i,j);
            // get the Latin word
            i = j+1;
            j = line.length();
            sl = line.substring(i,j);
            if (Debug.isSet())
               System.out.print("Got: " + se + ", " + st + ", " + sl + "\n");            
            // add it to the dictionary
            w = new Word(se,Word.checkType(st),sl);
            add(w);
            
            count++;
         }// end while
         
         // REPORT
         System.out.print("Loaded " + count + " words.\n\n");
         
      } // end try
      /** we go here when we get to end of file */
      catch (EOFException E) {
         System.out.print("Read " + count + " words.\n\n");
      }
      catch (FileNotFoundException E) {
         System.out.print("Bad File Name: " + fileName + "\n\n");
         throw E;
      }
      catch (IOException E) {
         System.out.print("Read Error: " + E + "\n\n");
         throw E;
      }
   } // load
   
   
   /** add a word to the dictionary, sorted alphabetically */
   public void add(Word w) {
      int i = 0;
      Word w2, eWord,lWord;
      
      // put it in the English part
      if (Debug.isSet())
         System.out.print("Adding: " + w.toString() + "\n");
      if (ec > 0) {
         do {
            eWord = (Word)EList.elementAt(i++);   
         } while ((w.toString().compareTo( eWord.toString()) < 0)
                  && (i < ec));
      }   
      EList.insertElementAt(w, i);
      ec++;
      
      // put it in the Latin part
      i = 0;
      w2 = new Word(w.Translation().toString(),w.Type(),w.toString());
      if (Debug.isSet())
         System.out.print("Adding: " + w2.toString() + "\n");
      if (lc > 0) {
         do {
            lWord = (Word)LList.elementAt(i++);
         } while ((w2.toString().compareTo( lWord.toString()) < 0)
                  && (i < lc)); 
      }
      LList.insertElementAt(w2, i);
      lc++;
   } // add
   /** return the next word in the list
    */
   public Word next(int lang) {      if (lang == ENGLISH){        lastLocation = (lastLocation < ec)? lastLocation+1 : 0;
        return (Word)EList.elementAt(lastLocation);
      }      else {
         lastLocation = (lastLocation < lc)? lastLocation+1 : 0;
         return (Word)LList.elementAt(lastLocation);      }
   }
   
   //==============================================================
   /** find a word in the English dictionary starting with a Word*/
   public Word find(Word w) {
      return find(w.toString(),ENGLISH);
   } // find
   
   /** find a word in the English dictionary starting with just a string*/
   public Word find(String S) {
      return find(S,ENGLISH);
   } // find

   /** find a word in the specified dictionary */
   public Word find(Word w, int lang) {
      return find(w.toString(),lang);
   } // find   
   /** find a word in the specified dictionary, given a string */
   public Word find(String s, int lang) {
      return find(s,0,lang);    } // find    
   /** find a word in the specified dictionary starting after word given */
   public Word find(Word w, int lang, Word start) {
      Word first = find(start.toString(),lang);      return find(first.toString(), lastLocation++, lang);
   } // find
   
   /** find a certain kind of word in the specified dictionary,    *  given a string */
   public Word find(int kind, String s, int lang) {
      Word w = find(s,0,lang);
      while((w != null)&&(w.Type() != kind))
         w = find(w.toString(), lastLocation++, lang);
      return w;    } // find      
   /** find a string in the specified dictionary    *  starting at the specified location,    *  given a string */
   public Word find(String s, int first, int lang) {
      Vector V;
      int i = 0;      
      if (lang == ENGLISH)
         V = EList;
      else // LATIN
         V = LList;      
      if ((first > 0)&&(first < V.size())) i = first;
      
      while ((i < V.size())&&(!s.equals(V.elementAt(i).toString()))){
         i++;
      }
      if ((i < V.size())&&(s.equals(V.elementAt(i).toString()))){         lastLocation = i;
         return (Word)V.elementAt(i);      }
      else {         lastLocation = -1;
         return null;      }      
   } // find
}
