/**
* @JSearch2.java
* @version     0.1, 13 July 2000
* @developer: Lawrence L. Jett, Jr
*/

import java.awt.*;
import java.applet.*;
import java.util.*;
import java.io.*;
import java.net.*;

/**
 * The Applet.
 */
public class JSearch3 extends Applet
 {
  private TextArea resultsTA;
  private TextField searchKeysTF;
  private Button searchBT;
  private Panel fieldsPanel;
  private Panel resultsPanel;

  private String fieldSeparatorCharacter;
  private String fieldNames;
  private String urlOfDataFile;
  private Vector dataLinesVector;
  private Vector fieldsVector;
  private String eightyBlanks;
  private int currentFocus;
  private Vector tabOrderVector;

  public void start()
   {
    Enumeration enum;
    String backgroundColor;
    String foregroundColor;
    String currentToken;
    eightyBlanks =  "                                                                                          ";

    dataLinesVector = new Vector(250);
    fieldsVector = new Vector(30);
    tabOrderVector = new Vector(30);
    searchBT = new Button("Search Database");

    super.init();

    //fieldsPanel will hold the N number of TextFields specified in the HTML code
    fieldsPanel = new Panel();
    fieldsPanel.setLayout( new FlowLayout(FlowLayout.LEFT) );
    //resultsPanel has a TextArea at bottom and a label at top that serves as a
    //column heading
    resultsPanel = new Panel();
    resultsPanel.setLayout( new BorderLayout() );

    resultsTA = new TextArea();
    resultsTA.setEditable(false);

    //Need to use a Font with all the letters the same size, so that our
    //resutls will line up into columns
    setFont(new Font("Helvetica", Font.BOLD, 14) );

    //Get the parameters specified in the APPLET tag of the HTML
    fieldSeparatorCharacter = getParameter("fieldSeparatorCharacter");
    fieldNames = getParameter("fieldNames");
    urlOfDataFile = getParameter("UrlOfDataFile");
    backgroundColor = getParameter("backgroundColor");
    foregroundColor = getParameter("foregroundColor");

    //Change our foreground, and background color to the ones specified
    int backRed   = (Integer.valueOf(backgroundColor.substring(0,2),16) ).intValue();
    int backGreen = (Integer.valueOf(backgroundColor.substring(2,4),16) ).intValue();
    int backBlue  = (Integer.valueOf(backgroundColor.substring(4,6),16) ).intValue();
    int foreRed   = (Integer.valueOf(foregroundColor.substring(0,2),16) ).intValue();
    int foreGreen = (Integer.valueOf(foregroundColor.substring(2,4),16) ).intValue();
    int foreBlue  = (Integer.valueOf(foregroundColor.substring(4,6),16) ).intValue();
    setForeground(new Color(foreRed, foreGreen, foreBlue) );
    setBackground(new Color(backRed, backGreen, backBlue) );

    loadFieldParameters();  //Load in field names/length from Applet param,
                            //and create "Field" objects and add it to screen.

    readDataUrl();          //Read in the data from URL supplied in Applet
                            //parameter and save in string Vector.

    fieldsPanel.add( new Label("   ")); //ensure some whitespace
    fieldsPanel.add(searchBT);
    tabOrderVector.addElement(searchBT);       //Search button is last in tab order

    resultsPanel.add("Center", resultsTA);

    if ( fieldsVector.size() > 1)
      {
       //Set GridLayout so that our FlowLayout Panel with the N number of TextFields will
       //wrap instead of being its "preffered" size, which is all components on one line.
       setLayout( new GridLayout(2,1) );
       add(fieldsPanel);
       add(resultsPanel);
      }
    else
      {
       //Set BorderLayout so that our FlowLayout Panel with the 1 TextFields will
       //be at "North" allowing the rest of the space for the results TextArea.
       setLayout( new BorderLayout() );
       add("North", fieldsPanel);
       add("Center",resultsPanel);
      }

    //Put cursor in first TextField, and init our tab tracker
    ((Field)fieldsVector.elementAt(0)).fieldTextField.requestFocus();
    currentFocus = 0;
   }

  public void stop()
   {
    removeAll();
   }

 /**
  * Create A "Field" object for each field name supplied in the applet parms.
  */
  public void loadFieldParameters()
   {
    String fieldName;
    Integer fieldLength;
    Field tmpField;

    //Load field names from Applet parameter into a Vector
    StringTokenizer t;
    t = new StringTokenizer(fieldNames, ",");
    while(t.hasMoreTokens() )
     {
       fieldName = t.nextToken();
       fieldLength = Integer.valueOf(t.nextToken());
       tmpField = new Field( fieldName, fieldLength.intValue());
       fieldsVector.addElement(tmpField);
       fieldsPanel.add(tmpField.fieldPanel);
       tabOrderVector.addElement(tmpField.fieldTextField);
     }
   }

 /**
  * Read in data from URL provided
  * Load each line into a Vector of strings for later searching.
  */
  public void readDataUrl()
   {
    Enumeration enum;
    URL fileURL = null;
    InputStream  input = null;
    DataInputStream dataInput = null;
    String inputLine = null;
    boolean moreRecords = true;

    try {
         fileURL = new URL(urlOfDataFile);
        }
    catch (MalformedURLException e)
        { resultsTA.appendText("Data file URL given is bad: Error MalformedURLException");}

    try {
         input = fileURL.openStream();
         dataInput = new DataInputStream(input);
        }
    catch ( IOException e) { resultsTA.appendText("Data file URL not opened correctly");}

    while (moreRecords)
    {
     try {
          inputLine = dataInput.readLine();
          if ( inputLine == null) { moreRecords= false; break; }
          if ( inputLine.indexOf("<") < 0   &&
               !inputLine.equals("")  )
           {
             dataLinesVector.addElement(inputLine);
           }
         }
     catch ( IOException e) { resultsTA.appendText("Data file URL not read correctly"); }
    }
    try { dataInput.close(); }
    catch ( IOException e) { resultsTA.appendText("Error closing data file URL "); }
 }

 /**
  * Search through Vector of Strings holding raw input lines.
  * breaking each line into fields and comparing each field against its
  * the contents of its corresponding TextField input.
  */
  private void doSearch()
   {

    StringTokenizer t;
    Enumeration linesEnum;
    Enumeration fieldsEnum;
    Vector fieldsInDataLineVector;
    String currentDataLine;
    String currentText;
    String currentToken;
    String workStr = "";
    String resultLine ="";
    boolean gotHit;
    boolean noneFound;
    String currentElement;

    searchBT.disable();
    noneFound = true;
    resultsTA.setText("");
    linesEnum = dataLinesVector.elements();

    // Get each line of data and break it up into fields.  Save the fields
    // in a vector- then compare whats in field 1 to what was entered in
    // TextField 1 on the screen, and so on for all fields.
    while (linesEnum.hasMoreElements())
     {
      resultLine = "";
      gotHit = true;
      currentDataLine = (String)linesEnum.nextElement();
      fieldsInDataLineVector = new Vector(30);
      //Break string into tokens including separator char back as tokens
      t = new StringTokenizer(currentDataLine, fieldSeparatorCharacter,true);
      // We get back "item" "sep-char" "item" "sep-char" ....
      for ( int i=0; i < fieldsVector.size(); i++ )
       {
        currentElement = "";          //Default to no
        if (t.hasMoreTokens())                       // If not at end of line
         {
          currentElement = (String)t.nextElement();
          // If two separator characters in a row this item is blank
          if ( currentElement.startsWith(fieldSeparatorCharacter) )
           currentElement = "";
          else
           {
            if (t.hasMoreTokens())                         // If not at end of line
               t.nextElement();                            // Eat the separator character
           }
         }
        fieldsInDataLineVector.addElement(currentElement);
       }
      for ( int i=0; i < fieldsVector.size(); i++ )
       {
        currentText =  ((Field)fieldsVector.elementAt(i)).fieldTextField.getText();
        currentToken = (String)fieldsInDataLineVector.elementAt(i);
        currentText =  currentText.toLowerCase();
        currentToken = currentToken.toLowerCase();
        if ( !(currentText.equals("")) &&
             currentToken.indexOf(currentText) < 0  )
           gotHit = false;
       }
      if (gotHit)
       {
        noneFound = false;
        for ( int i=0; i < fieldsVector.size(); i++ )
         {
          workStr = (String)fieldsInDataLineVector.elementAt(i);
          //If data field is less than display length pad it with blanks
          if ( workStr.length() < ((Field)fieldsVector.elementAt(i)).fieldLength )
            {
             workStr = workStr +
             eightyBlanks.substring(0,
                                      ((Field)fieldsVector.elementAt(i)).fieldLength -
                                       workStr.length());
             workStr = workStr + "\n";
            }
          //If data field is >=less than display length truncate it.
          else
           {
            if ( fieldsVector.size() > 1) //Don't truncate if only 1 field
             {
              workStr = workStr.substring(0,((Field)fieldsVector.elementAt(i)).fieldLength);
              workStr = workStr + "\n";
             }
           }
          resultLine = resultLine + workStr;
         }
        resultsTA.appendText(resultLine + "------------------------------------------\n");
       }
     }
     if (noneFound) resultsTA.appendText("*** No matches Found ***\n");
     else  {
            resultsTA.insertText("!",0);     //Insert at beginning to put scroll bar
            resultsTA.replaceText("",0,1);   //back at top of TextArea-then blank it out
           }

    searchBT.enable();
   }

/**
 *
 */
 public boolean action (Event e, Object o)
  {
     if ( e.target instanceof Button )
     {
      if (e.target == searchBT)
       {
        doSearch();
       }
     }
   return false;
  }

/**
 *
 */
  public boolean keyDown(Event e, int key)
   {
    // If tab key hit move the cursor amongst the TextFields
    if ( key == '\t')          // Tab key hit
     {
      if ( e.shiftDown())     //Shift was down
       {
        currentFocus--;
        if (currentFocus < 0 ) currentFocus = tabOrderVector.size() -1;
       }
      else
       {
        currentFocus++;
        if (currentFocus > (tabOrderVector.size() -1) ) currentFocus =0;
       }
      ((Component)tabOrderVector.elementAt(currentFocus)).requestFocus();
     }

    if ( key == Event.ENTER)
     {
      doSearch();
      currentFocus =0;
      ((Component)tabOrderVector.elementAt(currentFocus)).requestFocus();
     }
    return false;
   }

/**
 */
 public boolean handleEvent(Event evt)
  {
    return super.handleEvent(evt);
  }
}

