package ct.listeners.keylisteners;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.List;
import java.util.ListIterator;
import javax.swing.text.JTextComponent;

/**
* This class provides an action listener that suggests entries
* for a selected textbox from a given list of strings. Users can
* press the 'enter' key to allow the suggested item.
*
* @author ct
*/
public class TextSuggestionListener implements KeyListener
{
   private final static int  MAX_VALUE = 10000;
   private List<String>      m_items   = null;
   /**
   * set items that may be suggested in field
   * @param items all suggestable items. field is only allowed to contain
   * the amount of MAX_VALUE (10000 by default) items for performance issues
   */
   public void setItems(List<String> items){
      // ignore items that exceed the set maximum value
      if (items.size() > MAX_VALUE)
      {
         this.m_items = items.subList(0, MAX_VALUE);
      }
      this.m_items = items;
   }
   public void keyTyped(KeyEvent e) {
      // we don't need this one
   }
   public void keyPressed(KeyEvent e) {
      // we don't need this one
   }
   public void keyReleased(KeyEvent e) {
      JTextComponent txt = null;
      String         itm = null;
      int            len = 0;
      // key listener may only be applied to JTextComponents
      try
      {
         txt = (JTextComponent)e.getSource();
      }
      catch(Exception ex)
      {
         return;
      }
      // if text is empty don't suggest anything
      if (txt.getText().equals(""))
      {
         return;
      }
      // if enter key is pressed, set selection as fixed
      else if (e.getKeyCode() == KeyEvent.VK_ENTER)
      {
         txt.moveCaretPosition(txt.getText().length());
         return;
      }
      // if backspace or delete key is pressed, delete selection
      else if (e.getKeyCode() == KeyEvent.VK_DELETE ||
               e.getKeyCode() == KeyEvent.VK_BACK_SPACE)
      {
         txt.setText(txt.getText().substring(0, txt.getCaretPosition()));
         return;
      }
      // traverse through items
      for (ListIterator<String> itr = this.m_items.listIterator();
           itr.hasNext();)
      {
         itm = itr.next();
         // if item IS entered text, return
         if (itm.toLowerCase().equals(txt.getText().toLowerCase()))
         {
            return;
         }
         // if item starts with already entered text, fill suggestion
         // (ignoring text cases)
         else if (itm.toLowerCase().startsWith(txt.getText().toLowerCase()))
         {
            len = txt.getText().length();
            // remove part of string that was already entered by the user
            itm = itm.substring(len);
            // append text suggestion
            txt.setText(txt.getText() + itm);
            // select suggested text (from end to beginning of suggestion)
            // hereby the caret is moved to the beginning of the selection
            txt.setCaretPosition(txt.getText().length());
            txt.moveCaretPosition(len);
            break;
         }
      }
   }
}
