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

import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import lu.tudor.santec.gecamed.core.gui.GECAMedIconNames;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.widgets.GECAMedBaseDialogImpl;
import lu.tudor.santec.gecamed.core.gui.widgets.IntegerField;
import lu.tudor.santec.i18n.Translatrix;
import lu.tudor.santec.settings.SettingsPlugin;

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

/**
 * 
 * @author Johannes Hermen johannes.hermen(at)tudor.lu
 */
public class BackupAdminSettingsPlugin extends SettingsPlugin
{
	
	public static String						NAME						= "BACKUP_ADMIN_SETTINGS";
	
	private static final long					serialVersionUID			= 1L;
	
	public static final String					BACKUP_ENABLED				= "BACKUP_ENABLED";
	public static final String					BACKUP_TIME					= "BACKUP_TIME";
	public static final String					BACKUP_WEEKDAYS				= "BACKUP_WEEKDAYS";
	public static final String					NUMBER_OF_BACKUPS			= "NUMBER_OF_BACKUPS";
	
	public static final String					DO_DB_BACKUP				= "DO_DB_BACKUP";
	public static final String					DO_FILE_BACKUP				= "DO_FILE_BACKUP";
	public static final String					DO_DICOM_BACKUP				= "DO_DICOM_BACKUP";
	public static final String					DO_LETTER_TEMPLATE_BACKUP	= "DO_LETTER_TEMPLATE_BACKUP";
	public static final String					NOTIFIED_USERS 				= "NOTIFIED_USERS";
	
	private JLabel								backupTimeLabel;
	
	private JPanel								weekdaysPanel;
	
	// private static Logger logger =
	// Logger.getLogger(BackupAdminSettingsPlugin.class.getName());
	
	private LinkedHashMap<Integer, JCheckBox>	weekdays					= new LinkedHashMap<Integer, JCheckBox>();
	
	private DateFormat							weekdayFormat				= new SimpleDateFormat("EE", Translatrix.getLocale());
	
	private JLabel								keepFilesLabel;
	
	private IntegerField						keepFiles;
	
	private JPanel								timeSub;
	
	private JPanel								fileSub;
	
	private JLabel								weekdayTimeLabel;
	
	private SpinnerDateModel					timeModel;
	
	private JSpinner							timeSpinner;
	
	private JLabel								doDBBackupLabel;
	
	private JCheckBox							doDBBackup;
	
	private JLabel								doFileBackupLabel;
	
	private JCheckBox							doFileBackup;
	
	private JLabel								doDicomBackupLabel;
	
	private JCheckBox							doDicomBackup;
	
	private JLabel								backupEnabledLabel;
	
	private JCheckBox							backupEnabled;
	
	private JLabel								doLetterTemplateBackupLabel;
	
	private JCheckBox							doLetterTemplateBackup;
	
	private JLabel 								notifyIfBackupFailsLabel;
	
	private JButton 							notifyIfBackupFailsButton;
	
	private NotifyUsersDialog 					notifyUsersDialog;
	
	private List<Integer> 						notifiedUsers;
	
	
	// ***************************************************************************
	// * Constructor *
	// ***************************************************************************
	
	
	/**
	 * Creates a new instance of DICOMPlugin
	 */
	public BackupAdminSettingsPlugin()
	{
		super(NAME);
		Translatrix.addBundle("lu.tudor.santec.gecamed.backup.gui.resources.Translatrix");
		setIcon(GECAMedModule.getIcon(GECAMedIconNames.BACKUP_DB));
		this.setStationaryValues();
		this.buildPanel();
		
		relocalize();
	}
	
	
	// ***************************************************************************
	// * Class Primitives *
	// ***************************************************************************
	
	/**
	 * adds the components to the panel
	 */
	private void buildPanel()
	{
		initComponents();
		
		CellConstraints cc = new CellConstraints();
		FormLayout timePanelLayout = new FormLayout("2dlu, fill:pref:grow, 2dlu, 60dlu, 2dlu,", 
				"2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu");
		
		
		timeSub = createSubPanel(Translatrix.getTranslationString("backup.settings.timeSubPanel"));
		timeSub.setLayout(timePanelLayout);
		
		timeSub.add(this.backupEnabledLabel, cc.xy(2, 2));
		timeSub.add(this.backupEnabled, cc.xy(4, 2));
		
		timeSub.add(this.backupTimeLabel, cc.xy(2, 4));
		timeSub.add(this.timeSpinner, cc.xy(4, 4));
		
		timeSub.add(this.weekdayTimeLabel, cc.xy(2, 6));
		timeSub.add(this.weekdaysPanel, cc.xyw(2, 8, 3));
		
		addSubPanel(timeSub);
		
		FormLayout filePanelLayout = new FormLayout("2dlu, fill:pref:grow, 2dlu, 60dlu, 2dlu,", 
				"2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu");
		fileSub = createSubPanel(Translatrix.getTranslationString("backup.settings.keepSubPanel"));
		fileSub.setLayout(filePanelLayout);
		
		fileSub.add(this.keepFilesLabel, 			cc.xy(2, 2));
		fileSub.add(this.keepFiles, 				cc.xy(4, 2));
		
		fileSub.add(this.doDBBackupLabel, 			cc.xy(2, 4));
		fileSub.add(this.doDBBackup, 				cc.xy(4, 4));
		
		fileSub.add(this.doFileBackupLabel, 		cc.xy(2, 6));
		fileSub.add(this.doFileBackup, 				cc.xy(4, 6));
		
		fileSub.add(this.doDicomBackupLabel, 		cc.xy(2, 8));
		fileSub.add(this.doDicomBackup, 			cc.xy(4, 8));
		
		fileSub.add(this.doLetterTemplateBackupLabel,cc.xy(2,10));
		fileSub.add(this.doLetterTemplateBackup, 	cc.xy(4, 10));
		
		fileSub.add(this.notifyIfBackupFailsLabel, 	cc.xy(2, 12));
		fileSub.add(this.notifyIfBackupFailsButton, cc.xy(4, 12));
		
		addSubPanel(fileSub);
		
	}
	
	
	/**
	 * initialises the Components
	 */
	private void initComponents()
	{
		
		this.backupEnabledLabel 		= new JLabel(Translatrix.getTranslationString("backup.settings.backupEnabled"));
		this.backupEnabled 				= new JCheckBox();
		this.backupEnabled.addChangeListener(new ChangeListener()
		{
			public void stateChanged(ChangeEvent e)
			{
				boolean  enabled = backupEnabled.isSelected();
				
				backupTimeLabel.setEnabled(enabled);
				timeSpinner.setEnabled(enabled);
				weekdayTimeLabel.setEnabled(enabled);
				for (Iterator<JCheckBox> iter = weekdays.values().iterator(); iter.hasNext();)
				{
					JCheckBox element = (JCheckBox) iter.next();
					element.setEnabled(enabled);
				}
				keepFilesLabel.setEnabled(enabled);
				keepFiles.setEnabled(enabled);
				doDBBackupLabel.setEnabled(enabled);
				doDBBackup.setEnabled(enabled);
				doFileBackupLabel.setEnabled(enabled);
				doFileBackup.setEnabled(enabled);
				doDicomBackupLabel.setEnabled(enabled);
				doDicomBackup.setEnabled(enabled);
				doLetterTemplateBackupLabel.setEnabled(enabled);
				doLetterTemplateBackup.setEnabled(enabled);
				notifyIfBackupFailsLabel.setEnabled(enabled);
				notifyIfBackupFailsButton.setEnabled(enabled);
			}
		});
		
		
		this.backupTimeLabel 			= new JLabel(Translatrix.getTranslationString("backup.settings.time"));
		this.timeModel 					= new SpinnerDateModel();
		this.timeSpinner 				= new JSpinner(timeModel);
		JSpinner.DateEditor endeditor 	= new JSpinner.DateEditor(this.timeSpinner, "HH:mm");
		this.timeSpinner.setEditor(endeditor);
		
		this.weekdayTimeLabel 			= new JLabel(Translatrix.getTranslationString("backup.settings.weekday"));
		buildWeekDayPanel();
		
		this.keepFilesLabel 			= new JLabel(Translatrix.getTranslationString("backup.settings.keepfiles"));
		this.keepFiles 					= new IntegerField();
		
		this.doDBBackupLabel 			= new JLabel(Translatrix.getTranslationString("backup.settings.doDBBackup"));
		this.doDBBackup 				= new JCheckBox();
		this.doFileBackupLabel 			= new JLabel(Translatrix.getTranslationString("backup.settings.doFileBackup"));
		this.doFileBackup 				= new JCheckBox();
		this.doDicomBackupLabel 		= new JLabel(Translatrix.getTranslationString("backup.settings.doDicomBackup"));
		this.doDicomBackup 				= new JCheckBox();
		
		this.doLetterTemplateBackupLabel= new JLabel(Translatrix.getTranslationString("backup.settings.doLetterTemplateBackup"));
		this.doLetterTemplateBackup 	= new JCheckBox();
		
		this.notifyIfBackupFailsLabel 	= new JLabel(Translatrix.getTranslationString("Notify users if backup fails"));
		this.notifyIfBackupFailsButton 	= new JButton(Translatrix.getTranslationString("Select users"));
		this.notifyIfBackupFailsButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				if (notifyUsersDialog == null)
				{
					Window window = GECAMedBaseDialogImpl.getParentWindow(BackupAdminSettingsPlugin.this);
//					if (window instanceof JFrame)
//						 notifyUsersDialog = new NotifyUsersDialog((JFrame)window);
//					else 
						notifyUsersDialog = new NotifyUsersDialog((JDialog)window);
				}
				notifiedUsers = notifyUsersDialog.showUp(notifiedUsers);
			}
		});
		
	}
	
	
	private void buildWeekDayPanel()
	{
		this.weekdaysPanel = new JPanel(new GridLayout(1, 0));
		this.weekdaysPanel.setOpaque(false);
		
		Calendar c = new GregorianCalendar(Translatrix.getLocale());
		c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
		
		for (int i = 0; i < 7; i++)
		{
			JCheckBox weekday = new JCheckBox(weekdayFormat.format(c.getTime()));
			weekdaysPanel.add(weekday);
			weekday.setActionCommand(c.get(Calendar.DAY_OF_WEEK) + "");
			weekday.setOpaque(false);
			weekdays.put(c.get(Calendar.DAY_OF_WEEK), weekday);
			c.roll(Calendar.DAY_OF_WEEK, true);
		}
	}
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.settings.SettingsPlugin#revertToDefaults()
	 */
	public void revertToDefaults()
	{
		this.backupEnabled.setSelected((Boolean) getDefault(BACKUP_ENABLED));
		
		setTime((String) getDefault(BACKUP_TIME));
		setWeekDays((String) getDefault(BACKUP_WEEKDAYS));
		this.keepFiles.setValue((Integer) getDefault(NUMBER_OF_BACKUPS));
		
		this.doDBBackup.setSelected((Boolean) getDefault(DO_DB_BACKUP));
		this.doFileBackup.setSelected((Boolean) getDefault(DO_FILE_BACKUP));
		this.doDicomBackup.setSelected((Boolean) getDefault(DO_DICOM_BACKUP));
		this.doLetterTemplateBackup.setSelected((Boolean) getDefault(DO_LETTER_TEMPLATE_BACKUP));
		setNotifiedUsers((String) getDefault(NOTIFIED_USERS));
		
		reflectSettings();
		super.revertToDefaults();
	}
	
	
	public void setStationaryValues()
	{
		
		setStationary(BACKUP_ENABLED, 				true);
		
		Calendar c = new GregorianCalendar();
		c.set(Calendar.HOUR_OF_DAY, 12);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		setStationary(BACKUP_TIME, 					c.getTime());
		
		setStationary(BACKUP_WEEKDAYS, 				"2,3,4,5,6");
		
		setStationary(NUMBER_OF_BACKUPS, 			10);
		
		setStationary(DO_DB_BACKUP, 				true);
		setStationary(DO_FILE_BACKUP, 				true);
		setStationary(DO_DICOM_BACKUP, 				true);
		setStationary(DO_LETTER_TEMPLATE_BACKUP, 	true);
		
		setStationary(NOTIFIED_USERS, 				"");
	}
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.settings.SettingsPlugin#updateSettings()
	 */
	public void updateSettings()
	{
		
		setValue(BACKUP_ENABLED, this.backupEnabled.isSelected());
		
		setValue(BACKUP_TIME, 				getTime());
		setValue(BACKUP_WEEKDAYS, 			getWeekDays());
		setValue(NUMBER_OF_BACKUPS, 		this.keepFiles.getValue());
		
		setValue(DO_DB_BACKUP, 				this.doDBBackup.isSelected());
		setValue(DO_FILE_BACKUP, 			this.doFileBackup.isSelected());
		setValue(DO_DICOM_BACKUP, 			this.doDicomBackup.isSelected());
		setValue(DO_LETTER_TEMPLATE_BACKUP, this.doLetterTemplateBackup.isSelected());
		setValue(NOTIFIED_USERS, 			getNotifiedUsers());
		
		super.updateSettings();
	}
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.settings.SettingsPlugin#reflectSettings()
	 */
	public void reflectSettings()
	{
		super.reflectSettings();
		
		this.backupEnabled.setSelected((Boolean) getValue(BACKUP_ENABLED));
		
		try
		{
			setTime((String) getValue(BACKUP_TIME));
		}
		catch (Exception e)
		{
		}
		try
		{
			setWeekDays((String) getValue(BACKUP_WEEKDAYS));
		}
		catch (Exception e)
		{
		}
		try
		{
			this.keepFiles.setValue((Integer) getValue(NUMBER_OF_BACKUPS));
			this.doDBBackup.setSelected((Boolean) getValue(DO_DB_BACKUP));
			this.doFileBackup.setSelected((Boolean) getValue(DO_FILE_BACKUP));
			this.doDicomBackup.setSelected((Boolean) getValue(DO_DICOM_BACKUP));
			this.doLetterTemplateBackup.setSelected((Boolean) getValue(DO_LETTER_TEMPLATE_BACKUP));
			setNotifiedUsers((String) getValue(NOTIFIED_USERS));
		}
		catch (Exception e)
		{
		}
	}
	
	
	/**
	 * Method is part of the Relocalizable interface. The method does everything
	 * required to reflect changes of active Locale
	 */
	public void relocalize()
	{
		
		setLabel(Translatrix.getTranslationString("backup.settings"));
		
		setSubPanelTitle(this.timeSub, Translatrix.getTranslationString("backup.settings.timeSubPanel"));
		setSubPanelTitle(this.fileSub, Translatrix.getTranslationString("backup.settings.keepSubPanel"));
		
		
	}
	
	
	private String getWeekDays()
	{
		StringBuffer wDays = new StringBuffer();
		for (Iterator<JCheckBox> iter = weekdays.values().iterator(); iter.hasNext();)
		{
			JCheckBox element = (JCheckBox) iter.next();
			if (element.isSelected())
				wDays.append(element.getActionCommand() + ",");
		}
		return wDays.toString();
	}
	
	
	private void setWeekDays(String wDays)
	{
		try
		{
			for (Iterator<JCheckBox> iter = weekdays.values().iterator(); iter.hasNext();)
			{
				JCheckBox element = (JCheckBox) iter.next();
				element.setSelected(false);
			}
			if (wDays == null)
				return;
			
			String[] days = wDays.split(",");
			int[] dayConstants = new int[days.length];
			for (int i = 0; i < dayConstants.length; i++)
			{
				try
				{
					dayConstants[i] = Integer.parseInt(days[i]);
				}
				catch (Exception e)
				{
				}
			}
			for (int i = 0; i < dayConstants.length; i++)
			{
				JCheckBox weekday = weekdays.get(dayConstants[i]);
				if (weekday != null)
				{
					weekday.setSelected(true);
				}
			}
		}
		catch (Exception e)
		{
		}
	}
	
	
	public String getTime()
	{
		try
		{
			Calendar c = new GregorianCalendar();
			c.setTime(this.timeModel.getDate());
			return c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE);
		}
		catch (Exception e)
		{
		}
		return "00:00";
	}
	
	
	public void setTime(String time)
	{
		try
		{
			String[] tArr = time.split(":");
			Calendar c = new GregorianCalendar();
			c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(tArr[0]));
			c.set(Calendar.MINUTE, Integer.parseInt(tArr[1]));
			this.timeModel.setValue(c.getTime());
		}
		catch (Exception e)
		{
		}
	}
	
	
	private void setNotifiedUsers (String userIDs)
	{
		notifiedUsers = new LinkedList<Integer>();
		Integer idInt;
		
		for (String idString : userIDs.split(","))
		{
			try 
			{
				idInt = Integer.parseInt(idString);
				notifiedUsers.add(idInt);
			}
			catch (NumberFormatException e) {}
		}
	}
	
	
	private String getNotifiedUsers ()
	{
		StringBuffer ids = new StringBuffer();
		
		for (Integer id : notifiedUsers)
		{
			ids.append(id).append(',');
		}
		
		if (ids.length() > 0)
			// there's 1 ',' to much
			ids.deleteCharAt(ids.length()-1);
		
		return ids.toString();
	}
}
