/*******************************************************************************
 * 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.billing.gui.memo;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.swing.AbstractButton;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.SwingConstants;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Invoice;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Memo;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.InvoiceBean;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.InvoiceInterface;
import lu.tudor.santec.gecamed.billing.gui.BillingModule;
import lu.tudor.santec.gecamed.billing.utils.InvoiceWorkflow;
import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedTab;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.patient.gui.memo.MemoControler;
import lu.tudor.santec.i18n.Relocalizable;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Logger;

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

//***************************************************************************
//* Class Definition and Members                                            *
//***************************************************************************

public class MemoEditorPanel extends GECAMedTab implements ActionListener,
													    ListSelectionListener,
													    TableModelListener,
													    CellEditorListener,
													    Relocalizable
	{
	private MemoListBox				m_Memos;

	private JButton					m_AddMemoButton;
	private JButton					m_RemoveMemoButton;
	
	private InvoiceInterface		m_InvoiceInterface;
	
	private Invoice					m_Invoice;
	private	boolean					m_SaveOnDelete;
	private boolean					m_Showing;
	private boolean					m_Edited;
	
	private static Logger m_Logger = Logger.getLogger ("gecamed.billing.gui.MemoEditorPanel");

//	private static Pattern 
//    
//    c_InnerMostTagPattern = Pattern.compile ("^.*<([A-Z][A-Z0-9]*)[^>]*>(.*?)</\\1>.*$",Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
//	
//	private static Pattern
//	
//	c_TagContentPattern = Pattern.compile ("^.*?(\\w+).*?$",Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
//	
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************

	private static final String c_AddMemoButton    	= "MemoEditorPanel.AddMemoButton";
	private static final String c_RemoveMemoButton 	= "MemoEditorPanel.RemoveMemoButton";
//	private static final String c_SaveMemoButton 		= "MemoEditorPanel.SaveMemoButton";

	private static final String c_AddMemoTip    		= "MemoEditorPanel.AddMemoTip";
	private static final String c_RemoveMemoTip 		= "MemoEditorPanel.RemoveMemoTip";
//	private static final String c_SaveMemoTip 			= "MemoEditorPanel.SaveMemoTip";

	private static final long serialVersionUID = 1L;

	private final static String c_Columns= "3dlu,fill:pref:grow,3dlu,fill:max(50dlu;pref)";

	private final static String c_Rows=    "3dlu,fill:pref,3dlu," +
									 	"fill:max(10dlu;pref),3dlu,fill:max(10dlu;pref)," +
									 	"fill:pref:grow," +
									 	"fill:max(10dlu;pref),3dlu";
	
	public static final String c_InvoiceUpdated		= "MemoEditorPanel.InvoiceUpdated";

//***************************************************************************
//* Constructor(s)                                                          *
//***************************************************************************
//---------------------------------------------------------------------------

public MemoEditorPanel ()
	{
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;
	ImageIcon		l_Icon; 

	m_Invoice 			= null;
	m_SaveOnDelete 		= true;
	m_Showing			= false;
	l_Constraints  		= new CellConstraints();
	     
	l_Layout = new FormLayout(c_Columns, c_Rows);
	this.setLayout(l_Layout);
	this.setOpaque(false);
	
	m_Memos = new MemoListBox ();
	m_Memos.getViewport().setOpaque (false);
	m_Memos.setBackground(GECAMedColors.c_ScrollPaneBackground);
	m_Memos.addListSelectionListener(this);
	m_Memos.addTableModelListener(this);
	m_Memos.addCellEditorListener(this);
	
	l_Icon = BillingModule.getButtonIcon ("add_memo.png");
	m_AddMemoButton = new JButton (Translatrix.getTranslationString(c_AddMemoButton),l_Icon);
	m_AddMemoButton.setToolTipText (Translatrix.getTranslationString(c_AddMemoTip));
	m_AddMemoButton.setHorizontalAlignment(SwingConstants.LEFT);
	m_AddMemoButton.setVerticalTextPosition(AbstractButton.CENTER);
	m_AddMemoButton.setHorizontalTextPosition(AbstractButton.TRAILING); 
	m_AddMemoButton.setEnabled(true);
	
	l_Icon = BillingModule.getButtonIcon ("remove_memo.png");
	m_RemoveMemoButton = new JButton (Translatrix.getTranslationString(c_RemoveMemoButton),l_Icon);
	m_RemoveMemoButton.setToolTipText (Translatrix.getTranslationString(c_RemoveMemoTip));
	m_RemoveMemoButton.setHorizontalAlignment(SwingConstants.LEFT);
	m_RemoveMemoButton.setVerticalTextPosition(AbstractButton.CENTER);
	m_RemoveMemoButton.setHorizontalTextPosition(AbstractButton.TRAILING); 
	m_RemoveMemoButton.setEnabled(false);
	
//	l_Icon = BillingModule.getIconResource("save_memo.png");
//	m_SaveMemoButton = new JButton (Translatrix.getTranslationString(c_SaveMemoButton),l_Icon);
//	m_SaveMemoButton.setToolTipText (Translatrix.getTranslationString(c_SaveMemoTip));
//	m_SaveMemoButton.setHorizontalAlignment(SwingConstants.LEFT);
//	m_SaveMemoButton.setVerticalTextPosition(AbstractButton.CENTER);
//	m_SaveMemoButton.setHorizontalTextPosition(AbstractButton.TRAILING); 
//	m_SaveMemoButton.setEnabled(false);

	this.add (m_Memos, 		l_Constraints.xywh(2, 4, 1, 5));
	
	this.add (m_AddMemoButton, 		l_Constraints.xywh(4, 4, 1, 1));
	this.add (m_RemoveMemoButton, 	l_Constraints.xywh(4, 6, 1, 1));
//	this.add (m_SaveMemoButton, 		l_Constraints.xywh(4, 8, 1, 1));
	
	m_AddMemoButton.addActionListener(this);
	m_RemoveMemoButton.addActionListener(this);
//	m_SaveMemoButton.addActionListener(this);
	}

//---------------------------------------------------------------------------

//***************************************************************************
//* Primitives                                       						*
//***************************************************************************
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

private InvoiceInterface getInvoiceInterface ()
	{
	if (m_InvoiceInterface != null) return m_InvoiceInterface;

	try {
		m_InvoiceInterface = (InvoiceInterface) ManagerFactory.getRemote(InvoiceBean.class);
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return m_InvoiceInterface;
	}

//---------------------------------------------------------------------------

private void saveMemos ()
	{
	InvoiceInterface	l_InvoiceInterface;
	Set <Memo> 			l_Memos;
	
	if (m_Invoice == null) return;
	
	l_InvoiceInterface = getInvoiceInterface ();
	
	if (l_InvoiceInterface != null)
		{
		try {
			l_Memos = m_Memos.getMemos();
			m_Invoice = l_InvoiceInterface.saveMemos (m_Invoice,l_Memos);
			m_Edited = true;
			}
		catch (Exception p_Exception) 
			{
			m_Logger.warn(p_Exception.getLocalizedMessage());
			}
		}	
	}

//---------------------------------------------------------------------------

private Invoice fetchAuthors (Invoice p_Invoice)
	{
	InvoiceInterface	l_InvoiceInterface;
	Set <Memo> 			l_Memos;
	Set <Memo>			l_InitializedMemos;
	Iterator <Memo>		l_MemoIterator;
	Memo				l_Memo;
	
	if (p_Invoice == null) return p_Invoice;
	
	l_InvoiceInterface = getInvoiceInterface ();
	
	if (l_InvoiceInterface != null)
		{
		l_Memos = p_Invoice.getMemos();
		if (l_Memos == null) return p_Invoice;
		
		try	{
			l_InitializedMemos = new HashSet <Memo> ();
			l_MemoIterator 	   = l_Memos.iterator();
			while (l_MemoIterator.hasNext ())
				{
				l_Memo = l_MemoIterator.next();
				l_Memo = l_InvoiceInterface.fetchAuthorForMemo(l_Memo);
				l_InitializedMemos.add(l_Memo);
				}
			p_Invoice.setMemos (l_InitializedMemos);
			}
		catch (Exception p_Exception) 
			{
			m_Logger.warn(p_Exception.getLocalizedMessage());
			}			
		}	
	return p_Invoice;
	}

//---------------------------------------------------------------------------

//private boolean hasContent (String p_HTML)
//	{
//	Matcher	l_InnerMostTagMatcher;
//	Matcher	l_ContentMatcher;
//	boolean	l_HasContent			= false;
//	
//	if ((p_HTML == null) || (p_HTML.length() == 0)) return false;
//	
//	l_InnerMostTagMatcher = c_InnerMostTagPattern.matcher(p_HTML);
//	if (l_InnerMostTagMatcher.matches())
//		{
//		if (	l_InnerMostTagMatcher.group(2) != null)
//			{
//			l_ContentMatcher = c_TagContentPattern.matcher(l_InnerMostTagMatcher.group(2));
//			if (l_ContentMatcher.matches()) l_HasContent = true;
//			}
//		}
//	return l_HasContent;
//	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body                                      						*
//***************************************************************************
//---------------------------------------------------------------------------

public void reset ()
	{
	m_SaveOnDelete = false;
	
	m_Memos.removeAllMemos();	
	m_Invoice = null;
	this.setModified(false);
	}

//---------------------------------------------------------------------------

public void setInvoice (Invoice p_Invoice)
	{
	if (!m_Showing) return;
	
	System.out.println("SET: " + p_Invoice);
	if (p_Invoice == null)
		{
		m_Memos.removeAllMemos();
		this.setModified(false);
		}
	
	else if (p_Invoice.equals (m_Invoice) == false)
		{
		m_SaveOnDelete = false;
		
		if (p_Invoice.getState().intValue() == InvoiceWorkflow.c_NewState)
			{
			m_Memos.removeAllMemos();
			}
		else 
			{
			p_Invoice = this.fetchAuthors(BillingModule.getInstance().getCurrentInvoice());
			m_Memos.setMemos(p_Invoice.getMemos());
			}
			
		m_Memos.setCurrentAuthor(BillingModule.getCurrentUser());			
		}		


	m_Invoice = p_Invoice;
	m_Edited  = false;
//	System.out.println("SETTET: " + m_Invoice);
	}

//---------------------------------------------------------------------------

public void actionPerformed(ActionEvent p_ActionEvent) 
	{
	if ((m_Invoice == null) || (m_Memos.isEditing())) return;
	
	if (p_ActionEvent.getSource() == m_AddMemoButton)
		{
		Memo	l_Memo;
			
		l_Memo = new Memo ();
		l_Memo.setCreationDate(new Date ());
		l_Memo.setAuthor(BillingModule.getCurrentUser());
		m_Memos.addMemo(l_Memo);
		m_Memos.selectLastMemo ();
		m_Memos.focusOnSelectedMemo();
		}
	else if (p_ActionEvent.getSource() == m_RemoveMemoButton)
		{
		m_SaveOnDelete = true;
		
		m_Memos.removeSelectedMemo();
		}
	}

//---------------------------------------------------------------------------
/** Method is part of the ListSelectionListener interface. Method will be called as
 * soon as Result selection changes.
 * @param p_SelectionEvent specifies the selection event causing this method being called.
 */
//---------------------------------------------------------------------------

public void valueChanged (ListSelectionEvent p_SelectionEvent) 
    {
    Memo []   l_SelectedMemos;
    Memo		 l_Memo; 
    
    if (!p_SelectionEvent.getValueIsAdjusting())
        {    
     	l_SelectedMemos = m_Memos.getSelectedMemos();
		if (l_SelectedMemos != null && l_SelectedMemos.length == 1)
        	{
			l_Memo = l_SelectedMemos[0];
			if (l_Memo != null)
				{
				if (	(l_Memo.getAuthor().equals(BillingModule.getCurrentUser()))
					||  (BillingModule.userHasPermission(BillingModule.c_BillingModule, BillingModule.c_editAllMemos)) )
					{
					m_RemoveMemoButton.setEnabled (true);
					}
				else
					{
					m_RemoveMemoButton.setEnabled (false);
					}
				}
        	}
        }
    }

//---------------------------------------------------------------------------

public void preparetoShowup() 
	{
	Invoice l_Invoice;
	
	m_Showing = true;
	l_Invoice = BillingModule.getInstance().getCurrentInvoice();
//	System.out.println("SHOW: " + l_Invoice);
	this.setInvoice(l_Invoice);
		
//	m_Memos.packColumns();
	}

//---------------------------------------------------------------------------

public void preparetoHide () {
//	System.out.println("HIDE: " + m_Invoice);
	m_Showing = false;
	if (m_Edited) {
		this.firePropertyChange(MemoEditorPanel.c_InvoiceUpdated,null,m_Invoice);
	}
}

//---------------------------------------------------------------------------

public void tableChanged (TableModelEvent p_TableEvent) 
	{
	if (p_TableEvent.getType() == TableModelEvent.DELETE)
		{
		if (m_SaveOnDelete) this.saveMemos ();
		}
	else if (p_TableEvent.getType() == TableModelEvent.UPDATE)
		{
		m_Memos.selectMemoAt(p_TableEvent.getFirstRow());
		}
	}

//---------------------------------------------------------------------------

public void editingStopped (ChangeEvent p_Event) 
	{
	Memo []	l_SelectedMemos;
	Memo		l_Memo;
	
	l_SelectedMemos = m_Memos.getSelectedMemos();
	
	if (l_SelectedMemos != null && l_SelectedMemos.length == 1)
		{
		l_Memo = l_SelectedMemos [0];
		if (MemoControler.hasContent(l_Memo.getNote()) == false)
			{
			m_Memos.removeSelectedMemo();
			}
		this.saveMemos();
		}
	}

//---------------------------------------------------------------------------

public void editingCanceled (ChangeEvent p_Event) 
	{
	Memo []	l_SelectedMemos;
	Memo		l_Memo;
	
	l_SelectedMemos = m_Memos.getSelectedMemos();
	
	if (l_SelectedMemos != null && l_SelectedMemos.length == 1)
		{
		l_Memo = l_SelectedMemos [0];
		if (MemoControler.hasContent(l_Memo.getNote()) == false)
			{
			m_Memos.removeSelectedMemo();
			}
		}
	}

//---------------------------------------------------------------------------

public void relocalize() 
	{
	if (m_AddMemoButton != null)
		{	
		m_AddMemoButton.setText (Translatrix.getTranslationString(c_AddMemoButton));
		m_AddMemoButton.setToolTipText (Translatrix.getTranslationString(c_AddMemoTip));
		}
	
	if (m_RemoveMemoButton != null)
		{	
		m_RemoveMemoButton.setText (Translatrix.getTranslationString(c_RemoveMemoButton));
		m_RemoveMemoButton.setToolTipText (Translatrix.getTranslationString(c_RemoveMemoTip));
		}
	
//	if (m_SaveMemoButton != null)
//		{	
//		m_SaveMemoButton.setText (Translatrix.getTranslationString(c_SaveMemoButton));
//		m_SaveMemoButton.setToolTipText (Translatrix.getTranslationString(c_SaveMemoTip));
//		}
	}

//---------------------------------------------------------------------------

//***************************************************************************
//* End Of Class                                                            *
//***************************************************************************
}

