/*******************************************************************************
 * 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.patient.gui.incident;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Formatter;
import java.util.HashSet;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.table.AbstractTableModel;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Invoice;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.IconFetcher;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.i18n.Translatrix;

import com.jgoodies.forms.builder.ButtonBarBuilder;

/**
 * This dialog is shown when an invoice is created. It asks if the new invoice should be linked
 * to the current accident number of the patient.
 * It also allows to select from older accdient numbers.
 * 
 * 
 * @author martin.heinemann@tudor.lu
 * 26.04.2007
 * 10:07:01
 *
 *
 * @version
 * <br>$Log: AccidentInvoiceRelationDialog.java,v $
 * <br>Revision 1.7  2008-10-21 09:53:34  hermen
 * <br>fixed patient slot bug
 * <br>enhanced logging
 * <br>code cleanup
 * <br>
 * <br>Revision 1.6  2008-09-25 09:43:07  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.5  2008-01-22 13:51:52  heinemann
 * <br>code cleanup and java doc
 * <br>
 * <br>Revision 1.4  2007/07/03 12:35:29  heinemann
 * <br>system.out removed
 * <br>
 * <br>Revision 1.3  2007/05/25 13:50:25  heinemann
 * <br>pres-weekend checkin
 * <br>
 * <br>Revision 1.2  2007/04/26 13:39:46  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.1  2007/04/26 12:11:47  heinemann
 * <br>change invoice accident data if accident data is changed in consultation
 * <br>
 *
 */
public class AccidentInvoiceRelationDialog extends JDialog {

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

	private static AccidentInvoiceRelationDialog instance = new AccidentInvoiceRelationDialog();

	private JLabel infoLabel;

	private JButton okButton;

	private JButton cancelButton;

	private JPanel centerPanel;

	private JTable table;

	private JScrollPane scroll;

	private InvoiceTableModel tableModel;

	private JButton selectAllButton;

	private AbstractAction cancelAction;

	private AbstractAction okAction;

	protected List<Invoice> selectedInvoices;



	/**
	 *
	 */
	private AccidentInvoiceRelationDialog() {
		/* ================================================== */
		super(MainFrame.getInstance(), true);

		Translatrix.addBundle("lu.tudor.santec.gecamed.patient.gui.resources.Translatrix");
		initComponent();
		initActions();
		/* ================================================== */
	}

	/**
	 * @return
	 */
	public static AccidentInvoiceRelationDialog getInstance() {
		/* ================================================== */
		return instance;
		/* ================================================== */
	}


	public static void main (String argb[]) {
		/* ================================================== */
		AccidentInvoiceRelationDialog r = AccidentInvoiceRelationDialog.getInstance();
		List<Invoice> l = new ArrayList<Invoice>();

		for (int i=0;i<10;i++) {
			Invoice in = new Invoice();
			in.setInvoiceDate(new Date());
			l.add(in);
		}

		r.showDialog(l);

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


	public void showDialog(List<Invoice> invoices) {
		/* ================================================== */
		tableModel.setData(invoices);

		instance.setPreferredSize(new Dimension(450, 315));
		instance.pack();
//		MainFrame.showDialogCentered(instance);
		instance.setVisible(true);
		/* ================================================== */
	}


	/**
	 *
	 */
	private void initActions() {
		/* ================================================== */

		this.cancelAction = new AbstractAction(Translatrix.getTranslationString("pm.cancel"),
				GECAMedModule.getSmallIcon(GECAMedIconNames.CANCEL)) {

			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				/* ====================================================== */
				selectedInvoices = new ArrayList<Invoice>();
				instance.setVisible(false);
				/* ====================================================== */
			}
		};
		/* ------------------------------------------------------- */
		this.okAction = new AbstractAction(Translatrix.getTranslationString("pm.ok"),
				GECAMedModule.getSmallIcon(GECAMedIconNames.OK)) {

			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) {
				/* ====================================================== */
				// TODO
				selectedInvoices = tableModel.getSelectedInvoices();
					instance.setVisible(false);
				/* ====================================================== */
			}
		};

		this.okButton.setAction(okAction);
		this.cancelButton.setAction(cancelAction);

		/* ------------------------------------------------------- */
		// define dialog wide key mappings
		KeyStroke strokeEsc = KeyStroke.getKeyStroke("ESCAPE");

		((JPanel) this.getContentPane()).getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
					.put(strokeEsc, "continue");
		((JPanel) this.getContentPane()).getActionMap().put("continue", cancelAction);


		KeyStroke strokeEnter = KeyStroke.getKeyStroke("ENTER");

		((JPanel) this.getContentPane()).getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
					.put(strokeEnter, "ok");
		((JPanel) this.getContentPane()).getActionMap().put("ok", okAction);
		/* ================================================== */
	}



	/**
	 * Init component
	 */
	private void initComponent() {
		/* ====================================================== */
		this.setLayout(new BorderLayout(0, 10));
		this.getContentPane().setBackground(Color.WHITE);
		/* ------------------------------------------------------- */
		// in the north --> info label
		this.infoLabel = new JLabel();
		infoLabel.setIcon(IconFetcher.getBigIcon(PatientManagerModule.class, PatientManagerModule.QUESTION));
		infoLabel.setHorizontalTextPosition(SwingConstants.RIGHT);
		infoLabel.setFont(new Font(infoLabel.getFont().getName(), infoLabel.getFont().getStyle(), 15));
		infoLabel.setText(Translatrix.getTranslationString("patient.incident.accident.changeInvoiceQuestion"));
		infoLabel.setOpaque(false);

		/* ------------------------------------------------------- */
		this.add(infoLabel, BorderLayout.NORTH);
		/* ------------------------------------------------------- */
		// in the south --> Buttons
		this.okButton = new JButton();
		this.cancelButton = new JButton();

		ButtonBarBuilder bb = new ButtonBarBuilder();
		bb.addGlue();
		bb.addGridded(okButton);
		bb.addRelatedGap();
		bb.addGridded(cancelButton);
		bb.getPanel().setOpaque(false);
		/* ------------------------------------------------------- */
		// a panel to make a gap between the dialog border and the buttons
		JPanel gapPanel = new JPanel(new BorderLayout(5,5));
		gapPanel.setOpaque(false);
		gapPanel.add(bb.getPanel(), BorderLayout.CENTER);
		gapPanel.add(new JLabel(""), BorderLayout.SOUTH);
		gapPanel.add(new JLabel(""), BorderLayout.EAST);
		/* ------------------------------------------------------- */
		this.add(gapPanel, BorderLayout.SOUTH);
		/* ------------------------------------------------------- */



		/* ------------------------------------------------------- */
		/* ------------------------------------------------------- */
		// in the center --> centerpanel
		this.centerPanel = new JPanel(new BorderLayout());
		centerPanel.setBorder(BorderFactory.createTitledBorder(
				Translatrix.getTranslationString("patient.incident.accident.invoice")));
		centerPanel.setOpaque(false);
		// a table for the invoices
		this.table = new JTable();

		this.scroll = new JScrollPane(table);
		table.setTableHeader(null);

		this.tableModel = new InvoiceTableModel();
		table.setModel(tableModel);
		/* ------------------------------------------------------- */
		table.setShowVerticalLines(false);
		table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setRowSelectionAllowed(true);
		/* ------------------------------------------------------- */
		table.getColumnModel().getColumn(0).setMinWidth(35);
		table.getColumnModel().getColumn(0).setMaxWidth(35);
		/* ------------------------------------------------------- */

		centerPanel.add(scroll, BorderLayout.CENTER);
		/* ------------------------------------------------------- */
		// select All Button
		this.selectAllButton = new JButton(Translatrix.getTranslationString("patient.all"));
		selectAllButton.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				/* ====================================================== */
				tableModel.toggleAllSelections();
				/* ====================================================== */
			}

		});

		selectAllButton.setMargin(new java.awt.Insets(0, 0, 0, 0));

		ButtonBarBuilder bb2 = new ButtonBarBuilder();
		bb2.addFixed(selectAllButton);
		bb2.addGlue();
		bb2.getPanel().setOpaque(false);


		/* ------------------------------------------------------- */
		// meta panel for insets
		JPanel bP = new JPanel(new BorderLayout(5, 5));
		bP.setOpaque(false);
		bP.add(new JLabel(""), BorderLayout.WEST);
		bP.add(new JLabel(""), BorderLayout.NORTH);
		bP.add(bb2.getPanel(), BorderLayout.CENTER);
		/* ------------------------------------------------------- */


		/* ------------------------------------------------------- */
		centerPanel.add(bP, BorderLayout.SOUTH);
		/* ------------------------------------------------------- */
		this.add(new JLabel(" "), BorderLayout.EAST);
		this.add(new JLabel(" "), BorderLayout.WEST);

		this.add(centerPanel, BorderLayout.CENTER);
		/* ====================================================== */
	}


	public List<Invoice> getSelectedInvoices() {
		/* ================================================== */
		return this.selectedInvoices;
		/* ================================================== */
	}

	/**
	 * @author martin.heinemann@tudor.lu
	 * 26.04.2007
	 * 10:39:42
	 *
	 *
	 * @version
	 * <br>$Log: AccidentInvoiceRelationDialog.java,v $
	 * <br>Revision 1.7  2008-10-21 09:53:34  hermen
	 * <br>fixed patient slot bug
	 * <br>enhanced logging
	 * <br>code cleanup
	 * <br>
	 * <br>Revision 1.6  2008-09-25 09:43:07  heinemann
	 * <br>fixed copyrights
	 * <br>
	 * <br>Revision 1.5  2008-01-22 13:51:52  heinemann
	 * <br>code cleanup and java doc
	 * <br>
	 * <br>Revision 1.4  2007/07/03 12:35:29  heinemann
	 * <br>system.out removed
	 * <br>
	 * <br>Revision 1.3  2007/05/25 13:50:25  heinemann
	 * <br>pres-weekend checkin
	 * <br>
	 * <br>Revision 1.2  2007/04/26 13:39:46  heinemann
	 * <br>*** empty log message ***
	 * <br>
	 * <br>Revision 1.1  2007/04/26 12:11:47  heinemann
	 * <br>change invoice accident data if accident data is changed in consultation
	 * <br>
	 *
	 */
	class InvoiceTableModel extends AbstractTableModel {

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

		private List<Invoice> data;
		private HashSet<Integer> unchecked;

		private DateFormat dFormat = DateFormat.getDateInstance(DateFormat.SHORT,
											Translatrix.getLocale());

		public InvoiceTableModel() {
			/* ================================================== */
			data  = new ArrayList<Invoice>();
			unchecked = new HashSet<Integer>();
			/* ================================================== */
		}


		/**
		 * Per default each invoice is in checked state
		 *
		 * @param newData
		 */
		public void setData(List<Invoice> newData) {
			/* ================================================== */
			this.data.clear();
			this.unchecked.clear();
			/* ------------------------------------------------------- */
			data.addAll(newData);
			fireTableDataChanged();
			/* ================================================== */
		}


		public int getColumnCount() {
			/* ====================================================== */
			return 2;
			/* ====================================================== */
		}

		public int getRowCount() {
			/* ====================================================== */
			return data.size();
			/* ====================================================== */
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.AbstractTableModel#setValueAt(java.lang.Object, int, int)
		 */
		@Override
		public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
			/* ====================================================== */
			// no changes for col 1
			if (columnIndex == 1)
				return;
			/* ------------------------------------------------------- */
//			if (!(aValue instanceof Boolean))
//				return;
			/* ------------------------------------------------------- */
			Boolean b = (Boolean) aValue;
			if (b)
				unchecked.remove(rowIndex);
			else
				unchecked.add(rowIndex);
			fireTableDataChanged();
			/* ====================================================== */
		}


		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getValueAt(int, int)
		 */
		public Object getValueAt(int rowIndex, int columnIndex) {
			/* ====================================================== */
			if (columnIndex == 0) {
				/* ------------------------------------------------------- */
				if (unchecked.contains(rowIndex) )
					return false;
				else
					return true;
				/* ------------------------------------------------------- */
			}
			else if (columnIndex == 1) {
//				 Need to flush the data out of the buffer.

				Invoice i = data.get(rowIndex);
				Formatter format = new Formatter();
				String s =  "No: " + i.getAccidentNumber() + " - "
							+dFormat.format(i.getAccidentDate()) + " - "
							+format.format ("%2.2f", i.getAmount()) + "€";
				format.flush ();
			    format.close ();
			    return s;
			}
			else
				return null;
			/* ====================================================== */
		}



		/**
		 *
		 * Returns the selected invoices
		 * @return
		 */
		public List<Invoice> getSelectedInvoices() {
			/* ================================================== */
			List<Invoice> returnList = new ArrayList<Invoice>();
			for (Invoice i : data) {
				if (!(unchecked.contains(data.indexOf(i))))
					returnList.add(i);
			}
			return returnList;
			/* ================================================== */
		}

		/**
		 * toggles the selection for all invoices.
		 * If only some are selected the selection will be set for all,
		 * iff all are selected the complete set is unselected
		 */
		public void toggleAllSelections() {
			/* ================================================== */
			if (unchecked.size() == data.size())
				unchecked.clear();
			else {
				// uncheck all
				for (Invoice i : data) {
					if (!(unchecked.contains(data.indexOf(i))))
						unchecked.add(data.indexOf(i));
				}
			}
			/* -------------------------------------------------- */
			fireTableDataChanged();
			/* ================================================== */
		}


		/* (non-Javadoc)
		 * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int)
		 */
		@Override
		public boolean isCellEditable(int rowIndex, int columnIndex) {
			/* ====================================================== */
			if (columnIndex == 0)
				return true;
			else return false;
			/* ====================================================== */
		}


		/* (non-Javadoc)
		 * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
		 */
		@Override
		public Class<?> getColumnClass(int columnIndex) {
			/* ====================================================== */
			if (columnIndex == 0)
				return Boolean.class;
			else
				return super.getColumnClass(columnIndex);
			/* ====================================================== */
		}





	}



}
