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

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JSplitPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import lu.tudor.santec.gecamed.addressbook.ejb.entity.beans.Contact;
import lu.tudor.santec.gecamed.addressbook.gui.AddressbookModule;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Invoice;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Settlement;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Statement;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.StatementBean;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.StatementInterface;
import lu.tudor.santec.gecamed.billing.gui.BillingModule;
import lu.tudor.santec.gecamed.billing.gui.event.invoice.InvoiceChangeEvent;
import lu.tudor.santec.gecamed.billing.gui.event.invoice.InvoiceListener;
import lu.tudor.santec.gecamed.billing.gui.event.usermode.UserModeListener;
import lu.tudor.santec.gecamed.billing.gui.medpres.MedPres;
import lu.tudor.santec.gecamed.billing.utils.StatementWorkflow;
import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedLog;
import lu.tudor.santec.gecamed.core.gui.GECAMedMessage;
import lu.tudor.santec.gecamed.core.gui.GECAMedTab;
import lu.tudor.santec.gecamed.core.gui.IconFetcher;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.widgets.ButtonPanel;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.i18n.Relocalizable;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

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

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

public class StatementPanel extends GECAMedTab implements ListSelectionListener,
														  PropertyChangeListener,
														  ActionListener,
														  InvoiceListener,
														  UserModeListener,
														  Relocalizable 
	{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private JSplitPane				m_SplitPane;
	
	private JPanel					m_StatementPanel;
	private ButtonPanel				m_StatementTools;
	private JButton					m_NewStatementButton;
	private JButton					m_OpenStatementButton;
	private JButton					m_CloseStatementButton;
	private JButton					m_PrintStatementButton;
	private JButton					m_DeleteStatementButton;		
	private StatementListBox		m_StatementListing;
	
	private StatementInvoicesPanel	m_InvoiceListing;
	
	private StatementInterface		m_StatementInterface;
	private StatementDialog			m_StatementDialog;
	private StatementPrintDialog	m_StatementPrintDialog;
	
	private Statement				m_Statement;
	private Settlement				m_Settlement;

		
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************
	
	public final static boolean c_WithUserNotification 	  = true;
	public final static boolean c_WithoutUserNotification = false;
	
	private final static double	c_Zero				= 0d;

	private final static String c_Columns= "fill:pref:grow";		
	private final static String c_Rows=    "fill:pref:grow";

	private final static String c_StatementColumns	= "fill:pref:grow,3dlu";		
	
	private final static String c_StatementRows		= "fill:max(34px;pref)," +
										   		  	  "fill:pref:grow";

	private final static String	c_NewStatementButtonTip    = "StatementPanel.NewStatementTip";
	private final static String	c_OpenStatementButtonTip   = "StatementPanel.OpenStatementTip";
	private final static String	c_CloseStatementButtonTip  = "StatementPanel.CloseStatementTip";
	private final static String	c_PrintStatementButtonTip  = "StatementPanel.PrintStatementTip";
	private final static String	c_DeleteStatementButtonTip = "StatementPanel.DeleteStatementTip";
	
	private static Logger m_Logger = Logger.getLogger ("gecamed.billing.gui.statement.StatementPanel");
	
//***************************************************************************
//* Constructor(s)                                                          *
//***************************************************************************
//---------------------------------------------------------------------------

public StatementPanel ()
	{	
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;
     
    l_Constraints  	= new CellConstraints();
	l_Layout		= new FormLayout(c_Columns, c_Rows);
		
	this.setLayout (l_Layout); 
	this.setOpaque(false);
	  		
	m_Statement = null;
	
	this.buildStatementPanel();
	
	m_InvoiceListing   = new StatementInvoicesPanel ();
	//m_InvoiceListing.addInvoiceListener(this);
	m_InvoiceListing.addPropertyChangeListener(this);
	
	m_SplitPane = new JSplitPane (JSplitPane.HORIZONTAL_SPLIT,
								  m_StatementPanel,
								  m_InvoiceListing);
	m_SplitPane.setOpaque(false);
	m_SplitPane.setOneTouchExpandable(true);
	
	this.add (m_SplitPane,l_Constraints.xywh(1, 1, 1, 1));
	
	m_StatementDialog 		= new StatementDialog ();
	m_StatementPrintDialog	= new StatementPrintDialog ();
	
	BillingModule.getInstance().addUserModeListener (this);
//	BillingModule.getInstance().addInvoiceListener (this);
	}

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

private JPanel buildStatementPanel ()
	{
 	CellConstraints	l_Constraints;
	FormLayout		l_Layout;
    MouseAdapter	l_MouseAdapter;
	
    l_Constraints  	= new CellConstraints();
	l_Layout		= new FormLayout(c_StatementColumns, c_StatementRows);
	
	m_StatementPanel = new JPanel ();
	m_StatementPanel.setLayout (l_Layout); 
	m_StatementPanel.setOpaque(false);
			
	this.buildStatementTools();

    m_StatementListing = new StatementListBox ();
	m_StatementListing.getViewport().setOpaque(false);
	m_StatementListing.setBackground(GECAMedColors.c_ScrollPaneBackground);
	
  	//-----------------------------------------------------------------------
   	// Setup a MouseAdapter to intercept double-clicks on invoice. Double-click
   	// on invoice ought to open invoice in Editor Panel.
    //-----------------------------------------------------------------------
  	
   	l_MouseAdapter = new MouseAdapter()
    		{
    		public void mouseClicked(MouseEvent p_Event)
    			{
    			if (p_Event.getClickCount() == 2)
    				{
    				editSelectedStatement (); 
    				}
    			}
    		};
  
    m_StatementListing.addMouseListener (l_MouseAdapter); 
    m_StatementListing.addListSelectionListener (this);
	
 	m_StatementPanel.add (m_StatementTools,  l_Constraints.xywh(1, 1, 2, 1));
 	m_StatementPanel.add (m_StatementListing,l_Constraints.xywh(1, 2, 2, 1));
    
    return m_StatementPanel;
	}


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

private void buildStatementTools ()
	{
	m_StatementTools = new ButtonPanel (BillingModule.m_ModulePlainModeColor);
		
	if (BillingModule.userHasPermission(BillingModule.c_BillingModule,BillingModule.c_createStatements))
		{    	
		m_NewStatementButton = new JButton ();
		m_NewStatementButton.setIcon(BillingModule.getIconResource("stmnt_create_action.png"));	
		m_NewStatementButton.setToolTipText(Translatrix.getTranslationString(c_NewStatementButtonTip));	
		m_NewStatementButton.addActionListener(this);
		
		m_StatementTools.addButton(m_NewStatementButton);
		}
		
	if (BillingModule.userHasPermission(BillingModule.c_BillingModule,BillingModule.c_deleteStatements))
		{    	
		m_DeleteStatementButton = new JButton ();
		m_DeleteStatementButton.setIcon(BillingModule.getIconResource("stmnt_delete_action.png"));	
		m_DeleteStatementButton.setToolTipText(Translatrix.getTranslationString(c_DeleteStatementButtonTip));	
		m_DeleteStatementButton.addActionListener(this);
		
		m_StatementTools.addButton(m_DeleteStatementButton);
		}

	if (BillingModule.userHasPermission(BillingModule.c_BillingModule,BillingModule.c_closeStatements))
		{    	
		m_CloseStatementButton = new JButton ();
		m_CloseStatementButton.setIcon(BillingModule.getIconResource("stmnt_close_action.png"));	
		m_CloseStatementButton.setToolTipText(Translatrix.getTranslationString(c_CloseStatementButtonTip));	
		m_CloseStatementButton.addActionListener(this);
		
		m_StatementTools.addButton(m_CloseStatementButton);
		}
	
	if (BillingModule.userHasPermission(BillingModule.c_BillingModule,BillingModule.c_openStatements))
		{    	
		m_OpenStatementButton = new JButton ();
		m_OpenStatementButton.setIcon(BillingModule.getIconResource("stmnt_open_action.png"));	
		m_OpenStatementButton.setToolTipText(Translatrix.getTranslationString(c_OpenStatementButtonTip));	
		m_OpenStatementButton.addActionListener(this);
		
		m_StatementTools.addButton(m_OpenStatementButton);
		}
	
	if (BillingModule.userHasPermission(BillingModule.c_BillingModule,BillingModule.c_printStatements))
		{    	
		m_PrintStatementButton = new JButton ();
		m_PrintStatementButton.setIcon(BillingModule.getIconResource("stmnt_print_action.png"));	
		m_PrintStatementButton.setToolTipText(Translatrix.getTranslationString(c_PrintStatementButtonTip));	
		m_PrintStatementButton.addActionListener(this);
		
		m_StatementTools.addButton(m_PrintStatementButton);
		}	
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Interface Getters                                                       *
//***************************************************************************
//---------------------------------------------------------------------------

private StatementInterface getStatementInterface ()
	{
	if (m_StatementInterface != null) return m_StatementInterface;

	try {
		m_StatementInterface = (StatementInterface) ManagerFactory.getRemote(StatementBean.class);
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return m_StatementInterface;
	}

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

private Statement saveStatement (Statement p_Statement)
	{
	StatementInterface l_StatementInterface;
	
	l_StatementInterface  = this.getStatementInterface();
	if (l_StatementInterface == null) return p_Statement;
		
	try {
		p_Statement = l_StatementInterface.saveStatement(p_Statement);		
		}
	catch (Exception p_Exception)
		{
		m_Logger.log(Level.WARN, "Failed to save Statement!", p_Exception);
		}
	
	return p_Statement;
	}

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

private Settlement getSettlementForStatement (Statement p_Statement)
	{
	Settlement	l_Settlement = null;
	
	StatementInterface	l_StatementInterface = null;
	
	l_StatementInterface = getStatementInterface ();
	
	if (l_StatementInterface == null) return l_Settlement;
	
	try {
		l_Settlement = l_StatementInterface.getSettlement(p_Statement);
		}
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}
	
	return l_Settlement;
	}

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

private boolean allInvoicesSettledForStatement (Statement p_Statement)
	{
	Boolean l_AllInvoicesSettled = Boolean.FALSE;
	
	StatementInterface	l_StatementInterface = null;
	
	l_StatementInterface = getStatementInterface ();
	
	if (l_StatementInterface == null) return l_AllInvoicesSettled;
	
	try {
		l_AllInvoicesSettled = l_StatementInterface.allInvoicesSettledForStatement(p_Statement);
		}
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return l_AllInvoicesSettled;
	}

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

private Statement settleStatement (Statement p_Statement)
	{
	int	l_Action;
	
	if (p_Statement != null)
		{
		l_Action = StatementWorkflow.changeStatementState(p_Statement,StatementWorkflow.c_SettleAction);
		if (l_Action == StatementWorkflow.c_DoSettle)
			{
			p_Statement = this.saveStatement(p_Statement);
			if (m_StatementListing.updateStatement(p_Statement)) m_StatementListing.validate();
			}
		}
	
	return p_Statement;
	}

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

private Statement revokeStatement (Statement p_Statement)
	{
	int	l_Action;
	
	if (p_Statement != null)
		{
		l_Action = StatementWorkflow.changeStatementState(p_Statement,StatementWorkflow.c_RevokeAction);
		if (l_Action == StatementWorkflow.c_DoRevoke)
			{
			p_Statement = this.saveStatement(p_Statement);
			if (m_StatementListing.updateStatement(p_Statement)) m_StatementListing.validate();
			}
		}
	
	return p_Statement;
	}
//---------------------------------------------------------------------------

private Statement checkFullSettlement (Statement p_Statement)
	{
	if (p_Statement != null)
		{
		if (this.allInvoicesSettledForStatement(p_Statement))
			{
			this.settleStatement(p_Statement);
			}
		else
			{
			this.revokeStatement(p_Statement);
			}
		}
	return p_Statement;
	}

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

private Invoice settleInvoice (Invoice p_Invoice)
	{
	Settlement	l_SettlementMethod;
	Date		l_SettlementDate;
	double		l_Payed;
	double		l_Returned;
	double		l_Deduction;
	
	if (p_Invoice == null) return p_Invoice;
	
	l_SettlementMethod = m_Settlement;
	l_SettlementDate   = m_Statement.getSettlementDate();
	
	l_Payed		   = p_Invoice.getBalance();
	l_Returned			   = c_Zero;
	l_Deduction		   = c_Zero;
		
//	p_Invoice.setPayment 		(l_Credit);
//	p_Invoice.setSettlement		(l_SettlementMethod);
//	p_Invoice.setSettlementDate	(l_SettlementDate);
//	p_Invoice = BillingModule.getInstance().registerTransaction(p_Invoice, 
//																l_SettlementMethod, 
//																l_SettlementDate, 
//																l_Credit, 
//																l_Debit);		
	
	// TODO LEDGER -> moved to Beanmethod
	try {
		p_Invoice = BillingModule.getInstance().getAccountingInterface().registerTransaction(p_Invoice, 
				l_SettlementMethod, 
				l_SettlementDate, 
				l_Payed, 
				l_Returned,
				l_Deduction,
				false);
	
		GECAMedLog.user ("Billing","SETTLE Invoice", "Settled Invoice No: "+ p_Invoice + " via " + l_SettlementMethod + " Invoice Balance:" + p_Invoice.getBalance() + " Payed:"+l_Payed+ " Returned:"+l_Returned+ " Deduction:"+l_Deduction);
		

	} catch (Exception e) {
		m_Logger.error("Error settling Invoice: " + p_Invoice , e);
	}

	BillingModule.getInstance().fireInvoiceChange(InvoiceChangeEvent.c_InvoiceStatusChanged, p_Invoice);
	
	return p_Invoice;
	}

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

private Invoice revokeInvoice (Invoice p_Invoice)
	{
	Settlement	l_SettlementMethod;
	Date		l_SettlementDate;
	double		l_Credit;
	double		l_Debit;
	double		l_Deduction;
	
	if (p_Invoice == null) return p_Invoice;
	
	l_SettlementMethod = m_Settlement;
	l_SettlementDate   = m_Statement.getSettlementDate();

	l_Debit			   = p_Invoice.getPayment();
	l_Credit		   = c_Zero;
	l_Deduction		   = c_Zero;
	
//	p_Invoice.setPayment (c_Zero);
//	p_Invoice.setSettlementDate(null);
//	p_Invoice.setSettlement (null);
//	p_Invoice = BillingModule.getInstance().registerTransaction(p_Invoice, 
//																l_SettlementMethod, 
//																l_SettlementDate, 
//																l_Credit, 
//																l_Debit);
	
	// TODO LEDGER -> moved to Beanmethod
	try {
		p_Invoice = BillingModule.getInstance().getAccountingInterface().registerTransaction(p_Invoice, 
				l_SettlementMethod, 
				l_SettlementDate, 
				l_Credit, 
				l_Debit,
				l_Deduction,
				true);
		
		GECAMedLog.user ("Billing","REVOKE Invoice","Revoked " + l_Debit + "€ from Invoice: " + p_Invoice.getId());
		
	} catch (Exception e) {
		m_Logger.error("Error revoking Invoice: " + p_Invoice , e);
	}
	
	
	
	BillingModule.getInstance().fireInvoiceChange(InvoiceChangeEvent.c_InvoiceStatusChanged, p_Invoice);
	
	return p_Invoice;
	}

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

public void setStatement (Statement p_Statement, boolean forceReload) {
	if (p_Statement == null) return;
	
	m_Statement = p_Statement;
		
	m_Settlement = this.getSettlementForStatement(m_Statement);
	m_InvoiceListing.setStatement (m_Statement, forceReload);
	
	if (this.isEligibleForSettlement(false)) {
		m_InvoiceListing.setEditable(true);
		m_Statement = this.checkFullSettlement(m_Statement);
	} else {
		m_InvoiceListing.setEditable(false);
	}
	
	m_InvoiceListing.setStatement (m_Statement, false);

	if ((m_Statement.getState().intValue() >= StatementWorkflow.c_PrintedState) && (m_Statement.getSettlementDate() == null)) {
//		BillingModule.notifyUser("StatementPanel.NoSettlementDateTitle", 
//								 "StatementPanel.NoSettlementDateMessage", null);
	}
}

//---------------------------------------------------------------------------
	
public void updateListing ()
	{
	StatementInterface		l_StatementInterface = null;
	Collection <Statement>	l_Statements		 = null;
	
	
	l_StatementInterface = getStatementInterface ();
	
	if (l_StatementInterface == null) return;
	
	try {
		l_Statements = l_StatementInterface.getAllStatements();
		}
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	if (l_Statements != null) 
		{
		m_StatementListing.setStatements(l_Statements);
		m_StatementListing.packColumns();
		m_StatementListing.revalidate();
		}
	}

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

public boolean editStatement (Statement p_Statement)
	{
	boolean				l_WasModified;

	if (p_Statement == null) return false;

	m_StatementDialog.pack();
	m_StatementDialog.setStatement(p_Statement);

	MainFrame.showDialogCentered (m_StatementDialog);

	if (m_StatementDialog.wasAccepted() == false) return false;

	l_WasModified = m_StatementDialog.updateStatement (p_Statement);
	
	return l_WasModified;
	}

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

public void newStatement ()
	{
	Statement			l_Statement;
	
	l_Statement = new Statement ();
	if (this.editStatement(l_Statement) == true)
		{
		l_Statement.setState(StatementWorkflow.c_OpenState);
		l_Statement = this.saveStatement(l_Statement);
		m_StatementListing.addStatement(l_Statement);
		m_StatementListing.selectStatement(l_Statement.formatStatementNumber());
		m_StatementListing.revalidate();
		}
	}

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

public void editSelectedStatement ()
	{
	Statement 	l_SelectedStatement;
	boolean		l_WasModified;
	int					l_Action;
	
	if (BillingModule.userHasPermission (BillingModule.c_BillingModule, BillingModule.c_editStatements))
		{
		l_SelectedStatement = m_StatementListing.getSelectedStatement();
		
		
		if (l_SelectedStatement != null)
			{
			if (l_SelectedStatement.equals(Statement.DEFAULT_STATEMENT)) return;
			
			l_WasModified = this.editStatement (l_SelectedStatement);
			if (l_WasModified)
				{
				l_Action = StatementWorkflow.changeStatementState(l_SelectedStatement,StatementWorkflow.c_SaveAction);
				if (l_Action == StatementWorkflow.c_DoSave)
					{
					l_SelectedStatement = this.saveStatement(l_SelectedStatement);
					this.setStatement (l_SelectedStatement, false);
					
					if (l_SelectedStatement.getState().intValue() < StatementWorkflow.c_PrintedState)
						{
						m_InvoiceListing.updateInvoiceListing();
						}
					}
				}
			}
		}
	}

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

public boolean isEligibleForSettlement (boolean p_NotifyUser)
	{
	if (m_Statement == null) return false;
			
	if (m_Statement.getState().intValue() < StatementWorkflow.c_PrintedState)
		{
		if (p_NotifyUser) MainFrame.getInstance().showMessage(Translatrix.getTranslationString("StatementPanel.NotPrintedYet"));		
		return false;
		}
		
	if (m_Statement.getSettlementDate() == null)
		{
		if (p_NotifyUser) MainFrame.getInstance().showMessage(Translatrix.getTranslationString("StatementPanel.NoSettlementDate"));		
		return false;		
		}
	
	return true;
	}

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

public Statement getCurrentStatement ()
	{
	return m_Statement;
	}

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

public Invoice getSelectedInvoice ()
	{
	return m_InvoiceListing.getSelectedInvoice();
	}

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

public void setSelectedInvoice (Invoice p_Invoice)
	{
	m_InvoiceListing.setSelectedInvoice (p_Invoice);
	}

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

public void closeSelectedStatement ()
	{
	Statement 			l_SelectedStatement;
	int					l_Action;
	
	l_SelectedStatement = m_StatementListing.getSelectedStatement();
	if (l_SelectedStatement != null)
		{
		if (l_SelectedStatement.equals(Statement.DEFAULT_STATEMENT)) return;
		
		l_Action = StatementWorkflow.changeStatementState (l_SelectedStatement,StatementWorkflow.c_CloseAction);
		if (l_Action == StatementWorkflow.c_DoClose)
			{			
			m_InvoiceListing.closeInvoices();

			l_SelectedStatement = this.saveStatement(l_SelectedStatement);
			this.setStatement (l_SelectedStatement, true);
			
			final Statement changedStatement = l_SelectedStatement;
//			new Thread() {
//				public void run() {
//					m_StatementListing.setSelectedStatement(changedStatement);
//					setStatement(changedStatement, true);					
//				}
//			}.start();
			
			MainFrame.getInstance().showMessage(Translatrix.getTranslationString("StatementPanel.StatementClosed"));		
			}
		}
	}

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

public void openSelectedStatement ()
	{
	Statement 			l_SelectedStatement;
	int					l_Action;
	
	l_SelectedStatement = m_StatementListing.getSelectedStatement();
	if (l_SelectedStatement != null)
		{
		l_Action = StatementWorkflow.changeStatementState (l_SelectedStatement,StatementWorkflow.c_OpenAction);
		if (l_Action == StatementWorkflow.c_DoOpen)
			{
			m_InvoiceListing.openInvoices();

			l_SelectedStatement = this.saveStatement(l_SelectedStatement);
			this.setStatement (l_SelectedStatement, true);

			final Statement changedStatement = l_SelectedStatement;
//			new Thread() {
//				public void run() {
//					m_StatementListing.setSelectedStatement(changedStatement);
//					setStatement(changedStatement, true);					
//				}
//			}.start();

			MainFrame.getInstance().showMessage(Translatrix.getTranslationString("StatementPanel.StatementOpened"));		
			}
		}
	}

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

public Statement[] getSelectedStatements ()
	{
	Statement[]    l_SelectedStatements;
     
	l_SelectedStatements = m_StatementListing.getSelectedStatements(); 	
	return l_SelectedStatements;
	}

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

public void deleteSelectedStatements ()
	{
	Statement []		l_SelectedStatements;
	String []			l_Filler;

	StatementInterface	l_StatementInterface = null;

	Statement			l_Statement;
	Integer				l_Length;
	int					l_UserChoice;
	int					l_Index;
	int					l_Action;
	boolean				l_Allowed;
	

	l_UserChoice = JOptionPane.NO_OPTION;

	if (BillingModule.userHasPermission (BillingModule.c_BillingModule, BillingModule.c_deleteStatements))
		{
		l_SelectedStatements = this.getSelectedStatements ();
		if (l_SelectedStatements == null) return; 
				
		if (l_SelectedStatements.length == 1)
			{
			if (l_SelectedStatements[0].equals(Statement.DEFAULT_STATEMENT)) return;
			
			l_Filler = new String [1];
			l_Filler [0] = l_SelectedStatements[0].formatStatementNumber();
		
			l_UserChoice = BillingModule.getUserConfirmation("StatementPanel.DeleteSingleStatementTitle",
				  							  				 "StatementPanel.DeleteSingleStatementMessage",
				  							  				 l_Filler);
			}
		else
			{
			l_Filler = new String [1];
		
			l_Length = Integer.valueOf (l_SelectedStatements.length);
			l_Filler [0] = l_Length.toString();
		
			l_UserChoice = BillingModule.getUserConfirmation("StatementPanel.DeleteMultipleStatementsTitle",
	  				 									 	 "StatementPanel.DeleteMultipleStatementsMessage",
	  				 									 	 l_Filler);
			}
	
		if (l_UserChoice == JOptionPane.YES_OPTION)
			{
			l_StatementInterface = getStatementInterface ();	
			if (l_StatementInterface == null) return;
	
			l_Allowed = true;
			l_Index   = 0;
			
			while (	l_Allowed && (l_Index < l_SelectedStatements.length))
				{
				l_Statement = l_SelectedStatements[l_Index++];
				l_Action = StatementWorkflow.previewStateChange (l_Statement,StatementWorkflow.c_DeleteAction);
				l_Allowed &= (l_Action == StatementWorkflow.c_DoDelete);
				}
				
			if (l_Allowed == false)
				{
				BillingModule.notifyUser("StatementPanel.CanNotDeleteTitle", "StatementPanel.CanNotDeleteMessage", null);
				return;
				}
			
			for (l_Index = 0; l_Index < l_SelectedStatements.length; l_Index++)
				{
				l_Statement = l_SelectedStatements[l_Index];		
				
				if (l_Statement.equals(Statement.DEFAULT_STATEMENT)) break;
				
				l_Action = StatementWorkflow.changeStatementState (l_Statement,StatementWorkflow.c_DeleteAction);
				if (l_Action == StatementWorkflow.c_DoDelete)
					{
					if (l_Statement.getState().intValue() >= StatementWorkflow.c_ClosedState) m_InvoiceListing.openInvoices();
					
					try {
						l_StatementInterface.deleteStatement(l_Statement);
						GECAMedLog.user("Billing","DELETE Statement","Deleted Statement with ID " + l_Statement.getId());
						}
					catch (Exception p_Exception) 
						{
						m_Logger.warn(p_Exception.getLocalizedMessage());
						}
					}			
					
				m_StatementListing.removeSelectedStatements();
				m_InvoiceListing.reset();
				}
			}
		}
	}

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

public void printSelectedStatement()
	{
	StatementInterface	l_StatementInterface;
	Statement 			l_SelectedStatement;
	Integer				l_OldState;
	int					l_Action;
	
	if (BillingModule.userHasPermission (BillingModule.c_BillingModule, BillingModule.c_printStatements))
		{
		l_SelectedStatement = m_StatementListing.getSelectedStatement();
		if (l_SelectedStatement == null) return;
		
		l_OldState = l_SelectedStatement.getState();
		
		m_StatementPrintDialog.setStatement(l_SelectedStatement);
		m_StatementPrintDialog.setInvoiceStubs (m_InvoiceListing.getInvoiceStubs());
		
		l_Action = StatementWorkflow.changeStatementState(l_SelectedStatement,StatementWorkflow.c_PrintAction);			
	
//		if (l_Action == StatementWorkflow.c_DoPrint)
//			{
			m_StatementPrintDialog.pack();
			
			MainFrame.showDialogCentered (m_StatementPrintDialog);
			
			if (m_StatementPrintDialog.invoiceListWasPrinted())
				{
				l_StatementInterface  = this.getStatementInterface();
				if (l_StatementInterface == null) return;
						
				try {
					l_SelectedStatement = l_StatementInterface.saveStatement(l_SelectedStatement);
					}
				catch (Exception p_Exception)
					{
					m_Logger.log(Level.WARN, "Failed to save Statement State change after print!", p_Exception);
					}
				}
			else if (m_StatementPrintDialog.invoicesWerePrinted())
				{
				
				}
			else l_SelectedStatement.setState(l_OldState);
			}
//		}	
	}

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

public void addInvoiceListener (InvoiceListener p_Listener)
	{
	m_InvoiceListing.addInvoiceListener(p_Listener);
	}

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

@Override
public void preparetoShowup() 
	{
	if (m_Statement == null) {
		// reload list of statements
		this.updateListing();
		m_StatementListing.packColumns();
		m_SplitPane.setDividerLocation(0.33);
	} else {
		// reload selected statement
		this.setStatement(m_Statement, true);
	}
	
	InvoiceChangeEvent event = new InvoiceChangeEvent(m_InvoiceListing, 
			InvoiceChangeEvent.c_InvoiceSelectionChanged, m_InvoiceListing.getSelectedInvoice());
	BillingModule.getInstance().invoiceChanged(event);
	}

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

public void relocalize() 
	{
	if (m_NewStatementButton != null)
		m_NewStatementButton.setToolTipText(Translatrix.getTranslationString(c_NewStatementButtonTip));	
	
	if (m_DeleteStatementButton != null)
		m_DeleteStatementButton.setToolTipText(Translatrix.getTranslationString(c_DeleteStatementButtonTip));	

	if (m_OpenStatementButton != null)
		m_OpenStatementButton.setToolTipText(Translatrix.getTranslationString(c_OpenStatementButtonTip));	

	if (m_CloseStatementButton != null)
		m_CloseStatementButton.setToolTipText(Translatrix.getTranslationString(c_CloseStatementButtonTip));	

	if (m_PrintStatementButton != null)
		m_PrintStatementButton.setToolTipText(Translatrix.getTranslationString(c_PrintStatementButtonTip));	
	}

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

public void valueChanged(ListSelectionEvent p_SelectionEvent) 
	{
	Statement	l_Statement; 
	     
	if (!p_SelectionEvent.getValueIsAdjusting())
		{    
		l_Statement = m_StatementListing.getSelectedStatement();
		this.setStatement(l_Statement, false);
		}
	}

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

public void preparetoHide ()
	{
	m_Statement = this.checkFullSettlement(m_Statement);
	}

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

public void invoiceChanged (InvoiceChangeEvent p_Event) 
	{
	if (p_Event.getSource() == m_InvoiceListing)
		{
		if (p_Event.getType() == InvoiceChangeEvent.c_InvoiceSelectionChanged)
			{
//			m_Invoice = p_Event.getInvoice();
			}
		}
	}

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

public void propertyChange (PropertyChangeEvent p_Event) 
	{
	Invoice	l_Invoice;
	String	l_PropertyName;
	
	if (p_Event.getSource() == m_InvoiceListing)
		{
		l_PropertyName = p_Event.getPropertyName();
		
		if (StatementInvoicesPanel.c_InvoiceSettled.equals (l_PropertyName))
			{
			if (this.isEligibleForSettlement(true))
				{
				l_Invoice = (Invoice) p_Event.getNewValue();
				l_Invoice = this.settleInvoice (l_Invoice);
				m_InvoiceListing.setSelectedInvoice (l_Invoice);
				
				if (this.allInvoicesSettledForStatement(m_Statement))
					{
					m_Statement = this.settleStatement(m_Statement);
					m_InvoiceListing.setStatement(m_Statement, true);
					this.invalidate();
					}
				
				
				this.firePropertyChange(l_PropertyName,p_Event.getOldValue(),p_Event.getNewValue());						
				}
			}
		
		else if (StatementInvoicesPanel.c_InvoiceRevoked.equals (l_PropertyName))
			{
			if (this.isEligibleForSettlement(true)) 
				{
				l_Invoice = (Invoice) p_Event.getNewValue();
				l_Invoice = this.revokeInvoice (l_Invoice);
				m_InvoiceListing.setSelectedInvoice (l_Invoice);
				
				if (Statement.isSettled(m_Statement.getState()))
					{
					m_Statement = this.revokeStatement(m_Statement);
					m_InvoiceListing.setStatement(m_Statement, true);
					this.invalidate();
					}
				
				this.firePropertyChange(l_PropertyName,p_Event.getOldValue(),p_Event.getNewValue());									
				}
			}
		}
	}
//---------------------------------------------------------------------------

public void actionPerformed (ActionEvent p_ActionEvent)
	{
	if (p_ActionEvent.getSource().equals(m_NewStatementButton))
		{
		this.newStatement();
		}
	else if (p_ActionEvent.getSource().equals(m_DeleteStatementButton))
		{
		this.deleteSelectedStatements();
		}
	else if (p_ActionEvent.getSource().equals(m_OpenStatementButton))
		{
		this.openSelectedStatement();
		}
	else if (p_ActionEvent.getSource().equals(m_CloseStatementButton))
		{
		this.closeSelectedStatement();
		}
	else if (p_ActionEvent.getSource().equals(m_PrintStatementButton))
		{
		this.printSelectedStatement();
		}
	}

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

public void userModeChanged (boolean p_SuperUserMode) 
	{
	Color				l_Background;
	
	l_Background = (p_SuperUserMode)?BillingModule.m_ModuleSuperModeColor
									:BillingModule.m_ModulePlainModeColor;

	m_StatementTools.setColor(l_Background);
	}

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