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

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Invoice;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.InvoiceStub;
import lu.tudor.santec.gecamed.billing.gui.BillingModule;
import lu.tudor.santec.gecamed.billing.gui.invoice.stub.InvoiceStubUtils;
import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedLog;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.utils.GECAMedGuiUtils;
import lu.tudor.santec.gecamed.core.gui.utils.SwingWorker;
import lu.tudor.santec.i18n.Relocalizable;
import lu.tudor.santec.i18n.Translatrix;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.toedter.calendar.JDateChooser;

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

public class RevokeReminderDialog extends JDialog implements ItemListener,
														  ActionListener,
														  Relocalizable
	{
	private static final long serialVersionUID = 1L;
	
	private JPanel						m_ReminderPanel;
	private TitledBorder				m_ReminderBorder;
	
//	private JCheckBox					m_OnlyExpired;
	private JLabel						m_NumberOfRemindersLabel;	
	private JTextField					m_NumberOfReminders;
	private JLabel						m_ExpiryDateLabel;
	private JDateChooser				m_ExpiryDate;
	
	private JPanel						m_RevokePanel;
	private TitledBorder				m_RevokeBorder;

	private JButton						m_RevokeButton;
	private JProgressBar				m_RevokeProgress;
	
	private SwingWorker  				m_BatchRevoker;
	private boolean						m_Aborted;

	private JButton						m_CancelButton;
	private Collection <InvoiceStub>	m_InvoiceStubs;
	private Collection <InvoiceStub>	m_RevokedInvoiceStubs;

	private boolean 					m_Canceled = false;
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constants					                                            *
//***************************************************************************
//---------------------------------------------------------------------------
	
	private final static int	   c_IconTextGap   = 10;

	//=======================================================================
	//= Layout Strings
	//=======================================================================

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

	private final static String c_Rows					= 	"3dlu,fill:pref," +
	  														"3dlu,fill:pref," +
	  														"3dlu,fill:pref," +
	  														"3dlu,fill:pref,3dlu";

	private final static String c_ReminderColumns 		= 	"3dlu,fill:max(75dlu;pref)," +
	  													  	"3dlu,fill:max(75dlu;pref),3dlu";

	private final static String c_ReminderRows 			= 	"3dlu,fill:pref," +
															"3dlu,fill:pref," +
															"3dlu,fill:pref," +
	  														"3dlu,fill:pref," +
	  														"3dlu,fill:pref,3dlu";
	
	private final static String c_RevokeColumns 		= 	"3dlu,fill:pref:grow,3dlu";

	private final static String c_RevokeRows 			= 	"3dlu,fill:pref," +
															"3dlu,fill:pref,3dlu";
	
	//=======================================================================
	//= I18N Strings
	//=======================================================================

	private final static String c_Title						= "RevokeReminderDialog.Title";
	private final static String c_ReminderBorder			= "RevokeReminderDialog.ReminderBorder";
	private final static String c_OnlyExpiredLabel			= "RevokeReminderDialog.OnlyExpiredLabel";
	private final static String c_NumberOfRemindersLabel	= "RevokeReminderDialog.NumberOfRemindersLabel";
	private final static String c_ExpiryDateLabel			= "RevokeReminderDialog.ExpiryDateLabel";

	private final static String c_RevokeBorder				= "RevokeReminderDialog.RevokeBorder";
	private final static String c_RevokeButton				= "RevokeReminderDialog.RevokeButton";
	private final static String c_RevokeProgressIdle		= "RevokeReminderDialog.RevokeProgressIdle";
	private final static String c_RevokeProgressDone		= "RevokeReminderDialog.RevokeProgressDone";
	private final static String c_RevokeProgressAbort		= "RevokeReminderDialog.RevokeProgressAbort";

//	private static Logger m_Logger = Logger.getLogger (RevokeReminderDialog.class.getName());

	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor					                                            *
//***************************************************************************
//---------------------------------------------------------------------------

public RevokeReminderDialog ()
	{
	super (MainFrame.getInstance(),Translatrix.getTranslationString(c_Title),true);
	
	CellConstraints	l_Constraints;
	FormLayout		l_Layout;	
	
	m_RevokedInvoiceStubs 	= new LinkedHashSet <InvoiceStub> ();
	
	this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
	
	l_Constraints  = new CellConstraints();

	m_ReminderBorder 	= new TitledBorder ("");
	m_RevokeBorder 		= new TitledBorder ("");
	
	m_NumberOfRemindersLabel = new JLabel ();
	m_NumberOfRemindersLabel.setForeground(GECAMedColors.c_LabelColor);

//	m_OnlyExpired = new JCheckBox ();
//	m_OnlyExpired.setOpaque(false);
//	m_OnlyExpired.setSelected(true);
//	m_OnlyExpired.addItemListener(this);
	
	m_ExpiryDateLabel = new JLabel ();
	m_ExpiryDateLabel.setForeground(GECAMedColors.c_LabelColor);
	
	m_CancelButton = new JButton ();
	m_CancelButton.setIcon(GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL));
	m_CancelButton.setText(Translatrix.getTranslationString("core.cancel"));
	m_CancelButton.addActionListener(this);

	this.getContentPane().setBackground(GECAMedColors.c_GECAMedBackground);
	this.relocalize();
		
	//=======================================================================
	//= Assemble Invoices Panel
	//=======================================================================
	
	l_Layout = new FormLayout(c_ReminderColumns, c_ReminderRows);
	m_ReminderBorder = new TitledBorder (Translatrix.getTranslationString(c_ReminderBorder));
	
	m_ReminderPanel = new JPanel ();
	m_ReminderPanel.setOpaque(false);
	m_ReminderPanel.setLayout(l_Layout);
	m_ReminderPanel.setBorder(m_ReminderBorder);
	
	m_NumberOfReminders = new JTextField ();
	m_NumberOfReminders.setHorizontalAlignment(JTextField.RIGHT);
	m_NumberOfReminders.setText ("0");
	m_NumberOfReminders.setEditable(false);
	
	m_ExpiryDate = GECAMedGuiUtils.getDateChooser(false);
	m_ExpiryDate.setDate(Invoice.getDueDate (new Date()));
	
//	m_ReminderPanel.add (m_OnlyExpired,    			l_Constraints.xywh(2, 2, 3, 1));
	m_ReminderPanel.add (m_NumberOfRemindersLabel,	l_Constraints.xywh(2, 4, 1, 1));
	m_ReminderPanel.add (m_NumberOfReminders,   	l_Constraints.xywh(4, 4, 1, 1));
	m_ReminderPanel.add (m_ExpiryDateLabel,   		l_Constraints.xywh(2, 6, 1, 1));
	m_ReminderPanel.add (m_ExpiryDate,   			l_Constraints.xywh(4, 6, 1, 1));
	
	//=======================================================================
	//= Assemble Switch Panel
	//=======================================================================
	
	l_Layout = new FormLayout(c_RevokeColumns, c_RevokeRows);
	m_RevokeBorder = new TitledBorder (Translatrix.getTranslationString(c_RevokeBorder));
	
	m_RevokePanel = new JPanel ();
	m_RevokePanel.setOpaque(false);
	m_RevokePanel.setLayout(l_Layout);
	m_RevokePanel.setBorder(m_RevokeBorder);
	
    m_RevokeButton = new JButton ();
	m_RevokeButton.setIcon(BillingModule.getIconResource("rmndr_revoke.png"));
	m_RevokeButton.setText(Translatrix.getTranslationString(c_RevokeButton));
	m_RevokeButton.setIconTextGap(c_IconTextGap);
	m_RevokeButton.addActionListener(this);
	
	m_RevokeProgress = new JProgressBar ();
	m_RevokeProgress.setMinimum(0);
	m_RevokeProgress.setValue(0);
	m_RevokeProgress.setStringPainted(true);
	m_RevokeProgress.setString (Translatrix.getTranslationString(c_RevokeProgressIdle));

	m_RevokePanel.add (m_RevokeButton,    		l_Constraints.xywh(2, 2, 1, 1));
	m_RevokePanel.add (m_RevokeProgress,    	l_Constraints.xywh(2, 4, 1, 1));
	
	//=======================================================================
	//= Assemble Main Panel
	//=======================================================================

	l_Constraints  	= new CellConstraints();
	l_Layout		= new FormLayout(c_Columns, c_Rows);

	this.setLayout(l_Layout);

	this.add (m_ReminderPanel, 	l_Constraints.xywh(2, 2, 3, 1));
	this.add (m_RevokePanel, 	l_Constraints.xywh(2, 4, 3, 1));
	this.add (m_CancelButton, 	l_Constraints.xywh(4, 6, 1, 1));
	}

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

private Collection <InvoiceStub> getInvoiceStubs (boolean p_OnlyExpired)
	{
	Iterator <InvoiceStub>		l_InvoiceStubIterator;
	Collection <InvoiceStub>	l_ExpiredInvoiceStubs;
	InvoiceStub					l_InvoiceStub;
	
	if (p_OnlyExpired) 
		{
		l_ExpiredInvoiceStubs = new LinkedHashSet <InvoiceStub> ();
		
		l_InvoiceStubIterator = m_InvoiceStubs.iterator();
		while (l_InvoiceStubIterator.hasNext())
			{
			l_InvoiceStub = l_InvoiceStubIterator.next();
			if (l_InvoiceStub.isExpired()) l_ExpiredInvoiceStubs.add(l_InvoiceStub);
			}
		return l_ExpiredInvoiceStubs;
		}
	else return m_InvoiceStubs;	
	}

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

public Integer countInvoiceStubs (boolean p_OnlyExpired)
	{
	int						l_Count = 0;
	Iterator <InvoiceStub>	l_InvoiceStubIterator;
	
	if (m_InvoiceStubs == null) return l_Count;
	
	if (p_OnlyExpired == true) 
		{
		l_InvoiceStubIterator = m_InvoiceStubs.iterator();
		while (l_InvoiceStubIterator.hasNext())
			{
			if (l_InvoiceStubIterator.next().isExpired()) l_Count++;
			}
		}
	else l_Count = m_InvoiceStubs.size();
	
	return l_Count;
	}

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

private Invoice revokeReminder (Invoice p_Invoice, Date p_DueDate, Date p_ReminderDate)
	{
	int		l_NumberOfReminders;
	
	l_NumberOfReminders = p_Invoice.getNumberOfReminders();
	if (l_NumberOfReminders > 0) l_NumberOfReminders--;
	
	p_Invoice.setNumberOfReminders(l_NumberOfReminders);
	
	switch (l_NumberOfReminders)
		{
		case 0:
		
			p_Invoice.setState 		  (p_Invoice.getOldState());
			p_Invoice.setDueDate	  (p_DueDate);
//			p_Invoice.setDueDate      (true);
			p_Invoice.setReminderDate (null);
			break;
		
		case 1:
		case 2:
		case 3:
			
//			p_Invoice.setDueDate      (true);
			p_Invoice.setDueDate	  (p_DueDate);
//			p_Invoice.setReminderDate (p_Invoice.getDueDate());
//			p_Invoice.setDueDate 	  (Invoice.getEarlierDate (p_Invoice.getDueDate(), m_DuePeriod));
//			p_Invoice.setReminderDate (Invoice.getEarlierDate (p_Invoice.getReminderDate(), m_DuePeriod));
			break;
		}
	
	GECAMedLog.user("Billing","REVOKE Reminder","Revoked Reminder for Invoice with ID " + p_Invoice.getId());

	return p_Invoice;
	}
//---------------------------------------------------------------------------
//***************************************************************************
//* Swing Worker Thread                                                     *
//***************************************************************************
//---------------------------------------------------------------------------

Object BatchRevoker ()
	{
	this.batchRevokeReminders();
	return "";
	}

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

private synchronized void batchRevokeReminders ()
	{
	Collection <InvoiceStub>	l_InvoiceStubs;
	Iterator <InvoiceStub>		l_InvoiceStubIterator;
	InvoiceStub					l_InvoiceStub;
	Invoice						l_Invoice;
	
	Date						l_Today;
	int							l_NumberOfReminders;
	int							l_RevokeCount;
	
	InvoiceStubUtils			l_InvoiceStubUtils;
	
	l_InvoiceStubUtils = new InvoiceStubUtils ();	
	
	l_InvoiceStubs = this.getInvoiceStubs (getOnlyExpired());
	if (l_InvoiceStubs == null) return;
		
	l_Today 				= new Date ();
	l_NumberOfReminders 	= l_InvoiceStubs.size();
	m_RevokedInvoiceStubs 	= new LinkedHashSet <InvoiceStub> ();
	l_RevokeCount			= 0;
	
	m_RevokeProgress.setMinimum (0);
	m_RevokeProgress.setMaximum (l_NumberOfReminders);
	m_RevokeProgress.setValue	(0);
	
	l_InvoiceStubIterator = l_InvoiceStubs.iterator();
	
	while (l_InvoiceStubIterator.hasNext() && !m_Aborted)
		{
		l_InvoiceStub = l_InvoiceStubIterator.next();
		l_Invoice	  = l_InvoiceStubUtils.fetchInvoiceForStub (l_InvoiceStub,false);
		if (l_Invoice != null)
			{
			l_Invoice = this.revokeReminder (l_Invoice, m_ExpiryDate.getDate(), l_Today);
			
			m_RevokeProgress.setString (l_Invoice.formatInvoiceNumber(Invoice.c_LongFormat, true));
			m_RevokeProgress.setValue  (l_RevokeCount + 1);
			
			l_Invoice = l_InvoiceStubUtils.saveInvoice(l_Invoice);
			m_RevokedInvoiceStubs.add (l_InvoiceStub);
			}		
		l_RevokeCount++;
		}
	
	m_RevokeProgress.setValue(0);
	if (m_Aborted)
		{
		m_RevokeProgress.setString (Translatrix.getTranslationString(c_RevokeProgressAbort));	
		}
	else
		{
		m_RevokeProgress.setString (Translatrix.getTranslationString(c_RevokeProgressDone));
		this.setVisible (false);
		}
	}

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

private void startBatchRevoking ()
	{
	m_BatchRevoker = new SwingWorker() 
	{
	public Object construct() 
		{
		return BatchRevoker ();
		}
	public void start ()
		{
		m_Aborted = false;
		super.start();
		}
	public void finished ()
		{
		}
	public void interrupt ()
		{
		m_Aborted = true;
		super.interrupt();
		}
	};

	m_BatchRevoker.start ();  	
	}

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

private void abortBatchRevoking ()
	{
	if (m_BatchRevoker != null) m_BatchRevoker.interrupt();
	}

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

public void setInvoiceStubs (Collection <InvoiceStub> p_InvoiceStubs)
	{
	Integer	l_Count;
	
	if (p_InvoiceStubs != null)
		{
		m_InvoiceStubs = p_InvoiceStubs;
		l_Count = this.countInvoiceStubs(getOnlyExpired());
		m_RevokeButton.setEnabled(l_Count > 0);
		m_NumberOfReminders.setText (l_Count.toString());
		}
	}

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

public Collection <InvoiceStub> getRevokedInvoiceStubs ()
	{
	return m_RevokedInvoiceStubs;
	}

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

public boolean canceled ()
	{
	return m_Canceled;
	}

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

public void relocalize() 
	{
	if (m_ReminderBorder != null)
		m_ReminderBorder.setTitle (Translatrix.getTranslationString(c_ReminderBorder));

	if (m_NumberOfRemindersLabel != null)
		m_NumberOfRemindersLabel.setText(Translatrix.getTranslationString(c_NumberOfRemindersLabel));
	
//	if (m_OnlyExpired != null)
//		m_OnlyExpired.setText(Translatrix.getTranslationString(c_OnlyExpiredLabel));
		
	if (m_ExpiryDateLabel != null)
		m_ExpiryDateLabel.setText(Translatrix.getTranslationString(c_ExpiryDateLabel));
	
	if (m_RevokeBorder != null)
		m_RevokeBorder.setTitle (Translatrix.getTranslationString(c_RevokeBorder));
	
	if (m_CancelButton != null)
		m_CancelButton.setText(Translatrix.getTranslationString("core.cancel"));
	}

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

public void actionPerformed(ActionEvent p_Event) 
	{
	if (p_Event.getSource().equals(m_RevokeButton))
		{
		this.startBatchRevoking();
		}
	else if (p_Event.getSource().equals(m_CancelButton))
		{
		this.abortBatchRevoking();
		this.m_Canceled = true;
		this.setVisible(false);
		}
	}

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

public void itemStateChanged(ItemEvent p_Event) 
	{
	Integer	l_Count;
	
//	if (p_Event.getSource().equals(m_OnlyExpired))
//		{
//		if (m_NumberOfReminders != null)
//			{
//			l_Count = this.countInvoiceStubs (getOnlyExpired());
//			m_RevokeButton.setEnabled(l_Count > 0);
//			m_NumberOfReminders.setText (l_Count.toString());
//			}
//		}	
	}


private boolean getOnlyExpired() {
	return false;
}

//---------------------------------------------------------------------------	
//***************************************************************************
//* End of Class				                            				*
//***************************************************************************
//---------------------------------------------------------------------------	
}
