/*******************************************************************************
 * 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.office.gui.physicianmanagement;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Vector;

import javax.ejb.FinderException;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedLists;
import lu.tudor.santec.gecamed.core.gui.GECAMedLog;
import lu.tudor.santec.gecamed.core.gui.GECAMedMessage;
import lu.tudor.santec.gecamed.core.gui.GECAMedMessageListener;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.GECAMedTab;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.listener.MessageListenerRegister;
import lu.tudor.santec.gecamed.core.gui.widgets.GECAMedBaseDialog;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.gecamed.office.ejb.session.beans.OfficeManagerBean;
import lu.tudor.santec.gecamed.office.ejb.session.interfaces.OfficeManagerInterface;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.usermanagement.ejb.entity.beans.GecamedUser;
import lu.tudor.santec.gecamed.usermanagement.ejb.session.beans.UserAdminBean;
import lu.tudor.santec.gecamed.usermanagement.ejb.session.interfaces.UserAdminInterface;
import lu.tudor.santec.gecamed.usermanagement.gui.AdminModule;
import lu.tudor.santec.i18n.Translatrix;
import lu.tudor.santec.widgets.gui.ButtonFactory;

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

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

/**
 * JPanel with a table of all physicians and options to delete and create new
 * ones.
 *
 * @author Johannes Hermen johannes.hermen(at)tudor.lu
 *
 * @version <br>
 *          $Log: PhysicianManagementPanel.java,v $ <br>
 *          Revision 1.31 2013-12-27 18:09:26 donak <br>
 *          Cleanup of imports <br>
 *          <br>
 *          Revision 1.30 2013-07-15 06:18:37 ferring <br>
 *          logging changed <br>
 *          <br>
 *          Revision 1.29 2010-09-23 13:10:51 hermen <br>
 *          only create new calendar if physician is newly created <br>
 *          <br>
 *          Revision 1.28 2010-03-17 16:24:51 hermen <br>
 *          cleanup <br>
 *          <br>
 *          Revision 1.27 2010-03-12 14:17:42 hermen <br>
 *          cleanup of panel layouts and icons <br>
 *          <br>
 *          Revision 1.26 2009-06-02 12:52:59 hermen <br>
 *          added search for user/physician <br>
 *          <br>
 *          Revision 1.25 2008-10-02 15:09:41 heinemann <br>
 *          *** empty log message *** <br>
 *          <br>
 *          Revision 1.24 2008-09-25 09:43:08 heinemann <br>
 *          fixed copyrights <br>
 *          <br>
 *          Revision 1.23 2008-09-24 09:11:52 heinemann <br>
 *          added first run actions to gecamed. will disable all views except
 *          the ones of the admin tab for user, office and physician. <br>
 *          Tabs are enabled, if an physican was saved. <br>
 *          <br>
 *          Revision 1.22 2008-08-21 15:45:12 heinemann <br>
 *          removed the bogus behaviour when there is no office entry in the
 *          database. The fields on the print outs are now left blank. The user
 *          gets an information that the office address is missing. <br>
 *          <br>
 *          Revision 1.21 2008-05-29 10:07:51 hermen <br>
 *          added delete physician address <br>
 *          <br>
 *          Revision 1.20 2008-05-09 13:40:45 hermen <br>
 *          added physician address <br>
 *          <br>
 *          Revision 1.19 2008-04-08 09:52:33 heinemann <br>
 *          moved creation of new calendar from OfficeBean to AgendaModule <br>
 *          <br>
 *          Revision 1.18 2008-04-07 12:05:01 hermen <br>
 *          fire gecamedmessage on physician change <br>
 *          <br>
 *          Revision 1.17 2008-01-15 13:08:51 hermen <br>
 *          updated Javadoc and refactured codephysicianCollection.size()-1 <br>
 *
 */
public class PhysicianManagementPanel extends GECAMedTab {

	private static final long serialVersionUID = 1L;

	/**
	 * static logger for this class
	 */
	private static Logger logger = Logger.getLogger(PhysicianManagementPanel.class.getName());

	private JTable phyTable;
	private JButton editButton;
	private JButton newButton;
	private JButton deleteButton;
	private JButton reloadButton;

	private PhysicianTableModel tableModel;

	private OfficeManagerInterface manager;

	private boolean notBuild = true;

	private boolean isEnabled;

	private JTextField filterField;

	public static Boolean isOnScreen;
	Collection<Physician> physicianCollection;

	private JScrollPane pane;

	private PhysicianDataDialog physicianDataDialog;
	
	public PhysicianManagementPanel() {
		isOnScreen = false;

		this.setOpaque(false);
		
		Translatrix.addBundle("lu.tudor.santec.gecamed.office.gui.resources.WidgetResources");
		this.setTitle(Translatrix.getTranslationString("office.physicianmanagement"));
		
		this.setIcon(PatientManagerModule.getIcon(PatientManagerModule.PHYSICIAN));

		// Get the type manager
		this.manager = (OfficeManagerInterface) ManagerFactory.getRemote(OfficeManagerBean.class);

		if (notBuild) {
			buildPanel();
			notBuild = false;
		}

		reloadPhysicians();
		
		
	}

	private void reloadPhysicians() {
		physicianCollection = GECAMedLists.getListCopy(Physician.class);
		this.tableModel.setData(physicianCollection);

		filter();
	}

	/**
	 * adds the components to the panel
	 */
	private void buildPanel() {
		initComponents();
		try {
			phyTable.setRowSelectionInterval(0, 0);
		} catch (Exception ee) {
		}
		// build Layout
		FormLayout layout = new FormLayout("pref:grow, 3dlu, pref", "pref, 3dlu, pref, fill:10dlu:grow");
		this.setLayout(layout);
		CellConstraints cc = new CellConstraints();
		
		JPanel filterPanel = new JPanel(new BorderLayout());
		filterPanel.setOpaque(false);
		filterPanel.add(new JLabel("Search: "), BorderLayout.WEST);
		filterField = new JTextField();
		filterField.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				filter();
			}
		});
		filterPanel.add(filterField, BorderLayout.CENTER);
		this.add(filterPanel, cc.xy(1, 3));

		pane = new JScrollPane(this.phyTable);
		pane.setBackground(GECAMedColors.c_ScrollPaneBackground);
		pane.getViewport().setOpaque(false);
		this.add(pane, cc.xy(1, 4));

		JPanel bb = new JPanel(new FormLayout("pref", "pref,1dlu,pref,1dlu,pref,1dlu,pref,1dlu,pref:grow"));
		bb.setOpaque(false);
		bb.add(this.editButton, cc.xy(1, 1));
		bb.add(this.newButton, cc.xy(1, 3));
		bb.add(this.deleteButton, cc.xy(1, 5));
		bb.add(this.reloadButton, cc.xy(1, 7));

		this.add(bb, cc.xywh(3, 1, 1, 4));

	}

	protected void filter() {
		tableModel.getTextFilter().setFilter(filterField.getText());
		tableModel.setFilteringEnabled((filterField.getText().length() > 0), 7);
		tableModel.fireTableDataChanged();
		try {
			phyTable.setRowSelectionInterval(0, 0);
		} catch (Exception ee) {}
	}

	/**
	 * initializes the Components
	 */
	private void initComponents() {

		this.physicianDataDialog = new PhysicianDataDialog();

		this.tableModel = new PhysicianTableModel();

		
		this.phyTable = new JTable(this.tableModel);
		this.phyTable.setGridColor(this.phyTable.getBackground());
		this.phyTable.getColumnModel().getColumn(0).setMaxWidth(50);
		this.phyTable.getColumnModel().getColumn(0).setMinWidth(50);
		this.phyTable.getColumnModel().getColumn(1).setMaxWidth(100);
		this.phyTable.getColumnModel().getColumn(1).setMinWidth(100);
		this.phyTable.getColumnModel().getColumn(4).setMaxWidth(130);
		this.phyTable.getColumnModel().getColumn(4).setMinWidth(130);
		this.phyTable.getColumnModel().getColumn(5).setMaxWidth(130);
		this.phyTable.getColumnModel().getColumn(5).setMinWidth(130);
		
		// hidden search col.
		this.phyTable.getColumnModel().getColumn(7).setWidth(0);
		this.phyTable.getColumnModel().getColumn(7).setMinWidth(0);
		this.phyTable.getColumnModel().getColumn(7).setMaxWidth(0);
		
		PhysicianCellRenderer renderer = new PhysicianCellRenderer(tableModel);
		this.phyTable.getColumnModel().getColumn(0).setCellRenderer(renderer);
		this.phyTable.getColumnModel().getColumn(1).setCellRenderer(renderer);
		this.phyTable.getColumnModel().getColumn(2).setCellRenderer(renderer);
		this.phyTable.getColumnModel().getColumn(3).setCellRenderer(renderer);
		this.phyTable.getColumnModel().getColumn(4).setCellRenderer(renderer);
		this.phyTable.getColumnModel().getColumn(5).setCellRenderer(renderer);
		this.phyTable.getColumnModel().getColumn(6).setCellRenderer(renderer);
		
		this.phyTable.setRowHeight(20);
		this.phyTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				if (isEnabled) {
					deleteButton.setEnabled(true);
				}
			}
		});
		
		this.phyTable.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				// doubleclick --> open
				if (e.getClickCount() >= 2) {
					int row = phyTable.rowAtPoint(e.getPoint());
					phyTable.setRowSelectionInterval(row,  row);
					Physician p = tableModel.getPhysician(row);
					editPhysician(p);
				}
			}

		});

		this.newButton = ButtonFactory.createNarrowButton(GECAMedModule.getIcon(GECAMedIconNames.ADD_LINE));
		this.newButton.setToolTipText(Translatrix.getTranslationString("core.add"));
		this.newButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Physician p = new Physician();
				if (editPhysician(p)) {
					int lastRow = phyTable.convertRowIndexToView(tableModel.getRowCount() - 1);
					phyTable.setRowSelectionInterval(lastRow, lastRow);
					pane.getVerticalScrollBar().setValue(pane.getVerticalScrollBar().getMaximum());		
				}
			}
		});
		
		this.editButton = ButtonFactory.createNarrowButton(GECAMedModule.getIcon(GECAMedIconNames.EDIT));
		this.editButton.setToolTipText(Translatrix.getTranslationString("core.edit"));
		this.editButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int row = phyTable.getSelectedRow();
				Physician p = tableModel.getPhysician(row);
				editPhysician(p);
			}
		});
		this.editButton.setEnabled(false);
		
		this.deleteButton = ButtonFactory.createNarrowButton(GECAMedModule.getIcon(GECAMedIconNames.REMOVE_LINE));
		this.deleteButton.setToolTipText(Translatrix.getTranslationString("core.delete"));
		this.deleteButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Physician p = null;
				try {
					int row = phyTable.getSelectedRow();
					p = tableModel.getPhysician(row);
					deletePhysician(p);
				} catch (Exception e2) {
					logger.log(Level.WARN, "Error deleting Physician " + p + " : Physician could not be deleted\nhe might be still be used in old prescriptions etc..");
					JOptionPane.showMessageDialog(MainFrame.getInstance(),
							"Physician could not be deleted\nhe might be still be used in old prescriptions etc..",
							"Error deleting Physician", JOptionPane.ERROR_MESSAGE);
				}

				tableModel.fireTableDataChanged();
				try {
					phyTable.setRowSelectionInterval(0, 0);
				} catch (Exception ee) {
				}
			}
		});
		
		this.reloadButton = ButtonFactory.createNarrowButton(GECAMedModule.getIcon(GECAMedIconNames.RELOAD));
		this.reloadButton.setToolTipText(Translatrix.getTranslationString("core.reload"));
		this.reloadButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				reloadPhysicians();
			}
		});

		this.editButton.setHorizontalTextPosition(JLabel.RIGHT);
		this.editButton.setHorizontalAlignment(JLabel.LEFT);
		this.newButton.setHorizontalTextPosition(JLabel.RIGHT);
		this.newButton.setHorizontalAlignment(JLabel.LEFT);
		this.deleteButton.setHorizontalTextPosition(JLabel.RIGHT);
		this.deleteButton.setHorizontalAlignment(JLabel.LEFT);
		this.reloadButton.setHorizontalTextPosition(JLabel.RIGHT);
		this.reloadButton.setHorizontalAlignment(JLabel.LEFT);

	}

	protected boolean editPhysician(Physician p) {
		boolean create = !p.isPersistent();
		
		physicianDataDialog.setPhysician(p);
		physicianDataDialog.validate();
		int retVal = physicianDataDialog.showCenteredDialog();
		if (retVal == GECAMedBaseDialog.OK_OPTION) {
			p = physicianDataDialog.getData(p);
			
			try {
				p = manager.savePhysician(p);
				
				if (create) {
					GECAMedLog.system(AdminModule.MODULE_NAME, "Create Physician","Physician: " + p + " has been created");
					GECAMedMessage mes = new GECAMedMessage(AdminModule.getInstance(),
							MessageListenerRegister.MESSAGE_CREATE_NEW_CALENDAR, null, p);
					MainFrame.fireGECAMedMessage(mes);					
				} else {
					GECAMedLog.system(AdminModule.MODULE_NAME, "Update Physician","Physician: " + p + " has been changed");					
				}
				
				// replace in model.
				int index = tableModel.getData().indexOf(p);
				if (index >= 0) {
					tableModel.getData().set(index, p);
					tableModel.fireTableDataChanged();
				} else {
					tableModel.getData().add(p);
					filter();
				}
				
				
				int lindex = GECAMedLists.getListReference(Physician.class).indexOf(p);
				if (lindex >= 0) {
					GECAMedLists.getListReference(Physician.class).set(lindex, p);					
				} else {
					GECAMedLists.getListReference(Physician.class).add(p);
				}
				
				return true;
			} catch (Exception e1) {
				logger.log(Level.WARN, "saving physician failed");
			}
		}
		
		return false;
	}

	private void deletePhysician(Physician physician) throws Exception {
		if (physician == null)
			return;
		
		manager.deletePhysician(physician.getId());
		tableModel.getData().remove(physician);
		
		GECAMedLists.getListReference(Physician.class).remove(physician);
		GECAMedLists.notifyListeners(Physician.class);
		GECAMedLog.system(AdminModule.MODULE_NAME, "Delete Phyician", "Phyician: " + physician + " has been deleted");
		
		filter();
	}


	public void preparetoShowup() {
	}

	public void enablePanel(boolean b) {
		this.isEnabled = b;
		this.editButton.setEnabled(b);
		this.newButton.setEnabled(b);
		this.deleteButton.setEnabled(b);
		tableModel.fireTableDataChanged();
	}

	public void initList() {
		if(tableModel.getRowCount()>0){
			phyTable.setRowSelectionInterval(0, 0);
			
		}
	}

}
