package lu.tudor.santec.gecamed.agenda.utils;

import java.awt.EventQueue;

import javax.swing.JFrame;

import lu.tudor.santec.gecamed.agenda.ejb.entity.beans.AgendaCalendar;
import lu.tudor.santec.gecamed.agenda.ejb.entity.beans.Appointment;
import lu.tudor.santec.gecamed.agenda.ejb.entity.beans.AppointmentType;
import lu.tudor.santec.gecamed.agenda.ejb.session.beans.AppointmentManagerBean;
import lu.tudor.santec.gecamed.agenda.ejb.session.interfaces.AppointmentManager;
import lu.tudor.santec.gecamed.core.ejb.entity.beans.GECAMedEntityBean;
import lu.tudor.santec.gecamed.core.gui.utils.GECAMedGuiUtils;
import lu.tudor.santec.gecamed.core.test.TestUtils;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.PatientStub;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.PatientAdminBean;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.PatientAdminInterface;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.jtimechooser.JTimeChooser;

import javax.swing.JList;
import javax.swing.JOptionPane;

import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import javax.swing.JLabel;
import javax.swing.SwingConstants;

import com.sun.star.report.FormattedField;
import com.toedter.calendar.JDateChooser;

import javax.ejb.EJB;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.event.ChangeListener;

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

import javax.swing.event.ChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JTextField;
import javax.swing.JPanel;
import java.awt.Color;
import javax.swing.JTextPane;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class AppointmentsGeneratorGUI {

	private static Logger logger = Logger.getLogger(AppointmentsGeneratorGUI.class.getName());
	
	private JFrame frame;
	private JList<String> list;
	private JSpinner spinner;
	private AppointmentManager appointmentManager;
	private Collection<AgendaCalendar> col;
	private Collection<AppointmentType> appTypes;
	private JDateChooser chooser1;
	private JDateChooser chooser2;
	private JTimeChooser startTime;
	private JTimeChooser endTime;
	private JTextPane textPane;
	private JList appointmentsList;
	private AgendaCalendar selectedCalendar;
	private AppointmentType selectedAppType;
	private PatientAdminInterface patientAdminInterface;
	private ArrayList<PatientStub> patientCol;
	//Duration of an event in minutes
	int eventDuration=0;
	Boolean timeIsValid=false;
	
	
	
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					AppointmentsGeneratorGUI window = new AppointmentsGeneratorGUI();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public AppointmentsGeneratorGUI() {
	
		initialize();
		textPane.setText("Initializing...");
		try
		{
			start();
			textPane.setText(textPane.getText()+"\nFetch Start ");
			fetchCalendars();
			fetchPatients();
			textPane.setText(textPane.getText()+"\nFetch Complete ");
		
		}
		catch(Exception ex)
		{
			textPane.setText(textPane.getText()+"\nEXCEPTION : "+ex.getMessage());
		}
		
		
		
		
		
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 450, 567);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(null);
		
		JLabel lblPleaseSelectAn = new JLabel("Select Agenda");
		lblPleaseSelectAn.setHorizontalAlignment(SwingConstants.LEFT);
		lblPleaseSelectAn.setBounds(26, 6, 208, 16);
		frame.getContentPane().add(lblPleaseSelectAn);
		
		
		JLabel lblOptions = new JLabel("Options");
		lblOptions.setBounds(250, 6, 61, 16);
		frame.getContentPane().add(lblOptions);
		
		JLabel lblStart = new JLabel("Start");
		lblStart.setBounds(250, 50, 61, 16);
		frame.getContentPane().add(lblStart);
		
		JLabel lblEnd = new JLabel("End");
		lblEnd.setBounds(250, 80, 61, 16);
		frame.getContentPane().add(lblEnd);
		
		JLabel lblStartTime = new JLabel("Start time");
		lblStartTime.setBounds(250, 115, 61, 16);
		frame.getContentPane().add(lblStartTime);
		
		JLabel lblEndTime = new JLabel("End time");
		lblEndTime.setBounds(250, 152, 61, 16);
		frame.getContentPane().add(lblEndTime);
		
		JPanel panel = new JPanel();
		panel.setBackground(Color.RED);
		panel.setBounds(0, 304, 450, 2);
		frame.getContentPane().add(panel);
		
		list = new JList();
		list.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				appointmentsList.removeAll();
				
				fetchAppointments();
				for(AgendaCalendar cal : col)
				{
				
					if(cal.toString().equals(list.getSelectedValue().toString()))
					{
						selectedCalendar=cal;
					}
				}
			}
		});
		list.setBounds(36, 49, 198, 151);
		//frame.getContentPane().add(list);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(26, 28, 208, 112);
		scrollPane.setViewportView(list);
		frame.getContentPane().add(scrollPane);
		
		chooser1 =GECAMedGuiUtils.getDateChooser(false);
		chooser1.setBounds(280, 50, 140, 20);
		frame.getContentPane().add(chooser1);
		
		chooser2 =GECAMedGuiUtils.getDateChooser(false);
		chooser2.setBounds(280, 80, 140, 20);
		frame.getContentPane().add(chooser2);
		
		
		startTime = new JTimeChooser();
		startTime.setBounds(323, 110, 100, 30);
		frame.getContentPane().add(startTime);
		
		endTime = new JTimeChooser();
		endTime.setBounds(323, 151, 100, 30);
		frame.getContentPane().add(endTime);
		
		final JLabel lblDurationmin = new JLabel("Duration (min)");
		lblDurationmin.setBounds(250, 198, 100, 16);
		frame.getContentPane().add(lblDurationmin);
		
		spinner = new JSpinner();
		spinner.setBounds(353, 193, 70, 26);
		frame.getContentPane().add(spinner);
		
		JButton btnGenerateData = new JButton("Generate Data");
		btnGenerateData.addActionListener(new ActionListener() {
			@SuppressWarnings("deprecation")
			public void actionPerformed(ActionEvent e) {
				textPane.setText(textPane.getText()+"\nGenerating... ");
				try
				{
					generateData();
				}
				catch(Exception ex)
				{
					textPane.setText(textPane.getText()+"\nEXCEPTION : "+ex.getMessage());
				}
				
			}
		});
		btnGenerateData.setBounds(26, 469, 394, 29);
		frame.getContentPane().add(btnGenerateData);
		
		JButton btnRemoveAllGenerated = new JButton("Remove all generated Data");
		btnRemoveAllGenerated.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				textPane.setText(textPane.getText()+"\nDeleting... ");
				try
				{
					removeGeneratedData();
				}
				catch(Exception ex)
				{
					textPane.setText(textPane.getText()+"\nEXCEPTION : "+ex.getMessage());
				}
			}

			
		});
		btnRemoveAllGenerated.setBounds(26, 510, 394, 29);
		frame.getContentPane().add(btnRemoveAllGenerated);
		
		JScrollPane scrollPane_1 = new JScrollPane();
		scrollPane_1.setBounds(26, 346, 394, 97);
		frame.getContentPane().add(scrollPane_1);
		
		textPane = new JTextPane();
		scrollPane_1.setViewportView(textPane);
		
		JLabel lblPleaseSelectA = new JLabel("Console");
		lblPleaseSelectA.setHorizontalAlignment(SwingConstants.LEFT);
		lblPleaseSelectA.setBounds(26, 318, 208, 16);
		frame.getContentPane().add(lblPleaseSelectA);
		
		JPanel panel_1 = new JPanel();
		panel_1.setBackground(Color.RED);
		panel_1.setBounds(0, 455, 450, 2);
		frame.getContentPane().add(panel_1);


		JLabel lblAppointmentType = new JLabel("Appointment Type");
		lblAppointmentType.setHorizontalAlignment(SwingConstants.LEFT);
		lblAppointmentType.setBounds(26, 155, 208, 16);
		frame.getContentPane().add(lblAppointmentType);
		
		JScrollPane scrollPane2 = new JScrollPane();
		scrollPane2.setBounds(26, 180, 208, 112);
		frame.getContentPane().add(scrollPane2);
		
		appointmentsList = new JList();
		appointmentsList.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				
				for(AgendaCalendar cal : col)
				{
					
						for(AppointmentType at : appTypes)
						{
							if(at.getName().equals(appointmentsList.getSelectedValue().toString()))
							{
								selectedAppType=at;
								break;
							}
						}
					
				}
			}
		});
		scrollPane2.setViewportView(appointmentsList);
	}

	//START LOGGER, CONNEXION AND MANAGER
	private void start()
	{
		TestUtils.initLogger();
		TestUtils.initJBossConnection();
		appointmentManager	= (AppointmentManager) ManagerFactory.getRemote(AppointmentManagerBean.class);
		Exception e = null;
		logger.log(Level.FATAL, "org.apache.log4j works!",e);
	}
	
	private void fetchCalendars()
	{
		col=appointmentManager.getCalendars();
		DefaultListModel<String> listModel = new DefaultListModel<String>();
		for(AgendaCalendar cal : col)
		{
			listModel.addElement(cal.toString());
		}
		list.setModel(listModel);
		
	}
	
	private void fetchPatients()
	{
		patientAdminInterface	= (PatientAdminInterface) ManagerFactory.getRemote(PatientAdminBean.class);
		try {
			patientCol=	new ArrayList(patientAdminInterface.getPatientStubListBySearchString("", "", "", 200));
			for (PatientStub ps : patientCol) {
				//System.out.println("patient : "+ps.toString());
			}	
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private void fetchAppointments()
	{
		for(AgendaCalendar cal : col)
		{
			if(cal.toString().equals(list.getSelectedValue().toString()))
			{
				appTypes= appointmentManager.getAppointmentTypes(cal.getId(), false);
				DefaultListModel<String> listModel = new DefaultListModel<String>();
				for(AppointmentType at : appTypes)
				{
					listModel.addElement(at.getName());
				}
				appointmentsList.setModel(listModel);
				break;
			}
		}
	}
	
	private void generateData()
	{
		long startTotalMinutes;
		long endTotalMinutes;
		Date startAppointment;
		Date endPeriod;
		
		try
		{
			startAppointment=startTime.getDateWithTime(chooser1.getDate());
			endPeriod=endTime.getDateWithTime(chooser2.getDate());
			if(startAppointment!=null && endPeriod!=null)
			{
				startTotalMinutes=startAppointment.getSeconds()+60*startAppointment.getMinutes()+3600*startAppointment.getHours();
				endTotalMinutes=endPeriod.getSeconds()+60*endPeriod.getMinutes()+3600*endPeriod.getHours();
				
				if(endTotalMinutes>startTotalMinutes)
				{
					timeIsValid=true;
				}
				else
					timeIsValid=false;
			}
		}
		catch(Exception ex)
		{	
			timeIsValid=false;
			textPane.setText(textPane.getText()+"\nEXCEPTION : "+ex.getMessage());
		}

		eventDuration=(Integer)spinner.getValue();

		if(selectedCalendar!=null && selectedAppType!=null && timeIsValid && eventDuration>0)
		{
		
				startAppointment=startTime.getDateWithTime(chooser1.getDate());
				
				//End Date for the generator
				endPeriod=endTime.getDateWithTime(chooser2.getDate());
				
// Calculate difference betyeen start and end dates
				startTotalMinutes=startAppointment.getSeconds()+60*startAppointment.getMinutes()+3600*startAppointment.getHours();
				endTotalMinutes=endPeriod.getSeconds()+60*endPeriod.getMinutes()+3600*endPeriod.getHours();
				
				AppointmentType type = appointmentManager.getAppointmentTypes(selectedCalendar.getId(), false).iterator().next();
				
				int i=0;
				do
				{
					long startAppointmentInMinutes;
					long endAppointmentInMinutes;

					//Setting duration from the spinner in milliseconds
					Date endAppointment=new Date(startAppointment.getTime() + (eventDuration * 60000));

					startAppointmentInMinutes=startAppointment.getSeconds()+60*startAppointment.getMinutes()+3600*startAppointment.getHours();
					endAppointmentInMinutes=endAppointment.getSeconds()+60*endAppointment.getMinutes()+3600*endAppointment.getHours();
					
					if(startAppointmentInMinutes>=startTotalMinutes && endAppointmentInMinutes<=endTotalMinutes)
					{
					
						System.out.println("-- writing appointment");
					
						Appointment app= new Appointment();
						app.setStartDate(startAppointment);
						app.setEndDate(endAppointment);
						app.setCalendarId(selectedCalendar.getId());
						app.setCreated(new java.util.Date());
						app.setDescription("GEN");
						app.setTypeId(selectedAppType.getId());
						app.setPatientId(patientCol.get(i).getId());
						app.setSummary(patientCol.get(i).getFirstName());
						Appointment tmpApp=appointmentManager.saveAppointment(app);
						System.out.println(tmpApp.getId()+ " " +tmpApp.toString());
					
					
					}
					
					//Next appointment is set to the end of previous appointment
					startAppointment=endAppointment;
					endAppointment=new Date(startAppointment.getTime() + (eventDuration * 60000));
					
					startAppointmentInMinutes=startAppointment.getSeconds()+60*startAppointment.getMinutes()+3600*startAppointment.getHours();
					endAppointmentInMinutes=endAppointment.getSeconds()+60*endAppointment.getMinutes()+3600*endAppointment.getHours();
					
					i++;
					if(i>=200)
						i=0;
				}while(startAppointment.before(endPeriod));
				
				System.out.println("---- FINISH");
				textPane.setText(textPane.getText()+"\nGenerating Complete ");
			
		}
		else
		{
			JOptionPane.showMessageDialog(null,"Some options have not been selected or are incorrect. Please change"); 
		}
	
	}
	
	private void removeGeneratedData() {
		int dialogButton = JOptionPane.YES_NO_OPTION;
		int option = JOptionPane.showConfirmDialog(null, "Are you sure?", "Confirmation", JOptionPane.YES_NO_OPTION);

		if(option==JOptionPane.YES_OPTION)
		{
		
			col=appointmentManager.getCalendars();
			DefaultListModel<String> listModel = new DefaultListModel<String>();
			for(AgendaCalendar cal : col)
			{
				//ag.toString();
				Appointment app;
				do
				{
					app=appointmentManager.getAppointmentByCalIDandDesc(cal.getId(), "GEN");
					appointmentManager.deleteAppointment(null, app);
				}while(app!=null);
				
			}
			textPane.setText(textPane.getText()+"\nDeleting Complete ");
			}
			else
				textPane.setText(textPane.getText()+"\nDeleting Aborted ");
		}
}
