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

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
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.IconFetcher;
import lu.tudor.santec.gecamed.core.gui.utils.SystemInfo;
import lu.tudor.santec.gecamed.core.gui.widgets.GECAMedBaseDialogImpl;
import lu.tudor.santec.gecamed.core.gui.widgets.TranslatedComboBox;
import lu.tudor.santec.gecamed.letter.gui.LetterTemplateModule;
import lu.tudor.santec.i18n.Translatrix;
import lu.tudor.santec.settings.SettingsPlugin;

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

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

/*
 * Settings plugin for letters and templates
 */

public class LetterTemplateSettings extends SettingsPlugin {

	/**
	 * 
	 */
	public static final long serialVersionUID = 1L;

	public static final String NAME = "LetterTemplateModuleSettings";

	public static final String LETTER_LOCATION = "LETTER_LOCATION";

	public static final String TEMPLATE_LOCATION = "TEMPLATE_LOCATION";
	
	public static final String AVAILABLE_LETTER_STATES = "AVAILABLE_LETTER_STATES";

	public static final String WRITER = "WRITER";

	public static final String WORD = "WORD";

	public static final String TPS = "TPS";

	public static final String DEFAULT = "Default";

	public static final String DELETE = "DELETE";

	public static final String TYPES = "TYPES";

	public static final String ALLOW_OO = "ALLOW_OO";
	
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(LetterTemplateSettings.class.getName());

	private static ArrayList<String> TYPES_VALUES;

	private TranslatedComboBox cbTps;

	private JTextField tfLetter;

	private JTextField tfTemplate;

	private JCheckBox rbTemplate;

	private JCheckBox rbLetter;

	private JCheckBox cbDelete;
	
	private JList				letterStateList;
	
	private DefaultListModel	letterStateModel;
	
	private JButton				addLetterState;
	
	private JButton				removeLetterState;
	
	private JButton				renameLetterState;
	
	private JButton				moveLetterStateUp;
	
	private JButton				moveLetterStateDown;
	
	private Vector<String>		letterStates;

	private JCheckBox allowOOCB;
	
	
	
	public LetterTemplateSettings() {
		super(NAME);
		TYPES_VALUES = new ArrayList<String>();
		TYPES_VALUES.add("general");
		TYPES_VALUES.add("prescription");
		this.setStationaryValues();
		buildPanel();
	}

	private void buildPanel() {
		setLabel(Translatrix.getTranslationString("LetterTemplateModule.settings.name"));

		// Text Processing Software Chooser
		JPanel pTps = createSubPanel(Translatrix.getTranslationString("LetterTemplateModule.settings.subp_tps"));
		pTps.setLayout(new FormLayout("3dlu, 30dlu, 3dlu, fill:pref:grow, 3dlu", "3dlu, pref, 3dlu, pref, 3dlu"));
		CellConstraints cc = new CellConstraints();
		JLabel label = new JLabel(Translatrix.getTranslationString("LetterTemplateModule.settings.select_tps"));
		pTps.add(label, cc.xy(2, 2));
		String[] values = new String[2];
		values[0] = LetterTemplateSettings.WORD;
		values[1] = LetterTemplateSettings.WRITER;
		cbTps = new TranslatedComboBox("LetterTemplateModule.tps", values);
		cbTps.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				String tps = cbTps.getSelectedItemTranslated().toString();
				
				allowOOCB.setEnabled(tps.equals(LetterTemplateSettings.WORD));
				allowOOCB.setSelected(tps.equals(LetterTemplateSettings.WRITER));					
				
				if (!isShowing())
					return;
				
				if (tps.equals(LetterTemplateSettings.WORD)	&& SystemInfo.getOperatingSystem() == SystemInfo.SYSTEM_LINUX) {
					JOptionPane.showMessageDialog(LetterTemplateModule.getInstance(), Translatrix.getTranslationString("LetterTemplateModule.dialog.confirm.conflict"));
				}

			}
		});
		pTps.add(cbTps, cc.xy(4, 2));
		
		allowOOCB = new JCheckBox(Translatrix.getTranslationString("LetterTemplateModule.settings.allowOO"));
		pTps.add(allowOOCB, cc.xyw(2, 4, 3));
		
		
		addSubPanel(pTps);

		// Set local Path for Letters
		JPanel pLetterLocation = createSubPanel(Translatrix.getTranslationString("LetterTemplateModule.settings.subp_pletter"));
		pLetterLocation.setLayout(new FormLayout("3dlu, fill:pref:grow, 3dlu","3dlu, pref, 3dlu, pref, 3dlu"));
		rbLetter = new JCheckBox(Translatrix.getTranslationString("LetterTemplateModule.settings.default") +" (" + System.getProperty("java.io.tmpdir")+")");
		tfLetter = new JTextField();
		rbLetter.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				if (rbLetter.isSelected()) {
					tfLetter.setEnabled(false);
				} else {
					tfLetter.setEnabled(true);
				}
			}
		});
		
		pLetterLocation.add(rbLetter, cc.xy(2, 2));
		pLetterLocation.add(tfLetter, cc.xy(2, 4));
		addSubPanel(pLetterLocation);

		// Set path for templates.
		JPanel pTemplateLocation = createSubPanel(Translatrix.getTranslationString("LetterTemplateModule.settings.subp_ptemplate"));
		pTemplateLocation.setLayout(new FormLayout("3dlu, fill:pref:grow, 3dlu","3dlu, pref, 3dlu, pref, 3dlu"));
		tfTemplate = new JTextField();
		rbTemplate = new JCheckBox(Translatrix.getTranslationString("LetterTemplateModule.settings.default")+" (" + System.getProperty("java.io.tmpdir")+")");
		rbTemplate.addChangeListener(new ChangeListener() {

			public void stateChanged(ChangeEvent e) {
				if (rbTemplate.isSelected()) {
					tfTemplate.setEnabled(false);
				} else {
					tfTemplate.setEnabled(true);
				}

			}
		});
		pTemplateLocation.add(rbTemplate, cc.xy(2, 2));
		pTemplateLocation.add(tfTemplate, cc.xy(2, 4));
		addSubPanel(pTemplateLocation);

		// Delete local temporary files
		JPanel pDelete = createSubPanel(Translatrix.getTranslationString("LetterTemplateModule.settings.subp_options"));
		cbDelete = new JCheckBox(Translatrix.getTranslationString("LetterTemplateModule.settings.delete"));
		pDelete.add(cbDelete);
		addSubPanel(pDelete);
		
		JPanel letterStateSubPanel = createSubPanel(
				Translatrix.getTranslationString("LetterTemplateModule.settings.status"));
		letterStateSubPanel.setLayout(new BorderLayout());
		letterStateSubPanel.add(createStatePanel());
		addSubPanel(letterStateSubPanel);
		relocalize();
		setIcon(IconFetcher.getNormalIcon(LetterTemplateModule.class,
				"letter.png"));
	}

	private void setStationaryValues() {
		setStationary(TPS, WORD);
		setStationary(ALLOW_OO, false);
		setStationary(LETTER_LOCATION, DEFAULT);
		setStationary(TEMPLATE_LOCATION, DEFAULT);
		setStationary(DELETE, false);
		setStationary(TYPES, TYPES_VALUES);
		setStationary(AVAILABLE_LETTER_STATES, "");
	}

	public void updateSettings() {

		setValue(TPS, cbTps.getSelectedItemTranslated().toString());
		
		setValue(ALLOW_OO, this.allowOOCB.isSelected());
		
		if (rbLetter.isSelected()) {
			setValue(LETTER_LOCATION, DEFAULT);
			tfLetter.setText("");
		} else {
			setValue(LETTER_LOCATION, tfLetter.getText());
		}

		if (rbTemplate.isSelected()) {
			setValue(TEMPLATE_LOCATION, DEFAULT);
			tfTemplate.setText("");
		} else {
			setValue(TEMPLATE_LOCATION, tfTemplate.getText());
		}
		setValue(DELETE, cbDelete.isSelected());
		
		// state panel
		setValue(AVAILABLE_LETTER_STATES, getStateString());
		letterStates	= null;
	}

	public void relocalize() {
		super.relocalize();
		setLabel(Translatrix
				.getTranslationString("LetterTemplateModule.settings.name"));
	}

	public void reflectSettings() {
		super.reflectSettings();
		this.cbTps.setSelectedItem(Translatrix.getTranslationString("LetterTemplateModule.tps."	+ getValue(TPS)));
		
		this.allowOOCB.setSelected((Boolean) getValue(ALLOW_OO));
		
		String letter_location = (String) getValue(LETTER_LOCATION);
		if (letter_location.equalsIgnoreCase(DEFAULT)) {
			rbLetter.setSelected(true);
			tfLetter.setEnabled(false);
			tfLetter.setText("");
		} else {
			this.tfLetter.setText((String) getValue(LETTER_LOCATION));
			rbLetter.setSelected(false);
			tfLetter.setEnabled(true);
		}

		String template_location = (String) getValue(TEMPLATE_LOCATION);
		if (template_location.equalsIgnoreCase(DEFAULT)) {
			rbTemplate.setSelected(true);
			tfTemplate.setEnabled(false);
			tfTemplate.setText("");
		} else {
			this.tfTemplate.setText((String) getValue(TEMPLATE_LOCATION));
			rbTemplate.setSelected(false);
			tfTemplate.setEnabled(true);
		}
		this.cbDelete.setSelected((Boolean) getValue(DELETE));
		
		// letter states
		setStateString((String) getValue(AVAILABLE_LETTER_STATES));
	}
	
	
	public void revertToDefaults() {
		this.cbTps.setSelectedItem(Translatrix
				.getTranslationString("LetterTemplateModule.tps."
						+getDefault(TPS)));
		
		this.allowOOCB.setSelected((Boolean) getDefault(ALLOW_OO));
		
		this.tfLetter.setText((String) getDefault(LETTER_LOCATION));
		this.tfLetter.setText((String) getDefault(TEMPLATE_LOCATION));
	}
	
	
	private String getStateString ()
	{
		StringBuilder	states	= null;
		String			element;
		
		for (int index = 0; index < letterStateModel.size(); index++)
		{
			element	= (String) letterStateModel.get(index);
			if (states == null)
				 states	= new StringBuilder();
			else states.append(",");
			
			states.append("\"")
					.append(element)
					.append("\"");
		}
		return states == null ? "" : states.toString();
	}
	
	
	private void setStateString (String state)
	{
		String[] data;
		
		
		if (letterStateModel == null)
			letterStateModel = new DefaultListModel();
		
		letterStateModel.clear();
		
		if (state == null || state.trim().length() <= 0)
			return;
		
		try
		{
			data	= state.substring(1, state.length()-1).split("\",\"");
			
			for (int i = 0; i < data.length; i++)
			{
				letterStateModel.addElement(data[i]);
			}
		}
		catch (Exception e)
		{
			logger.log(Level.ERROR, "The states \""+state+"\" couldn't be converted as a list of letter states. " +
					"The format is \"<<name 1>>\",\"<<name 2>>\",...,\"<<name n>>\"", e);
		}
	}
	
	
	private JPanel createStatePanel ()
	{
		JScrollPane		scroller;
		CellConstraints	cc 		= new CellConstraints();
		int				row		= 0;
		JPanel			panel 	= new JPanel(new FormLayout(
				"10px, f:p:g, 5px, f:32px, 10px",
				" 5px, f:32px," +	// up
				" 3px, f:32px," +	// down
				"10px, f:32px," +	// add
				" 3px, f:32px," +	// remove
				" 3px, f:32px," +	// rename
				" 0px:g," +			// extra space for the list
				" 5px"));
		panel.setOpaque(false);
		
		
		if (letterStateModel == null)
			letterStateModel= new DefaultListModel();
		letterStateList		= new JList(letterStateModel);
		scroller			= new JScrollPane(letterStateList);
		scroller.setOpaque(false);
		scroller.getViewport().setOpaque(false);
		scroller.getHorizontalScrollBar().setUnitIncrement(16);
		addLetterState		= new JButton(new AbstractAction("", 
				GECAMedModule.getMediumIcon(GECAMedIconNames.ADD))
		{
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) 
			{
				// add a new element
				String name = askLetterStateName(null);
				
				if (name != null)
					letterStateModel.addElement(name);
			}
		});
		addLetterState.setToolTipText(Translatrix.getTranslationString("LetterTemplateModule.settings.status.add"));
		removeLetterState		= new JButton(new AbstractAction("", 
				GECAMedModule.getMediumIcon(GECAMedIconNames.REMOVE))
		{
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) 
			{
				// remove the selected element
				int[]	selection	= letterStateList.getSelectedIndices();
				
				
				Arrays.sort(selection);
				for (int i = selection.length-1; i >= 0; i--)
					letterStateModel.remove(selection[i]);
			}
		});
		removeLetterState.setToolTipText(Translatrix.getTranslationString("LetterTemplateModule.settings.status.remove"));
		renameLetterState		= new JButton(new AbstractAction("", 
				GECAMedModule.getMediumIcon(GECAMedIconNames.RENAME))
		{
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) 
			{
				// rename the selected element
				String	name	= (String) letterStateList.getSelectedValue();
				
				
				if (name == null)
					return;
				
				name	= askLetterStateName(name);
				
				if (name == null)
					return;
				
				letterStateModel.set(letterStateList.getSelectedIndex(), name);
			}
		});
		renameLetterState.setToolTipText(Translatrix.getTranslationString("LetterTemplateModule.settings.status.rename"));
		moveLetterStateUp		= new JButton(new AbstractAction("", 
				GECAMedModule.getMediumIcon(GECAMedIconNames.UP))
		{
			private static final long serialVersionUID = 1L;

			public void actionPerformed(ActionEvent e) 
			{
				// switch selected item with the one above
				int[]	selection	= letterStateList.getSelectedIndices();
				int[]	newSelection= new int[selection.length];
				int		index;
				String	name1;
				String	name2;
				

				Arrays.sort(selection);
				for (int i = 0; i < selection.length; i++)
				{
					index	= selection[i];
					if (index < 1)
						return;
					
					name1	= (String) letterStateModel.get(index);
					name2	= (String) letterStateModel.get(index - 1);
					letterStateModel.set(index, name2);
					letterStateModel.set(index - 1, name1);
					letterStateList.setSelectedIndex(index - 1);
					
					newSelection[i]	= index - 1;
				}
				
				letterStateList.setSelectedIndices(newSelection);
			}
		});
		moveLetterStateUp.setToolTipText(Translatrix.getTranslationString("LetterTemplateModule.settings.status.up"));
		moveLetterStateDown	= new JButton(new AbstractAction("", 
				GECAMedModule.getMediumIcon(GECAMedIconNames.DOWN))
		{
			private static final long serialVersionUID = 1L;
			
			public void actionPerformed(ActionEvent e) 
			{
				// switch selected item with the one beneath
				int[]	selection	= letterStateList.getSelectedIndices();
				int[]	newSelection= new int[selection.length];
				int		index;
				String	name1;
				String	name2;
				
				
				Arrays.sort(selection);
				for (int i = selection.length-1; i >= 0; i--)
				{
					index	= selection[i];
					if (index > letterStateModel.getSize() - 2)
						return;
					
					name1	= (String) letterStateModel.get(index);
					name2	= (String) letterStateModel.get(index + 1);
					letterStateModel.set(index, name2);
					letterStateModel.set(index + 1, name1);
					letterStateList.setSelectedIndex(index + 1);
					
					newSelection[i]	= index + 1;
				}
				
				letterStateList.setSelectedIndices(newSelection);
			}
		});
		moveLetterStateDown.setToolTipText(Translatrix.getTranslationString("LetterTemplateModule.settings.status.down"));
		
		
		panel.add(scroller,					cc.xywh(2, 2, 1, 10));
		panel.add(moveLetterStateUp,		cc.xy(4, row+=2));
		panel.add(moveLetterStateDown,		cc.xy(4, row+=2));
		panel.add(addLetterState,			cc.xy(4, row+=2));
		panel.add(removeLetterState,		cc.xy(4, row+=2));
		panel.add(renameLetterState,		cc.xy(4, row+=2));
		
		return panel;
	}
	
	
	private String askLetterStateName (String name)
	{
		while (true)
		{
			if (name == null)
				name = "";
			
			name = GECAMedBaseDialogImpl.showInputMessageDialog(this, 
					Translatrix.getTranslationString("LetterTemplateModule.settings.status.selectNameTitle"), 
					Translatrix.getTranslationString("LetterTemplateModule.settings.status.selectNameMessage"), 
					name);
			
			if (name == null)
				return name;
			else
			{
				// remove the split character
				name = name.replace("\",\"", "");
				
				if (name.trim().length() > 0 && !letterStateModel.contains(name))
					return name;
				else
					GECAMedBaseDialogImpl.showMessageDialog(this, 
							Translatrix.getTranslationString("LetterTemplateModule.settings.status.nameAlreadyExistsTitle"), 
							Translatrix.getTranslationString("LetterTemplateModule.settings.status.nameAlreadyExistsMessage"), 
							GECAMedBaseDialogImpl.OK_BUTTON_MODE);
			}
		}
	}
	
	
	public Vector<String> getLetterStates ()
	{
		if (letterStates == null)
		{
			letterStates = new Vector<String>();
			
			for (int index = 0; index < letterStateModel.getSize(); index++)
				letterStates.add((String) letterStateModel.get(index));
		}
		
		return letterStates;
	}
}
