/*****************************************************************************
 *                                                                           *
 *  Copyright (c) 2010 by SANTEC/TUDOR www.santec.tudor.lu                   *
 *                                                                           *
 *                                                                           *
 *  This library is free software; you can redistribute it and/or modify it  *
 *  under the terms of the GNU Lesser General Public License as published    *
 *  by the Free Software Foundation; either version 2 of the License, or     *
 *  (at your option) any later version.                                      *
 *                                                                           *
 *  This software 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 along with this library; if not, write to the Free Software      *
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  *
 *                                                                           *
 *****************************************************************************/
package lu.tudor.santec.gecamed.prescription.gui.editor;

import java.awt.Window;
import java.util.Date;
import java.util.Vector;

import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
import javax.swing.text.SimpleAttributeSet;

import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.GECAMedOptionPane;
import lu.tudor.santec.gecamed.core.gui.utils.WindowToolbox;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Incident;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.IncidentEntry;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.patient.gui.PatientPanel;
import lu.tudor.santec.gecamed.prescription.ejb.entity.beans.Prescription;
import lu.tudor.santec.gecamed.prescription.ejb.session.beans.PrescriptionManagerBean;
import lu.tudor.santec.gecamed.prescription.ejb.session.interfaces.PrescriptionManager;
import lu.tudor.santec.gecamed.prescription.gui.util.PrescriptionUtils;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Logger;

/**
 * The datamodel for the prescription. Contains all functions to save, modify and delete the prescriptions.
 *  
 * @author Thorsten Roth thorsten.roth(at)tudor.lu
 *
 * @version
 * <br>$Log: PrescriptionDataModel.java,v $
 * <br>Revision 1.24  2013-12-27 18:09:24  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.23  2013-09-23 09:30:43  ferring
 * <br>eSante: saving document data in database
 * <br>
 * <br>Revision 1.22  2013-09-23 06:48:36  ferring
 * <br>NOW it should all be UTF-8
 * <br>
 * <br>Revision 1.21  2013-09-23 06:46:57  ferring
 * <br>should now be UTF-8 file
 * <br>
 * <br>Revision 1.20  2013-07-15 06:18:35  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.19  2010-11-26 16:50:41  troth
 * <br>Complete - # 682: Mehrfache Wiederverschreibungen nicht mehr möglich in Release 1.1.01
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/682
 * <br>
 * <br>Revision 1.18  2010-10-11 08:47:38  troth
 * <br>add revised UndoTextArea/UndoTextField to the text fields in consultations view
 * <br>
 * <br>Revision 1.17  2010-09-06 14:29:21  troth
 * <br>Incomplete - # 625: Unfalldatum nicht angezeigt in Dialog-Verschreibungsfenster
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/625
 * <br>
 * <br>Revision 1.16  2010-09-02 13:09:51  troth
 * <br>Incomplete - # 621: Fehlerhafter Speicherverhalten beim Erstellen von Verschreibung in Dialogfenster
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/621
 * <br>
 * <br>Revision 1.15  2010-09-02 12:28:14  troth
 * <br>Incomplete - # 621: Fehlerhafter Speicherverhalten beim Erstellen von Verschreibung in Dialogfenster
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/621
 * <br>
 * <br>Revision 1.14  2010-08-16 14:32:04  troth
 * <br>Incomplete - # 599: Keep prescription history stable when consultation tabs are clicked
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/599
 * <br>
 * <br>Revision 1.13  2010-07-28 12:39:52  troth
 * <br>fix bug now line of the open prescription entry in the history table of every open prescriptionpanel is colored not only the current.
 * <br>
 * <br>Revision 1.12  2010-07-20 14:18:49  troth
 * <br>add function for colored the line of the open prescription entry in the history table
 * <br>
 * <br>Revision 1.11  2010-06-14 12:20:49  troth
 * <br>Bug Fix - when open  prescription dialog a incident have save without any entries
 * <br>
 * <br>Revision 1.10  2010-05-27 12:22:13  troth
 * <br>Incomplete - # 516: Erzeugen leerer Verschreibungen mit der Druck-Funktion
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/516
 * <br>Incomplete - # 517: Falsche Aktion im Speicher-Dialog für Verschreibungen beim Schliessen des Dialog-Fensters
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/517
 * <br>
 * <br>Revision 1.9  2010-05-26 16:33:34  troth
 * <br>bugfix - change the way to get a new and create a incident. rename the method getRecentIncident() in class PatientPanel to getCurrentIncident()
 * <br>
 * <br>Revision 1.8  2010-05-26 12:13:44  troth
 * <br>fix bug - incident witch is no accident and has no attached IncidentEntries have been save trigger from the prescription editor
 * <br>
 * <br>Revision 1.7  2010-05-19 15:13:56  troth
 * <br>fix characteristics of the savedialog cancel action - Incomplete - # 492: Verwirrendes Verhalten der Cancel Funktion im Speicherdialog
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/492
 * <br>
 * <br>Revision 1.6  2010-05-18 13:20:35  troth
 * <br>fix save function of represcribe - Incomplete - # 504: Kein direktes Abspeichern nach Neuverschreibung möglich
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/504
 * <br>
 * <br>Revision 1.5  2010-05-17 15:24:34  troth
 * <br>Incomplete - # 491: Inkonsistenter Zustand nach Löschen einer verschreibung
 * <br>http://santec.tudor.lu/trac/gecamed/ticket/491
 * <br>
 * <br>Revision 1.4  2010-05-10 15:09:07  troth
 * <br>add template search function in template dialog
 * <br>
 * <br>Revision 1.3  2010-05-07 08:59:35  troth
 * <br>edit call of function getRecentIncident() because the function getRecentIncident() move from class PrescriptionDataModel to PatientPanel
 * <br>
 * <br>Revision 1.2  2010-04-27 10:00:58  troth
 * <br>special  character for quantities array
 * <br>
 * <br>Revision 1.1  2010-04-26 16:51:09  troth
 * <br>Redesign of the prescription view - all prescription class and new package
 * <br>
 */
public class PrescriptionDataModel implements DocumentListener {

	private Document currentPrescriptionDocument = new PlainDocument();
	
	private PrescriptionManager manager;
	
	private static Logger m_Logger = Logger.getLogger ("lu.tudor.santec.gecamed.patient.gui.history");
	
	private PatientPanel patientPanel;
	
	private Prescription currentPrescription;

	private boolean prescriptionModified;

	private Vector<PrescriptionDataPanel> prescriptionPanels = new Vector<PrescriptionDataPanel>();

	private Patient patient;
	
	//private PrescriptionDataPanel prescriptionDataPanel;

	/**
	 * @param panel the patient panel
	 */
	public PrescriptionDataModel(PatientPanel patientPanel) {
		this.patientPanel = patientPanel;

		this.currentPrescriptionDocument.addDocumentListener(this);
		
		try {
 			manager = (PrescriptionManager) ManagerFactory.getRemote(PrescriptionManagerBean.class);
 			}
 		catch (Exception p_Exception)
 			{
 			m_Logger.warn(p_Exception.getLocalizedMessage());
 			}
 		
 		this.prescriptionModified = false;
	}


	/**
	 * Creates a new instance of the prescriptionpanel with this model.
	 * 
	 * @return a prescriptionpanel     
	 */
	public JPanel getPrescriptionPanelView(boolean isPanel) {
//		this.prescriptionDataPanel = new PrescriptionDataPanel(isPanel, this, this.patientPanel);
//		return this.prescriptionDataPanel;
		JPanel panel = new PrescriptionDataPanel(isPanel, this, this.patientPanel);
		return panel;
	}
	
	
	/**
	 * Creates a new instance of the prescriptiondialog with this model.
	 * 
	 * @return a prescriptiondialog
	 */
	public PrescriptionDataDialog getPrescriptionDialog() {
		PrescriptionDataDialog dialog = new PrescriptionDataDialog(this);
		return dialog;
	}

	
	/**
	 * set the selected patient
	 * @param patient the selected patient
	 */
	public void setPatient(Patient patient) {
		
		if (patient != null && patient.equals(this.patient))
			return;
		
		this.patient = patient;
		
		setPrescription(new Prescription());
		m_Logger.info("loading ImportantPatientdata for patientID  " + patient.getId());
	}
	
	
	/**
	 * set the selected prescription to the datamodel and all instances of prescriptionpanels/prescriptiondialogs.
	 * it shows a savedialog if the current prescription is not save.
	 * 
	 * @param prescription the selected prescription 
	 */
	public void setPrescription(Prescription prescription) {
				
		if(this.showPrescriptionSaveDialog(this.getActivePanel(), prescription)) {
			
			//this.currentPrescription = prescription;
			try {
				this.currentPrescriptionDocument.remove(0,
				this.currentPrescriptionDocument.getLength());
				this.currentPrescriptionDocument.insertString(
						0,
						currentPrescription.getTextContent(),
						new SimpleAttributeSet());
			} catch (BadLocationException e) {
				e.printStackTrace();
			}
			for (PrescriptionDataListener listener : prescriptionPanels) {
				listener.setPrescription(this.currentPrescription);
			}
			prescriptionChanged(false);
		}
	}
	
	public void updatePrescriptionPannels()
	{
		//this.currentPrescription = prescription;
		
		for (PrescriptionDataListener listener : prescriptionPanels) {
			listener.setPrescription(this.currentPrescription);
		}
	}
	
	/**
	 * Save all prescriptions for the current consultation
	 */
	public Prescription saveData() {		
		
		if(currentPrescriptionDocument.getLength() <= 0)
			return null;
		
		Incident incident;
		// check if currentPrescription has a incident
		// if not make a new one
		if(currentPrescription.getIncidentId() != null)
		{
			incident = currentPrescription.getIncidentEntry().getIncident();
		} else {
			incident = PatientManagerModule.getInstance().getPatientPanel().getCurrentIncident();
		}
		
		this.getActivePanel().updatePrescription(incident);
		
		// if the incident is not a accident
//		if (!incident.getIsAccident()) {
//			incident.setAccidentDate(currentPrescription.getAccidentDate());
//			incident.setAccidentNr(currentPrescription.getAccidentNr));
//		}
		
		// as prescriptions can not be modified, we mustn't check
		// whether the prescriptions is persistant or not
		// just do it =)
		if (incident != null && incident.isPersistent()) {
			if (currentPrescription != null) {
				currentPrescription.setIncidentId(incident.getId());
				// fill with static data, patient name, address, physician etc
				PrescriptionUtils.fillStaticData(currentPrescription, GECAMedModule.getCurrentPatient());
			}
			try {
				currentPrescription = manager.savePrescription(currentPrescription);
				prescriptionChanged(false);
				
				// set new prescription id to the renderer of all panels
				IncidentEntry incidentEntry = currentPrescription.getIncidentEntry();
				if(incidentEntry != null) {
					for (PrescriptionDataPanel prescriptionPanel : prescriptionPanels) {
						prescriptionPanel.getPrescriptionHistoryView().highlightEntry(incidentEntry);
					}
				}
				
				new Thread() {
					public void run() {
						PatientManagerModule.getInstance().getPatientPanel().reloadHistory();						
					}
				}.start();
				//PatientManagerModule.getInstance().getPatientPanel().reloadHistory();
				return currentPrescription;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		return null;
	}

	/**
	 * get the current prescription
	 * @return the current prescription
	 */
	public Prescription getPrescription() {
		return this.currentPrescription;
	}
	
	/**
	 * get the current prescription document
	 * @return the current prescription document
	 */
	public Document getCurrentPrescriptionDocument()
	{
		return this.currentPrescriptionDocument;
	}
	
	/**
	 * set the current prescription document
	 * @param currentPrescriptionDocument
	 */
	public void setCurrentPrescriptionDocument(Document currentPrescriptionDocument)
	{
		this.currentPrescriptionDocument = currentPrescriptionDocument;
	}

	public Date getCurrentPrescriptionDate()
	{
		return this.currentPrescription.getPrescriptionDate();
	}
	/* (non-Javadoc)
	 * @see javax.swing.event.DocumentListener#changedUpdate(javax.swing.event.DocumentEvent)
	 */
	public void changedUpdate(DocumentEvent e) {
		prescriptionChanged(this.currentPrescriptionDocument.getLength() != 0);
	}
	public void insertUpdate(DocumentEvent e) {
		prescriptionChanged(this.currentPrescriptionDocument.getLength() != 0);
	}
	public void removeUpdate(DocumentEvent e) {
		prescriptionChanged(this.currentPrescriptionDocument.getLength() != 0);
	}

	/**
	 * set the prescription textcontent, the modify mode. 
	 * 
	 * @param changed if true prescription modify else prescription save
	 */
	public void prescriptionChanged(boolean changed) {
		if (changed) {
			try {
				this.currentPrescription.setTextContent(
						this.currentPrescriptionDocument.getText(0, 
								this.currentPrescriptionDocument.getLength()));				
			} catch (Exception e) {
				e.printStackTrace();
			}
			this.prescriptionModified = true;
			for (PrescriptionDataPanel listener : prescriptionPanels) {
				listener.prescriptionModified();
			}
		} else {
			this.prescriptionModified = false;
			for (PrescriptionDataPanel listener : prescriptionPanels) {
				listener.prescriptionSaved();
			}	
		}
	}

	/**
	 * add all created prescriptionpanel to the prescriptiondatamodel to update the panels if prescription modify, save or close.
	 * 
	 * @param listener 
	 */
	public void addModelListener(PrescriptionDataPanel listener) {
		this.prescriptionPanels.add(listener);
	}


	/**
	 * check if a prescription is modified
	 * 
	 * @return true if a prescription is modify
	 */
	public boolean isPrescriptionModified() {
		return this.prescriptionModified;
	}
	
	/**
	 * show the prescription savedialog  
	 * 
	 * @param prescriptionDataPanel parentpanel of dialog
	 */
	public boolean showPrescriptionSaveDialog(PrescriptionDataPanel prescriptionDataPanel, Prescription prescription)
	{
		if(this.isPrescriptionModified())
		{
			int result = GECAMedOptionPane.showConfirmDialog(
					prescriptionDataPanel.getParent(),
					Translatrix.getTranslationString("prescription.saveDialog.text"),
					Translatrix.getTranslationString("prescription.saveDialog.title"),
					GECAMedOptionPane.YES_NO_CANCEL_OPTION);
			
			if(result == GECAMedOptionPane.YES_OPTION) {
				// prescriptionDataPanel.updatePrescription();
				this.saveData();
				return true;
			}

			if(result == GECAMedOptionPane.NO_OPTION) {
			
			}
			
			if(result == GECAMedOptionPane.CANCEL_OPTION || result == GECAMedOptionPane.CLOSED_OPTION) {
				prescriptionChanged(true);
				return false;
			}
		}else{
			
		}
		this.currentPrescription = prescription;
		return true;
	}

	
	/**
	 * get the active prescriptionpanel
	 *  
	 * @return the active prescriptionpanel
	 */
	private PrescriptionDataPanel getActivePanel() {
		for (PrescriptionDataPanel prescriptionPanel : prescriptionPanels) {
			Window parent = WindowToolbox.getOwnerFrame(prescriptionPanel);
			if (parent instanceof JDialog && parent.isVisible())
				return prescriptionPanel;
		}
		for (PrescriptionDataPanel prescriptionPanel : prescriptionPanels) {
			if (prescriptionPanel.isVisible())
				return prescriptionPanel;
		}
		return null;
	}
	
	public void setScrollPaneValue(int value, int maximum)
	{
		for (PrescriptionDataPanel prescriptionPanel : prescriptionPanels) {
			prescriptionPanel.setScollPaneValue(value, maximum);
		}
	}
}
