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

import java.awt.BorderLayout;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.utils.GECAMedFocusTraversalPolicy;
import lu.tudor.santec.gecamed.core.gui.widgets.StatusBar;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.PatientAddress;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.PatientAdminBean;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.IPatientPermissions;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.PatientAdminInterface;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.patient.gui.PatientViewTab;
import lu.tudor.santec.i18n.Translatrix;

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

import com.jgoodies.forms.debug.FormDebugPanel;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;

/**
 * container panel for all administrative patient data panels
 *
 * @author Johannes Hermen johannes.hermen(at)tudor.lu
 *
 * @version
 * <br>$Log: PatientAdminPanel.java,v $
 * <br>Revision 1.42  2013-12-27 18:08:01  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.41  2013-07-15 06:18:34  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.40  2013-06-24 12:57:28  ferring
 * <br>eSante function button removed / out commented
 * <br>
 * <br>Revision 1.39  2013-06-10 08:22:14  ferring
 * <br>eSante POC
 * <br>
 * <br>Revision 1.38  2010-08-18 13:58:21  troth
 * <br>Add a small patient create dialog to Agenda-, Waitingroom- module | Incomplete - # 608: Agenda/Waitingroom
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/608
 * <br>
 * <br>Revision 1.37  2010-06-24 13:24:58  hermen
 * <br>Incomplete - # 402: Problem with billing adress copy in case of multiples adresses
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/402
 * <br>
 * <br>Revision 1.36  2009-10-01 13:49:13  hermen
 * <br>added physician panel to patient
 * <br>select CNS as default for new patient
 * <br>
 * <br>Revision 1.35  2009-05-29 13:51:21  hermen
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.34  2009-01-06 14:48:08  hermen
 * <br>small bugfixes
 * <br>
 * <br>Revision 1.33  2008-09-25 09:43:06  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.32  2008-06-05 10:14:18  hermen
 * <br>set Focus to panel if it gets visible
 * <br>
 * <br>Revision 1.31  2008-06-04 12:54:01  hermen
 * <br>fixed copy patient address to assure address
 * <br>
 * <br>Revision 1.30  2008-05-07 14:39:53  heinemann
 * <br>new waitingroom
 * <br>
 * <br>Revision 1.29  2008-04-16 14:26:14  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.28  2008-04-16 14:24:28  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.27  2008-03-20 16:08:14  heinemann
 * <br>*** empty log message ***
 * <br>
 * <br>Revision 1.26  2008-03-12 10:30:06  hermen
 * <br>changed PatientViewTab to abstract and added getName() method
 * <br>
 * <br>Revision 1.25  2008-01-21 14:03:27  hermen
 * <br>updated Javadoc and refactured code
 * <br>
 *
 */
public class PatientAdminPanel extends PatientViewTab 
{
	
	public static final String NAME 		 = "ADMIN_PANEL";
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(PatientAdminPanel.class.getName());
    
    private static final long serialVersionUID 	= 1L;
  
    //~ Instance fields ========================================================

    private Patient currentPatient;
    private PatientAdminInterface manager;
    private Vector<IPatientDataPanel> panels 	= new Vector<IPatientDataPanel>();
	private boolean editable;
	
//	private JButton eSanteRepositoryButton;

	private GECAMedFocusTraversalPolicy focusPolicy;

    //~ Constructors ===========================================================

    public PatientAdminPanel(String[] enabledPanels)
    {
    	this.setOpaque(false);
    	
    	this.setTitle(Translatrix.getTranslationString("pm.administrativeData"));
    	this.setIcon(PatientManagerModule.getIcon(PatientManagerModule.PATIENT_ADMINSTRATIVE));
        // build the Panel
        this.buildPanel(enabledPanels);
    }

    //~ Methods ================================================================
    /**
     * returns the current shown Patient
     *
     * @return the current shown Patient
     */
    public Patient getPatient() {
        return this.currentPatient;
    }
    
    
	/* (non-Javadoc)
	 * @see lu.tudor.santec.gecamed.core.gui.GECAMedTab#enableTab()
	 */
	@Override
	public void enableTab() {
		/* ============================================= */
//		 check permissions
		// view history
		if (GECAMedModule.userHasPermission(IPatientPermissions.VIEW_ADMINISTRATIVE)
				|| GECAMedModule.userHasPermission(IPatientPermissions.EDIT_ADMINISTRATIVE)) {
			super.enableTab();
		}
		else
			super.disableTab();
		/* ============================================= */
	}
    

    /**
     * collect the values from the Panel and save them to db
     */
    public void saveData() {
        StatusBar.getInstance().setProgress(Translatrix.getTranslationString(
                "pm.savingPatient"), 0); 
        
    	for (Iterator<IPatientDataPanel> iter = panels.iterator(); iter.hasNext();) {
			IPatientDataPanel element = (IPatientDataPanel) iter.next();
			element.getPatient(currentPatient);
		}

    	// if new Patient
        if (! currentPatient.isPersistent()) {
        	StatusBar.getInstance().setProgress(Translatrix.getTranslationString(
            "pm.creatingNewPatient"), 80); 
            logger.info(Translatrix.getTranslationString("pm.creatingNewPatient: ") +  
            		this.currentPatient.getSurName());
        	//  for new Patient set creationdate and creator
            this.currentPatient.setCreationDate(new Date());
        }
        // save Patient
        try {
        	// set Status to ACTIVE
        	Integer oldStatus = currentPatient.getStatus();
            this.currentPatient.setStatus(Patient.STATUS_ACTIVE);	
			this.currentPatient = manager.savePatient(currentPatient);
			if (oldStatus != null && !oldStatus.equals(currentPatient.getStatus()))
				logger.info("Status of patient changed to \"" + currentPatient.getStatusName() + "\"");
		} catch (Exception e1) {
			MainFrame.reportServerError(e1);
		}
    }

    /**
	 * sets the current shown Patient
	 */
    public void setPatient(Patient patient) {
    	long start = System.currentTimeMillis();
    	/* ------------------------------------------------------ */
    	// check permissions
  		this.currentPatient = patient;
   		if (GECAMedModule.userHasPermission(IPatientPermissions.EDIT_ADMINISTRATIVE)) {
    				this.setEnabled(true);
    				this.editable = true;
   		}
   		else {
    			this.setEnabled(false);
    			this.editable = false;    			
   		}
    	/* ------------------------------------------------------ */
   		
   		// disallow 
    	if (!patient.isPersistent() && ! GECAMedModule.userHasPermission(IPatientPermissions.CREATE_PATIENT)) {
			this.setEnabled(false);
			this.editable = false;    
    	}
    	
    	
    	for (Iterator<IPatientDataPanel> iter = panels.iterator(); iter.hasNext();) {
			IPatientDataPanel element = (IPatientDataPanel) iter.next();
			element.setPatient(currentPatient, editable);
		}
        this.setModified(false);
        
        logger.info("loading Administrative Data for " + patient.toString() + " took: "+ (System.currentTimeMillis()-start) + "ms");
    }

    /**
     * adds the components to the panel
     */
    @SuppressWarnings("deprecation")
    private void buildPanel(String[] enabledPanels) {
        initComponents(enabledPanels);

        JPanel jp = new JPanel();
        
        FormLayout layout = new FormLayout("5dlu,fill:40dlu:grow,5dlu,fill:40dlu:grow, 5dlu,fill:40dlu:grow, 5dlu,fill:40dlu:grow,5dlu,fill:40dlu:grow, 5dlu,fill:40dlu:grow, 5dlu", "5dlu");
        jp.setLayout(layout);
        CellConstraints cc = new CellConstraints();
        
        // add Panels
        
        int col = -1;
        
        // start at row 2
        int row = 2;
        int span = 11;
//    	for (Iterator iter = panels.iterator(); iter.hasNext();) {
        if (panels != null) {
        	for (int i = 0; i < panels.size(); i++) {
        		try {
        			IPatientDataPanel elem = panels.elementAt(i);
//        	    	for (IPatientDataPanel elem : panels) {
        	    		/* ------------------------------------------------------- */
        	    		if (isFullSize(elem)) {
        	    			/* ------------------------------------------------------- */
        	    			// create a new row
        	    			layout.appendRow(new RowSpec("fill:pref"));
        	    			layout.appendRow(new RowSpec("5dlu"));
        	    			// we use the whole row for the element
            				jp.add((JPanel) elem, cc.xyw(2, row, 11));
            				// store 
            				col = -1;
            				row += 2;
        	    			/* ------------------------------------------------------- */
        	    		} else {
        	    			/* ------------------------------------------------------- */
        	    			if (col == -1) {
        	    				
        	    				/* ------------------------------------------------------- */
        	    				// if the last one was full size, we are going
        	    				// to place the current in the first column only
        	    				
        	    				// create a new row
        		    			layout.appendRow(new RowSpec("fill:pref"));
        		    			layout.appendRow(new RowSpec("5dlu"));
        		    			try {
        		    				if (panels.size()> i+1 && !isFullSize(panels.elementAt(i+1))) {
        		    					span = 5;
        		    					if (panels.size() > i+2 && !isFullSize(panels.elementAt(i+2))) {
        		    						span = 3;
        		    					}
        		    				} else {
        		    					span = 11;
        		    				}							
        						} catch (Exception e) {
        							logger.warn("Error calculating Panel Spaning!", e);
        							span = 3;
        						}
        		    			
        		    			// add in the column
        		    			jp.add((JPanel) elem, cc.xyw(2, row, span));
        		    			// store infos
        		    			col = 1;
        		    			row += 2;
        	    				/* ------------------------------------------------------- */
        	    			} else if (col == 1){
        	    				/* ------------------------------------------------------- */
        	    				// place the current half size in the second column
        	    				row -= 2;
        	    				jp.add((JPanel) elem, cc.xyw(3+span, row, span));
        	    				// reset info
        	    				col = 2;
        	    				row += 2;
        	    				/* ------------------------------------------------------- */
        	    			} else if (col == 2){
        	    				/* ------------------------------------------------------- */
        	    				// place the current half size in the second column
        	    				row -= 2;
        	    				jp.add((JPanel) elem, cc.xyw(4+(2*span), row, span));
        	    				// reset info
        	    				col = -1;
        	    				row += 2;
        	    				/* ------------------------------------------------------- */
        	    			}
        	    			/* ------------------------------------------------------- */
        	    		}
        				/* ------------------------------------------------------- */
				} catch (Exception e) {
					logger.error("Error adding Panel!", e);
				}
        	}
        		
        }
        jp.setOpaque(false);
        
        this.setLayout(new BorderLayout());
        JScrollPane pane = new JScrollPane(jp);
        pane.setOpaque(false);
        pane.getViewport().setOpaque(false);
        this.add(pane, BorderLayout.CENTER);
        /* ------------------------------------------------------- */
        // install the focus thing
        /* ------------------------------------------------------- */
        this.focusPolicy = new GECAMedFocusTraversalPolicy();
        /* ------------------------------------------------------- */
        if (panels != null) {
	    	for (IPatientDataPanel elem : panels) {
	    		/* ------------------------------------------------------- */
	    		focusPolicy.add(elem.getComponentsForFocus());
	    		/* ------------------------------------------------------- */
	    	}
        }
        /* ------------------------------------------------------- */
        
//        eSanteRepositoryButton = new JButton(new BrowseRepository())
//        {
//			private static final long	serialVersionUID	= -912679721167084824L;
//
//			@Override
//        	public void setEnabled (boolean b)
//        	{
//        		if (b && currentPatient != null
//        				&& currentPatient.getIdLuxembourg() != null 
//        				&& currentPatient.getIdLuxembourg().trim().length() > 0)
//        			super.setEnabled(true);
//        		else
//        			super.setEnabled(false);
//        	}
//        };
//        eSanteRepositoryButton.setHorizontalAlignment(SwingConstants.LEFT);
//        eSanteRepositoryButton.setEnabled(true);
//        eSanteRepositoryButton.setToolTipText(Translatrix.getTranslationString("Open the eSanté document repository of this patient"));
//        eSanteRepositoryButton.setIconTextGap(3);
//        eSanteRepositoryButton.setFont(GECAMedFonts.BUTTON_FONT);
//        eSanteRepositoryButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
        
//        this.addComponentListener(new ComponentAdapter() {
//
//        	
//        	private FocusTraversalPolicy originalPolicy = null;
//        	
//			/* (non-Javadoc)
//			 * @see java.awt.event.ComponentAdapter#componentHidden(java.awt.event.ComponentEvent)
//			 */
//			@Override
//			public void componentHidden(ComponentEvent e) {
//				/* ====================================================== */
//				/* ------------------------------------------------------- */
//				// set the default
//				/* ------------------------------------------------------- */
//				if (originalPolicy != null)
//					MainFrame.getInstance().setFocusTraversalPolicy(originalPolicy);
//				/* ====================================================== */
//			}
//
//			/* (non-Javadoc)
//			 * @see java.awt.event.ComponentAdapter#componentShown(java.awt.event.ComponentEvent)
//			 */
//			@Override
//			public void componentShown(ComponentEvent e) {
//				/* ====================================================== */
//				// save the default
//				/* ------------------------------------------------------- */
//				originalPolicy = MainFrame.getInstance().getFocusTraversalPolicy();
//				/* ------------------------------------------------------- */
//				// set the new
//				/* ------------------------------------------------------- */
//				MainFrame.getInstance().setFocusTraversalPolicy(PatientAdminPanel.this.focusPolicy);
//				/* ====================================================== */
//			}
//        	
//        });
		/* ================================================== */
    }
    
    
    /**
     * checks if the component needs a complete row
     * or can share with another
     * @param comp
     * @return
     */
    private boolean isFullSize(Object comp) {
    	/* ================================================== */
//    	if (comp instanceof PatientGeneralDataPanel)
//    		return true;
    	if (comp instanceof PatientBasicAdminInfoPanel)
    		return true;
    	// phone
    	if (comp instanceof PatientPhoneInfo)
    		return false;
    	// billing address
    	if (comp instanceof PatientContactInfo)
    		return false;
    	// addresses
    	if (comp instanceof PatientAddressInfo)
    		return true;
    	// family
    	if (comp instanceof PatientFamilyPanel)
    		return true;
    	// user infos
    	if (comp instanceof PatientAddressInfo)
    		return true;
    	if (comp instanceof PatientRemarks)
    		return false;
    
    	return true;
		/* ================================================== */
    }
    

    /**
     * initialises the Components
     */
    @SuppressWarnings("unchecked")
    private void initComponents(String[] enabledPanels)
    {
		 // Get the type manager
		manager = (PatientAdminInterface) ManagerFactory.getRemote(PatientAdminBean.class);
    	
    	
		if (enabledPanels == null) {
			// create all optional modules
			enabledPanels = PatientManagerModule.getInstance().administrativeElementsPlugin.getEnabledElements().split(" ");
		}
		
		Object[] oArr = {this};
		Class[] cArr = {this.getClass()};
		for (int i = 0; i < enabledPanels.length; i++) {
			 // get the class
            try {
            	if (enabledPanels[i].trim().equals(""))
            		continue;
				Class l_class = Class.forName(enabledPanels[i]);
                Constructor l_constructor = l_class.getConstructor(cArr);
                IPatientDataPanel l_panel = (IPatientDataPanel) l_constructor.newInstance(oArr);
                panels.add(l_panel);
			} catch (Exception e) {
				logger.log(Level.WARN, "The panel: " + enabledPanels[i] + "could not be loaded", e);
				
			}
		}

    }

	public boolean isFilledOK() {
		boolean ok = true;
		for (Iterator iter = panels.iterator(); iter.hasNext();) {
		    IPatientDataPanel panel = (IPatientDataPanel) iter.next();
			if (! panel.isFilledOK()) {
			    ok = false;
			}
		}
		return ok;
	}

	@Override
	public String getName() {
		return NAME;
	}
	
	
	public PatientAddress getPatientAddress() {
	    try {
		PatientAddress pa = new PatientAddress();
		for (Iterator<IPatientDataPanel> iter = panels.iterator(); iter.hasNext();) {
		    IPatientDataPanel element = (IPatientDataPanel) iter.next();
		    if (element instanceof PatientBasicAdminInfoPanel) {
			((PatientBasicAdminInfoPanel) element).getAddress(pa);
		    }
		}
		return pa;		
	    } catch (Exception e) {
		return null;
	    }
	}
	
	public void afterShowup() {
	    try {
		for (Iterator<IPatientDataPanel> iter = panels.iterator(); iter.hasNext();) {
		    IPatientDataPanel element = (IPatientDataPanel) iter.next();
		    if (element instanceof PatientBasicAdminInfoPanel) {
			((PatientBasicAdminInfoPanel) element).getFocus();
		    }
		}
	    } catch (Exception e) {}
	}
	
	
	@Override
	public Collection<JComponent> getActionComponents ()
	{
		List<JComponent> components = new ArrayList<JComponent>(1);
//		components.add(eSanteRepositoryButton);
		return components;
	}
	
	
//	public void enableESanteRepositoryButton (boolean enable)
//	{
//        eSanteRepositoryButton.setEnabled(enable);
//	}
}
