/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.prescription.gui.widgets.toolkit.searchbox;


import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.PlainDocument;

import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.prescription.ejb.entity.dataclasses.DrugLight;
import lu.tudor.santec.gecamed.prescription.gui.PrescriptionIcons;
import lu.tudor.santec.gecamed.prescription.gui.util.IResultListener;
import lu.tudor.santec.gecamed.prescription.gui.util.NewDrugWorker;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Logger;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;


/**
 * This class is a textfield which has functionality to show
 * search results in a JList, placed into a popup right under the
 * textfield.
 * The search is triggered on the fly by typing letters into the
 * textfield.
 *
 * The init method must be called explicitly!
 *
 * @author Martin Heinemann martin.heinemann@tudor.lu
 *
 */
public class SearchBox extends JPanel implements IResultListener, FocusListener{

	
	/*
	 * This class is to complex to explain it now. I am not able to reproduce the logic that
	 * is behind this. Its very early code. It might be faster to rewrite it as to
	 * understand whats happening. So, good luck if you want to change something.
	 * 
	 */
	
	
	
	private static final long serialVersionUID = 1L;

	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(SearchBox.class.getName());

	/* ----------Default values  - --------------------*/
    private final int SEARCHOFFSET = 2;

    private int textfieldSize = 20;
    private String labelText = Translatrix.getTranslationString("SearchBox.searchLabel"); //$NON-NLS-1$
    private int searchOffset = SEARCHOFFSET;

    private SearchBoxPopup popup;
    private JTextField searchTextField;
    private JLabel     searchLabel;

    // Object from which the suggestion-data comes from
    private ISearchBoxLookUp gatherer = null;
    // Thread which is doing the lookup
    private SearchBoxLookupThread gatherThread;


    // Set of all the components which wants to recieve the selected
    // object
    private Set<IResultListener> targets = new TreeSet<IResultListener>();


    private boolean isInsertAction = false;
//    private int lastNumberOfResultsFound = 0;

    /**
     * This variable will store the actual selected object
     */
    public Object currentSelectedObject = null;

    private JButton drugInfoButton;

	protected boolean blockFireresult = false;

	private ComponentEvent lastEvent;

	private Vector<FocusListener> focusListeners  = new Vector<FocusListener>();


    /**
     * Waiting for further configuration
     * initComponent() must be called manually
     */
    public SearchBox() {
        logger.debug("Enter/Leave constructor"); //$NON-NLS-1$
        // Waiting for further configurations
        // -> no initComponent
    }
    /* --------------------------------------------------------------------------- */
    /* *************************************************************************** */


    /* *************************************************************************** */
    /*                   initComponent                                             */
    /*                                                                             */
    /**
     * Initialises the GUI components and places them on the JPanel
     */
    public void initComponents() {
    	/* ================================================== */
    	this.setLayout(new FormLayout("fill:pref:grow","fill:pref:grow")); //$NON-NLS-1$

        CellConstraints cc = new CellConstraints();

        /* ------------------------------------------------------- */
        // Label
        /* ------------------------------------------------------- */
        searchLabel= new JLabel(this.labelText);
        searchLabel.setName("searchFieldLabel"); //$NON-NLS-1$
        // TextField
        searchTextField  = new JTextField(this.textfieldSize);
        searchTextField.setName("searchTextField"); //$NON-NLS-1$
        // Anchor Label -> TextField
        searchLabel.setLabelFor(searchTextField);
        this.searchTextField.setDocument(new SearchBoxDocument());
        // KeyListener for TextField
        this.searchTextField.addKeyListener(new SearchBoxKeyListener());
        this.searchTextField.addFocusListener(this);

//        this.add(this.searchLabel, cc.xy(2, 2));
//        this.add(this.searchText, cc.xy(4, 2));
        this.add(this.searchTextField, cc.xy(1, 1));

        this.drugInfoButton = new JButton();
        drugInfoButton.setIcon(PrescriptionIcons.getMiniIcon(PrescriptionIcons.DRUG_INFO));
        drugInfoButton.setPreferredSize(new Dimension(20, 20));
        drugInfoButton.setFocusable(false);

//        this.add(drugInfoButton, cc.xy(6, 2));

        initButtonListener();
//        initDrugInfoWindow();

        // Show Panel
        //this.setVisible(true);
        // must be called by the parent panel/frame

        // Popup
        this.popup = new SearchBoxPopup(this.searchTextField);
        /* The popup is not focusable. All the key interactions are handled
         * by the SearchBox KeyListener
         */
        this.popup.setFocusable(false);

        /* ------------------------------------------------------ */
        // set the mouselistener for the popup menu
        this.popup.addMouseListener(new MouseListener() {

			public void mouseClicked(MouseEvent e) {
				/* ============================================= */
				if (popup.isVisible()) {
				    isInsertAction = true;
					searchTextField.setText(
		                    SearchBox.this.popup.getListRenderer()
		                        .getStringForTextField(
		                                SearchBox.this.popup.getSelectedItem()));

		            // save the found object in a variable
		            SearchBox.this.currentSelectedObject = SearchBox.this.popup.getSelectedItem();

					popup.setVisible(false);
					if (!blockFireresult)
						fireResultFound();
				}
				/* ============================================= */
			}
			public void mousePressed(MouseEvent e) {}
			public void mouseReleased(MouseEvent e) {}
			public void mouseEntered(MouseEvent e) {}
			public void mouseExited(MouseEvent e) {}

        });
        /* ------------------------------------------------------ */

        this.searchTextField.addFocusListener(new FocusListener() {

            public void focusGained(FocusEvent e) {}

			public void focusLost(FocusEvent e) {
                popup.setVisible(false);
                lastEvent = e;
//                fireSearchByKeyEvent(new KeyEvent(searchTextField,1,(long) 0.1,1,KeyEvent.VK_3));
                fireSearchByKeyEvent(null);
                fireFocusLost();
//                if (!blockFireresult)
//                	fireResultFound();
            }
        });


    }


    /**
     * Inform focus listeners that the textfield has lost the focus
     */
    private void fireFocusLost() {
    	/* ================================================== */
    	for (FocusListener l : this.focusListeners)
    		l.focusLost(null);
    	/* ================================================== */
    }
    
    /**
     * Inform focus listeners that the textfield has gained the focus
     */
    private void fireFocusGained() {
    	/* ================================================== */
    	for (FocusListener l : this.focusListeners)
    		l.focusGained(null);
    	/* ================================================== */
    }
    
    
    @Override
    public void addFocusListener(FocusListener l) {
    	/* ================================================== */
    	this.focusListeners.add(l);
    	/* ================================================== */
    }
    
    /* --------------------------------------------------------------------------- */
    /* *************************************************************************** */




    /**
     * Inits the actionlistener for the drug info button
     */
    private void initButtonListener() {
        /* =============================================================== */

        this.drugInfoButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                /* =========================================================== */
                showDrugInfoWindow();
                /* =========================================================== */
            }

        });

        /* =============================================================== */
    }

    /**
     * Opens the DrugBrowser window
     */
    private void showDrugInfoWindow() {
        /* =============================================================== */
    	// TODO
//    	System.out.println("TODO, open drug browser, SearchBox::showDrugInfoWindow");
//        Object data = null;
//        if (this.currentSelectedObject != null) {
//            data = this.currentSelectedObject;
//        } else
//            data = new String(searchText.getText());

        // PrescriptionWorker
//        PrescriptionWorker pWorker = new PrescriptionWorker();
//
//        Collection<DrugLight> result = pWorker.openDrugBrowser(data, this,
//        					this.drugBrowserDrugListener);
//        /* ---------------------------------------------------------------- */
//        if (result != null && result.size() > 0) {
//        	/* ---------------------------------------------------------------- */
//        	// if there is more than one results
//        	// use the first one for the current container
//        	this.searchText.setText(((DrugLight) result.toArray()[0]).getName());
////
//        	this.fireSearchThreadAfterDrugBrowser();
////        	this.currentSelectedObject = this.popup.getSelectedItem();
//        	fireResultFound();
//        	// the rest is send to the IResultListener
//        	if (result.size() > 1) {
//        		// remove the first on
//        		result.remove(result.toArray()[0]);
//        		// and notify the listener
//        		this.drugBrowserDrugListener.receiveResult(result.toArray());
//        	}
////        	/* ---------------------------------------------------------------- */
//    	}
//        	else
//    		/* ---------------------------------------------------------------- */
//    		this.searchText.setText((String) data);
//        /* ---------------------------------------------------------------- */
//        fireResultFound();
        /* ---------------------------------------------------------------- */

//        DrugBrowser.getInstance().setDrug(data);
//        DrugBrowser.getInstance().setResultListener(new IResultListener() {
//
//            public void receiveResult(Object data) {
//                /* =========================================================== */
//                    if (data instanceof DrugLight) {
//                        SearchBox.this.searchText.setText(((DrugLight) data).getCefipName());
//                        SearchBox.this.fireSearchThread();
//                    } else
//                        SearchBox.this.searchText.setText((String) data);
//                     fireResultFound();
//
//                /* =========================================================== */
//            }
//
//        });
//
//        // get the parent dialog or frame
//        // from the back through the thorax right in the eye
//        Component currComp = this.getParent();
//
//        while (currComp != null) {
////        	currComp.getClass().getName();
////        	if (currComp.getParent().getClass().getName().equals("javax.swing.JDialog")) {
//        	if (currComp instanceof JDialog) {
//        		break;
//        	} else if (currComp instanceof JFrame) {
////        		if (currComp.getParent().getClass().getName().equals("javax.swing.JFrame")) {
//        		break;
//        	} else
//        		currComp = currComp.getParent();
//        }
//        DrugBrowser.getInstance().setVisible(true,
//        			(Window) WindowToolbox.getOwnerFrame(this),
//        			true);
        /* =============================================================== */
    }


    /* *************************************************************************** */
    /*                   fireResultFound                                           */
    /*                                                                             */
    /**
     * Sends the found data to the registered listeners
     *
     * @param data
     */
    public void fireResultFound() {
    	Object data = null;

        if (popup.isVisible())
            // hmm, we can't get here for now
            try {
                data = popup.getSelectedItem();
            } catch (Exception e) {
                e.printStackTrace();
                data = searchTextField.getText();
            }
        else {
            /*
             * When we got here, the popup is not visible and the enter event
             * was fired on the JTextfield.
             * So the ResultListeners must obtain the last selcted object from
             * the list.
             * If there is no selected object just return the string from the text
             * field
             */
            if (this.currentSelectedObject != null) {
                data = this.currentSelectedObject;
            } else
                data = new String(searchTextField.getText());
        }

		for (IResultListener t : this.targets) {
			t.receiveResult(data);
		}
        isInsertAction = false;

    }
    /* --------------------------------------------------------------------------- */
    /* *************************************************************************** */


    /* *************************************************************************** */
    /*                   fireSearchThread                                          */
    /*                                                                             */



    /**
     * gathers the related information from the SearchBoxDrugGatherer and
     * pushes them to the Popup
     * Afterwards the focus must be brought back to the TextField to be able
     * to type ahead to granulate the match -list
     */
    public void fireSearchThread() {
        logger.debug("Enter fireSearchThread"); //$NON-NLS-1$
        //      if gatherer is not set, there will be no auto suggestion!
        if (gatherThread != null)
            try {
            gatherThread.interrupt();
            } catch (Exception e) {
            	e.printStackTrace();
            }

        /* No lookup if the last search returned without any results
         *
         * if the list of the popup is emtpy and the textField has more than
         * the given offset characters
         */

        /* ====================================================== */
            //  not really
		/* ====================================================== */

//        if ((popup.getListSize() <= 1) && (this.searchText.getText().length() > searchOffset)) {
////                && (this.searchText.getText().length() >= lastNumberOfResultsFound)) {
//            logger.finer("Leave fireSearchThread - last search was empty"); //$NON-NLS-1$
//            // reset the selectedObject
//            this.currentSelectedObject = null;
//            return;
//        }
//        System.out.println("DB Lookup -----");

        /*
         * Else if the last Result wasn't empty, just do another lookup
         */

        if (gatherer != null) {
            gatherThread = new SearchBoxLookupThread(
                    gatherer, searchTextField, popup, searchOffset);
            logger.debug("Start new search thread"); //$NON-NLS-1$
            gatherThread.start();
            logger.debug("New search thread started"); //$NON-NLS-1$
        }
    }


    public void fireSearchThreadAfterDrugBrowser() {
        logger.debug("Enter fireSearchThread"); //$NON-NLS-1$
        //      if gatherer is not set, there will be no auto suggestion!
        if (gatherThread != null)
            try {
            gatherThread.interrupt();
            } catch (Exception e) {e.printStackTrace();}

        Thread t = new Thread() {

        	public void run() {
        			List<DrugLight> result =
        				NewDrugWorker.getDrugsByPattern(SearchBox.this.searchTextField.getText());

        			if (result.size() == 1) {
        				SearchBox.this.currentSelectedObject = result.get(0);
        				// inform the listeners
//        				SearchBox.this.fireResultFound();

        			}
        	}

        };
        t.start();

//        /* No lookup if the last search returned without any results
//         *
//         * if the list of the popup is emtpy and the textField has more than
//         * the given offset characters
//         */
//        if ((popup.getListSize() <= 1) && (this.searchText.getText().length() > searchOffset)
//                && (this.searchText.getText().length() >= lastNumberOfResultsFound) && !forceLookup) {
//            logger.finer("Leave fireSearchThread - last search was empty"); //$NON-NLS-1$
//            // reset the selectedObject
//            this.currentSelectedObject = null;
//            return;
//        }
//
       //        }
    }

    /* --------------------------------------------------------------------------- */
    /* *************************************************************************** */

    /* *************************************************************************** */
    /*                                                                             */
    /*                          insertLastMatchingChar                             */
    /**
     * This method compares the string from the textfield with the ones in the
     * suggestion list of the popup. If the number of results is under a specific
     * limit the textfield will suggest the last possible characters which will
     * match to all of the entries in the list.
     */
    @SuppressWarnings("unused")
	private void insertLastMatchingChar() {
        // get the pattern from the textfield
        String pattern = searchTextField.getText();
        // get the items from the list
        List<Object> os = popup.getListData();
        /* the smallest differenz of an item and the pattern
         * must be stored. After finishing the search, the smallest pattern
         * will represent the intersection of the pattern an the list items
         */
        int offset = 1000;
        // we need the list renderer to obtain the same data which is used
        // in the db queries
        ISearchBoxDataRenderer renderer = popup.getListRenderer();
        // running through the list
        for (Object o : os) {
            // Object must be put into the list renderer to get the related data
            int t = renderer.getRelevantData(o).compareToIgnoreCase(pattern);
            if (t < offset)
                offset = t;
        }
        /* the ofset should now have the smallest intersection number of the paatern
         * and the items.
         * If the offset = 0 the smallest item is equal to the pattern
         *  |--> nothing to do
         * If the offset is smaller than 0
         *  |--> we have done something wrong. this should not happen.
         * if the offset is greater than 0 the offset is the number of
         * characters which are equal to all the items and the pattern
         */
        if ((offset > 0) && (offset < 1000)){
            System.out.println("=================================================="); //$NON-NLS-1$
            System.out.println("OffSet: "+offset); //$NON-NLS-1$
//            System.out.println(os[0]);
            System.out.println(renderer.getRelevantData(os.get(0))
                    .substring(pattern.length(), pattern.length()+offset));

            String newChars = renderer.getRelevantData(os.get(0))
                .substring(pattern.length(), pattern.length()+offset);

            int pos_orig = searchTextField.getCaretPosition();

            searchTextField.setText(pattern+newChars);
            searchTextField.setSelectionStart(pos_orig);
            searchTextField.setSelectionEnd(searchTextField.getText().length());
            searchTextField.setCaretPosition(pos_orig);
        }
    }




    /* This is the interface to the gatherer
     * so it can push the gathered informations back to the searchbox
     * which will pipe them to the popup
     *
     * (non-Javadoc)
     * @see lu.tudor.santec.gecam.prescription.gui.widgets.util.IResultListener#putResult(java.lang.Object)
     */
    public void receiveResult(Object data) {

        if (data instanceof List) {
            final List list = (List) data;


            // if the list is empty reset the sorted selected object
            if (list.size() == 0)
                this.currentSelectedObject = null;

            SwingUtilities.invokeLater(new Runnable() {
              @SuppressWarnings("unchecked")
			public void run() {
                // Wird erst aufgerufen, wenn alle
                // Aufgaben abgearbeitet wurden
                  SearchBox.this.popup.setNewData(list);

              }
            });
        }
    }





    /* --------------------------------------------------------------------------- */
    /* *************************************************************************** */

    @Override
	public void requestFocus() {
		/* ====================================================== */
		this.searchTextField.requestFocus();
		/* ====================================================== */
	}


	/* *************************************************************************** */
    /*                                                                             */
    /*                          Getter/Setter                                      */
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    /**
     * @return
     */
    public int getTextfieldSize() {
        return textfieldSize;
    }
    /**
     * @param textfieldSize
     */
    public void setTextfieldSize(int textfieldSize) {
        this.textfieldSize = textfieldSize;
    }

    /**
     * @return
     */
    public String getLabelText() {
        return labelText;
    }

    /**
     * @param labelText
     */
    public void setLabelText(String labelText) {
        this.labelText = labelText;
    }

    public int getSearchOffset() {
        return searchOffset;
    }


    public void setSearchOffset(int searchOffset) {
        this.searchOffset = searchOffset;
    }


    /**
     * Sets a text to the textfield
     *
     * @param drugText
     */
    public void setDrugText(String drugText) {
        this.searchTextField.setText(drugText);
    }


    public void addResultListener(IResultListener target){
    	this.targets.add(target);
    }
    public void removeResultListener(IResultListener target){
    	this.targets.remove(target);
    }

    public void setLookUp(ISearchBoxLookUp lookUp) {
        this.gatherer = lookUp;
        // set this as result listener of the lookup
        this.gatherer.addResultListener(this);

    }
    public ISearchBoxLookUp getLookUp() {
        return this.gatherer;
    }

    public void setListRenderer(ISearchBoxDataRenderer r) {
        if ( r != null)
            popup.setListRenderer(r);
        else
            logger.warn("ISearchBoxDataRenderer is null"); //$NON-NLS-1$
    }


    public void setFocusToTextField() {
    	this.searchTextField.requestFocus();
    }

    public void setComponentEnable(boolean b) {
        this.searchTextField.setEditable(b);
    }

    /**
     * Reset the component
     */
    public void reset() {
    	/* ================================================== */
    	this.setDrugText("");
    	this.currentSelectedObject = null;
    	lastEvent = null;
    	fireResultFound();
		/* ================================================== */
    }

    /**
     * Set the object that should be used
     *
     * @param o
     */
    public void setCurrentObject(Object o) {
    	/* ================================================== */
    	this.currentSelectedObject = o;
		/* ================================================== */
    }

    /* ------------------------------------------------------------------------------- */



    /* ********************************************************************************
     *
     *   FocusListener/MouseListener/DocumentListener
     */

    public void focusGained(FocusEvent e) {
    	fireFocusGained();
    	
    }


    public void focusLost(FocusEvent e) {
    	fireSearchByKeyEvent(e);

    }


    public void fireSearchByKeyEvent(ComponentEvent ce) {
    	/* ================================================== */
    	// we have to check if the invocation is triggered
    	// by focus lost or a key event
    	//
    	// if the last event is a key event, we should do nothing
    	// here because everything has been done by the keyevent
    	/* ------------------------------------------------------- */
    	if (lastEvent == null)
    		lastEvent = ce;
    	else {
    		if (lastEvent instanceof KeyEvent && ce instanceof FocusEvent)
    			return;
    	}
    	/* ------------------------------------------------------- */
    	if (popup.isVisible()) {
		    isInsertAction = true;

		    // save the found object in a variable
		    SearchBox.this.currentSelectedObject = SearchBox.this.popup.getSelectedItem();

		    // check if there are nested drugs
		    if (currentSelectedObject != null && currentSelectedObject instanceof DrugLight) {
		    	blockFireresult = true;
		    	/* ------------------------------------------------------ */
		    	DrugLight d = (DrugLight) currentSelectedObject;
		    	if (d.getSubTypes() != null && d.getSubTypes().size() > 0) {
		    		/* ------------------------------------------------------ */
//		    		e.consume();
		    		// show the dialog
		    		DrugFormSelector ds = new DrugFormSelector(MainFrame.getInstance());
		    		// create a list with the parent and the subtypes
		    		List<DrugLight> all = new ArrayList<DrugLight>();
		    		all.add(d);
		    		all.addAll(d.getSubTypes());

		    		Object newObject = null;
		    		newObject = ds.showDialog(all);
		    		if (newObject != null) {
		    			currentSelectedObject = newObject;
		    			searchTextField.setText(((DrugLight) currentSelectedObject).getName()
		    					+ " " + ((DrugLight) currentSelectedObject).getForm());
		    		}
		    		/* ------------------------------------------------------ */
		    	} else
		    		searchTextField.setText(d.getName() + " " + d.getForm());
		    	/* ------------------------------------------------------ */
		    }
		    else {
//			    // set text to the textfield
//				searchText.setText(
//                        SearchBox.this.popup.getListRenderer()
//                            .getStringForTextField(
//                                    SearchBox.this.popup.getSelectedItem()));
		    }

		    blockFireresult = false;


			popup.setVisible(false);
            fireResultFound();
		}
		// else -> push data to targets
		else {
			fireResultFound();
		}
		/* ================================================== */
    }




    /* ******************************************************************************* */
    /*                                                                                 */
    /*                          Document for the TextField                             */
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    /**
     * @author Martin Heinemann martin.heinemann@tudor.lu
     *
     * Document Model for the searchBox JTextField
     */
    class SearchBoxDocument extends PlainDocument {

        private static final long serialVersionUID = 1L;
        private DocumentListener docListener;

        /**
         *
         */
        public SearchBoxDocument() {
            // Register Listener
            this.docListener = new SearchBoxDocumentListener();
            this.addDocumentListener(docListener);
        }

        /**
         * @author Martin Heinemann martin.heinemann@tudor.lu
         *
         * DocumentListener for the JTextField
         */
        class SearchBoxDocumentListener implements DocumentListener {

            public void insertUpdate(DocumentEvent e) {
                // Important
            	// Hier muss das rein mit der Datenbank abfrage bei neuer Eingabe!
                if (!isInsertAction) {
                    fireSearchThread();

                }
            }
            public void removeUpdate(DocumentEvent e) {
            	// Hier muss das rein mit der Datenbank abfrage bei neuer Eingabe!
                    if(!isInsertAction) {
                        fireSearchThread();
                    }
            }
            public void changedUpdate(DocumentEvent e) {
            }
        }

    }

    /* ******************************************************************************* */
    /*                                                                                 */
    /*                          KeyListener for the TextField                          */
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
   class SearchBoxKeyListener implements KeyListener {

	public void keyTyped(KeyEvent e) {}

	public void keyPressed(KeyEvent e) {
		// If keyactions are arrow up/down -> focus to the popup
		if (e.getKeyCode() == KeyEvent.VK_UP) {
		        popup.setListPosition(popup.getListPosition()-1);
//            thats all, consume the event.
                e.consume();
        }

		if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            popup.setListPosition(popup.getListPosition()+1);
            // thats all, consume the event.
            e.consume();
        }

		if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_TAB) {
			fireSearchByKeyEvent(e);
		}
        if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
            if (popup.isVisible())
                popup.setVisible(false);
        }

        // Trigger for auto suggestion Alt+Space
        if((e.isControlDown()) && (e.getKeyCode() == KeyEvent.VK_SPACE)) {

            isInsertAction = false;
            fireSearchThread();
        }
	}
	public void keyReleased(KeyEvent e) {}

   }


}
