/*******************************************************************************
 * 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.editor;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.AbstractCellEditor;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.TableCellEditor;
import javax.swing.text.BadLocationException;

import lu.tudor.santec.gecamed.core.gui.GECAMedFonts;
import lu.tudor.santec.gecamed.prescription.ejb.entity.dataclasses.DrugLight;
import lu.tudor.santec.gecamed.prescription.gui.util.IResultListener;
import lu.tudor.santec.gecamed.prescription.gui.widgets.toolkit.searchbox.DefaultSearchBoxRenderer;
import lu.tudor.santec.gecamed.prescription.gui.widgets.toolkit.searchbox.SearchBox;
import lu.tudor.santec.gecamed.prescription.gui.widgets.toolkit.searchbox.persistence.SearchBoxDrugGatherer;

/**
 * This is the cell editor for the table in the prescrition editor for the type medicin.
 * Each drug prescription consist of a drug name and a posology/description.
 * The first part is a single textfield with advanced feature. If there is a druglist in the database
 * the input from the textfield is used to make a query on the drug name. The result is put into an list
 * appearing right under the textfield. Somekind of autocompletion textfield. If CTRL+Space ist pressed, 
 * the search is triggerd by hand. To the right of this field there is a button to open the DrugBrowser.
 * If there is already some text in the field, this is used to generate the first filter on the drug list 
 * in the browser.
 * The second field is a textarea that only is editabe if a drug has been entered.
 * There is a button to the right to open the posology chooser.
 * 
 * @author martin.heinemann@tudor.lu
 * 15.01.2008
 * 12:51:35
 *
 *
 * @version
 * <br>$Log: DrugCellEditor.java,v $
 * <br>Revision 1.8  2008-10-14 12:18:28  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.7  2008-10-13 09:26:47  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.6  2008-09-25 09:43:08  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.5  2008-07-08 14:59:50  heinemann
 * <br>complete - # 161: Modifying prescription templates deletes changes
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/161
 * <br>
 * <br>Revision 1.4  2008-01-15 13:40:47  heinemann
 * <br>better documentation
 * <br>
 *   
 */
public class DrugCellEditor extends AbstractCellEditor implements
					TableCellEditor, DocumentListener, IResultListener, FocusListener {

	/**
	 * @return the rowIndex
	 */
	public int getRowIndex() {
		/* ====================================================== */
		return rowIndex;
		/* ====================================================== */}

	private static final long serialVersionUID = 1L;

	private JTextArea descriptionEditor = new JTextArea();

	private JComponent current;

	private int rows = 0;

	private JTable table;

	private int rowIndex;

	private final int OFFSET = 19;

	private SearchBox searchBox;
	private Object searchResult;
	
	private boolean stopCalled = false;
	
	/**
	 * 
	 */
	public DrugCellEditor() {
		/* ================================================== */
		descriptionEditor.setPreferredSize(new Dimension(300, 100));
		descriptionEditor.setLineWrap(true);
		descriptionEditor.setFont(GECAMedFonts.TEXTFIELD_FONT);
		descriptionEditor.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {

				if (e.getKeyCode() == KeyEvent.VK_TAB) {
					/* ------------------------------------------------------- */
					e.consume();
					fireEditingStopped();
					/* ------------------------------------------------------- */
				}
			}
		});
		/* ------------------------------------------------------- */
		FocusAdapter focAd = new FocusAdapter() {

			/* (non-Javadoc)
			 * @see java.awt.event.FocusAdapter#focusGained(java.awt.event.FocusEvent)
			 */
			@Override
			public void focusGained(FocusEvent e) {
				/* ====================================================== */
				stopCalled = false;
				super.focusGained(e);
				/* ====================================================== */
			}

			@Override
			public void focusLost(FocusEvent e) {
				/* ============================================= */
				if (!stopCalled) {
					stopCalled = true;
					stopCellEditing();
				}
				super.focusLost(e);
				/* ============================================= */
			}
			
			

		};
		descriptionEditor.addFocusListener(focAd);
		/* ------------------------------------------------------ */
		this.searchBox = new SearchBox();
		searchBox.setLookUp(new SearchBoxDrugGatherer());
		searchBox.addResultListener(this);
		searchBox.initComponents();
		searchBox.addFocusListener(this);
		/* ------------------------------------------------------- */
		searchBox.setListRenderer(new DefaultSearchBoxRenderer());

		descriptionEditor.getDocument().addDocumentListener(this);
		/* ================================================== */
	}
	
	
	public boolean hasFocus() {
		/* ================================================== */
		return (descriptionEditor.hasFocus() || searchBox.hasFocus());
		/* ================================================== */
	}
	
	/* (non-Javadoc)
	 * @see javax.swing.CellEditor#getCellEditorValue()
	 */
	public Object getCellEditorValue() {
		/* ================================================== */
		if (current instanceof SearchBox) {
			if (searchResult == null) {
				return new DrugLight();
			}
			return searchResult;
		}
		return descriptionEditor.getText();
		/* ================================================== */
	}

    /* (non-Javadoc)
     * @see javax.swing.table.TableCellEditor#getTableCellEditorComponent(javax.swing.JTable, java.lang.Object, boolean, int, int)
     */
    public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int rowIndex, int colIndex )  {
    	/* ================================================== */
    	this.table = table;
    	this.rowIndex = rowIndex;

    	if (rowIndex%2 == 0) {
    		current = searchBox;
    		searchBox.reset();
    		if (((DrugLight) value).getName() != null && !"".equals(((DrugLight) value).getName())) {
    			DrugLight dl = (DrugLight) value;
	    		searchBox.setDrugText(dl.getName() +
	    				(dl.getForm() != null && !"".equals(dl.getForm())
	    					? " " + dl.getForm()
	    					: "")
	    				);
    		}
    		else
    			searchBox.setDrugText("");
    		searchResult = value;
    		searchBox.setCurrentObject(value);
    	} else {
    		descriptionEditor.setSize(table.getColumnModel().getColumn(colIndex).getWidth(),
    				descriptionEditor.getPreferredSize().height);

    	    resize();
    		current = descriptionEditor;
    		descriptionEditor.setText((String) value);
    	}
    	return current;
    	/* ================================================== */
    }

    

    /* ------------------------------------------------------ */
    // helper to resize the textarea
    /**
     * 
     */
    private void resize() {
    	/* ====================================================== */
    		try {
				rows = getLineCount(descriptionEditor);
			} catch (BadLocationException e) {
			}
    		// resize pref size
    		descriptionEditor.setPreferredSize(new Dimension(
    				descriptionEditor.getPreferredSize().width,
    				OFFSET * rows));

	    if (table.getRowHeight(rowIndex) < descriptionEditor.getPreferredSize().height) {
	    	table.setRowHeight(rowIndex, descriptionEditor.getPreferredSize().height);
	      }


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


	/* (non-Javadoc)
	 * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
	 */
	public void changedUpdate(DocumentEvent e) {
		/* ============================================= */
		resize();
		/* ============================================= */
	}

	public void insertUpdate(DocumentEvent e) {
		/* ============================================= */
		resize();
		/* ============================================= */
	}

	public void removeUpdate(DocumentEvent e) {
		/* ============================================= */
		resize();
		/* ============================================= */
	}

	/**
	  * Gibt die Anzahl der (gewrappten) Zeilen zurück.
	  * @param area
	  * @return
	  * @throws BadLocationException
	  *
	  * @creditz <a href="http://groups.google.de/group/de.comp.lang.java/browse_thread/thread/7b2a34a94ab77fb7/400946ff25b241a4?lnk=st&q=JTextArea+getRows+&rnum=10&hl=de#400946ff25b241a4">
	  * de.comp.lang.java</a>
	  */
	public static int getLineCount(JTextArea area)
	        throws BadLocationException {
	        String text = area.getText();
	        int len = text.length();
	        int line = area.getLineOfOffset(len);
	        return line+1;

	}

	public void receiveResult(Object data) {
		/* ============================================= */
		this.searchResult = data;

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

	@Override
	public void cancelCellEditing() {
		super.cancelCellEditing();
		searchBox.reset();
	}

	@Override
	public boolean stopCellEditing() {
		searchBox.fireSearchByKeyEvent(null);
		stopCalled = true;
		return super.stopCellEditing();
	}

	public void focusGained(FocusEvent e) {
		/* ====================================================== */
		// TODO Auto-generated method stub
		stopCalled = false;
		/* ====================================================== */
	}

	public void focusLost(FocusEvent e) {
		/* ====================================================== */
		if (!stopCalled) {
			stopCalled = true;
			super.stopCellEditing();
		}
		
		/* ====================================================== */
	}




}
