/*******************************************************************************
 * 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.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JList;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListDataListener;

/**
 * This is the popup containing the JList that appears 
 * when the SearchBox wants to make a proposition for auto-completion.
 * 
 * 
 * @author Martin Heinemann martin.heinemann@tudor.lu
 *
 */
public class SearchBoxPopup extends JPopupMenu {

	/**
     *
     */
    private static final long serialVersionUID = 1L;


    /*      */
	final private int POPUP_HEIGHT = 8;


    private JList list;
    private JScrollPane scrollpane = null;
    private JTextField searchField;
//    private String[]  stringList = null;

    private SearchBoxListModel listModel;
    private ISearchBoxDataRenderer listRenderer = null;

    private List <Object> listContent;


    public SearchBoxPopup() {

    }

//    /**
//     * FRICKEL! !!!!!
//     *
//     */
//    public void setFocus(int direction) {
//    	this.list.requestFocus();
//    	// this is to place the selection to the second entry
//        int index = 1;
//        if (list.getSelectedIndex() != 0)
//            /* The direction is important to switch to the next item in the list
//             * the normal race condition is: the focus is on the textfield*/
//            index = list.getSelectedIndex()+direction;
//    	this.list.setSelectedIndex(index);
//
//    }



    /**
     * @param box
     */
    public SearchBoxPopup(JTextField searchField) {
        this.searchField = searchField;
        this.list = new JList();
        this.initComponents();
        //this.setFocusable(false);
    }
    /**
     * @param box
     * @param list
     */
    public SearchBoxPopup(JTextField searchField, List list) {
        this.searchField  = searchField;
        this.list       = new JList(list.toArray());
        this.initComponents();

    }

    /**
     * @param box
     * @param stringList
     */
    public SearchBoxPopup(JTextField searchField, String[] stringList) {
        this.searchField 	= searchField;
//    	this.stringList 	= stringList;
    	this.initComponents();
    }

    /**
     * @param data
     */
    public void setNewData(List<Object> data) {
        this.listModel.setData(data);
        this.listContent = data;
        //this.show(searchField, 0, searchField.getHeight());
        this.doShow();
    }

    /**
     * Tries to show the popup wether there is data or not
     */
    private void doShow() {
    	if (this.list.getModel().getSize() != 0) {
            // Set size according to the size of the SearchBox
            setPopupSize(new Dimension(searchField.getWidth(), searchField.getHeight()*POPUP_HEIGHT));
    		// Position related to the textfield
            // show only if the searchField has got focus
            SwingUtilities.invokeLater(new Runnable() {
            	public void run() {
            		if (searchField.hasFocus()) 
            			SearchBoxPopup.this.show(searchField, 0, searchField.getHeight());
            	}
            });

    		// Select the first entry
//    		this.list.setSelectedIndex(0);
    		//System.out.println("do Show");


    	}
    	else
    		this.setVisible(false);
    }


    /* =========================================================================== */
    /*                  Functions for operating on the JList                       */
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    /**
     * Return the selected Item from the JList
     * @return
     */
    public Object getSelectedItem() {
    	return this.list.getSelectedValue();
    }

    public int getListPosition() {
        return this.list.getSelectedIndex();
    }
    public void setListPosition(int index) {
        this.list.setSelectedIndex(index);
        this.list.ensureIndexIsVisible(index);
    }

    public int getListSize() {
        return list.getModel().getSize();
    }

    public List <Object> getListData() {
        //SearchBoxListModel sblm = (SearchBoxListModel) list.getModel();

//        Object[] o = new Object[getListSize()];
//        o = listModel.getData();

        return this.listContent;
    }

    public ISearchBoxDataRenderer getListRenderer() {
        return (ISearchBoxDataRenderer) this.list.getCellRenderer();
    }

    public void setListRenderer(ISearchBoxDataRenderer listRenderer) {
        this.listRenderer = listRenderer;
        if (this.listRenderer!= null)
            this.list.setCellRenderer(this.listRenderer);
    }

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

    /**
     *  Initialises the components
     */
    private void initComponents() {
    	// Init JPopupMenu
    	setLayout(new GridLayout(1,1));

        setBackground(new Color(255, 255, 255));


        // in der Liste darf immer nur ein Element selektierbar sein
        //this.list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        // ListModel
        this.listModel = new SearchBoxListModel();
        this.list.setModel(listModel);
        // Renderer
        //this.list.setCellRenderer(new ISearchBoxDataRenderer());

        // Mouse Listener
        this.list.addMouseListener(new SearchBoxPopupMouseListener());

        this.list.setFont(new Font("Arial",Font.PLAIN,10));

        // ScrollPane
        this.scrollpane = new JScrollPane(this.list);
        this.scrollpane.setBorder(BorderFactory.createEmptyBorder());
        // List to ScrollPane
        //this.scrollpane.add(this.list);
        this.add(this.scrollpane);

    }


    /* ******************************************************************************* */
    /*                                                                                 */
    /*                          List Model                                             */
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    class SearchBoxListModel implements ListModel {


        /*      Data Field                                                             */
        private Object[] data = {};


        public int getSize() {
            return this.data.length;
        }

        public Object getElementAt(int index) {
            return data[index];
        }

        /* =========================================================================== */
        /*                  Getters / Setters                                          */
        /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

        public Object[] getData() {
            return data;
        }

        public void setData(Object[] data) {
            this.data = data;
           // this.fireContentsChanged(this, 0, data.length);

        }



        public void setData(List <Object> data) {
            if (data == null) return;
            list.setListData(data.toArray());
        }

        public void addListDataListener(ListDataListener l) {
            // TODO Auto-generated method stub

        }

        public void removeListDataListener(ListDataListener l) {
            // TODO Auto-generated method stub

        }

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


    /* ******************************************************************************* */
    /*                                                                                 */
    /*                          Mouse Listener                                         */
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    class SearchBoxPopupMouseListener implements MouseListener {

		@SuppressWarnings("deprecation")
		public void mouseClicked(MouseEvent e) {
            if (e.getClickCount() == 2) {
//                int index = list.locationToIndex(e.getPoint());
                // like Enter
                searchField.getKeyListeners()[0].keyPressed(
                        new KeyEvent(list,10,0,0,KeyEvent.VK_ENTER));
             }
            else {
            	int index = list.locationToIndex(e.getPoint());
            	list.setSelectedIndex(index);
            }
		}

		public void mousePressed(MouseEvent e) {}
		public void mouseReleased(MouseEvent e) {}
		public void mouseEntered(MouseEvent e) {}
		public void mouseExited(MouseEvent e) {}

    }
}
