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

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

import lu.tudor.santec.gecamed.core.gui.GECAMedAction;
import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
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.PhysicianListener;
import lu.tudor.santec.gecamed.core.gui.RegistrationDesk;
import lu.tudor.santec.gecamed.core.gui.controller.ControllerConfig;
import lu.tudor.santec.gecamed.core.gui.controller.document.DocumentController;
import lu.tudor.santec.gecamed.core.gui.listener.EntryTypeRegister;
import lu.tudor.santec.gecamed.core.gui.utils.SystemInfo;
import lu.tudor.santec.gecamed.core.gui.widgets.NamedComponent;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.letter.ejb.entity.beans.LetterTemplate;
import lu.tudor.santec.gecamed.letter.ejb.session.beans.LetterTemplateBean;
import lu.tudor.santec.gecamed.letter.ejb.session.interfaces.LetterTemplateInterface;
import lu.tudor.santec.gecamed.letter.gui.actions.AddTemplateAction;
import lu.tudor.santec.gecamed.letter.gui.actions.CopyTemplateAction;
import lu.tudor.santec.gecamed.letter.gui.actions.DeleteTemplateAction;
import lu.tudor.santec.gecamed.letter.gui.actions.OpenTemplateAction;
import lu.tudor.santec.gecamed.letter.gui.actions.SaveTemplateAction;
import lu.tudor.santec.gecamed.letter.gui.components.ComboBoxSearchTypeModel;
import lu.tudor.santec.gecamed.letter.gui.components.ComboBoxTypeModel;
import lu.tudor.santec.gecamed.letter.gui.listeners.TemplateListSelectionListener;
import lu.tudor.santec.gecamed.letter.gui.settings.LetterTemplateSettings;
import lu.tudor.santec.gecamed.letter.gui.templatelist.ListRenderer;
import lu.tudor.santec.gecamed.letter.gui.templatelist.TemplateDetailsPanel;
import lu.tudor.santec.gecamed.letter.gui.templatelist.TemplateListModel;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.gecamed.waitingroom.gui.WaitingroomAdminSettingsPlugin;
import lu.tudor.santec.i18n.Translatrix;

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

/*
 * 
 * MAIN PART THAT MANAGES TEMPLATES
 *  
 */

public class LetterTemplateModule extends GECAMedModule implements PhysicianListener
{
	/**
	 * 
	 */
	private static final long			serialVersionUID	= 1L;
	
	public static final String			MODULE_NAME			= "LetterTemplateModule";
	
	public static final String			ICON_LETTER			= "letter.png";

	public static final String			ALL					= "all";
	
	public static final Color			LETTER_MODULE_COLOR	= new Color(163, 186, 208);
	
	public static final Color			MODIFIED_COLOR		= Color.YELLOW;
	
	private JPanel						contentPane;
	
	private JList						list;
	
	private LetterTemplateInterface		templateManager;
	
	private static TemplateListModel	listModel;
	
	private TemplateDetailsPanel		details;
	
	private CellConstraints				cc;
	
	public LetterTemplateSettings		letterSettings;
	
	private JTextField					tSearch;
	
	private JComboBox<String>			cbType;
	
	private JPopupMenu					menu;
	
	private JMenuItem					updateVersionMenuItem;
	
	private OpenTemplateAction			openTemplateAction;
	
	private SaveTemplateAction			saveTemplateAction;
	
	private AddTemplateAction			addTemplateAction;
	
	private CopyTemplateAction			copyTemplateAction;
	
	private DeleteTemplateAction		deleteTemplateAction;
	
	private ComboBoxSearchTypeModel		cbModel;
	
	private boolean						isModified;

	private JScrollPane listPane;
	
	private static LetterTemplateModule	letterTemplateModule;
	
	
	public LetterTemplateModule()
	{
		/*
		 * Initiate the module
		 * 
		 */
		super(MODULE_NAME, IconFetcher.getNormalIcon(LetterTemplateModule.class, ICON_LETTER), LETTER_MODULE_COLOR);
		
		letterTemplateModule = this;
		
		Translatrix.addBundle("lu.tudor.santec.gecamed.letter.gui.resources.Translatrix");
		
		String moduleNameTranslated = Translatrix.getTranslationString(getName());
		
		this.titlePanel.setTopic(moduleNameTranslated);
		
		listModel = new TemplateListModel();
		
		/*
		 * Initiate the session beans allowing to get and save templates
		 * 
		 */
		templateManager = (LetterTemplateInterface) ManagerFactory.getRemote(LetterTemplateBean.class);
		
		/*
		 * Getting the physician, templates are bound to a physician
		 * 
		 */
		RegistrationDesk.addPhysicianListener(this);
		
		/*
		 * Registering GECAMedActions , Buttons that appear north-east in the
		 * LetterTemplateModule ADD, REMOVE, OPEN a template
		 * 
		 */
		registeringActions();
		
		/*
		 * Settingsmenu for templates and letters
		 * 
		 */
		letterSettings = new LetterTemplateSettings();
		addAdminSettingsPlugin(letterSettings);
		
		/*
		 * Registering Handler for letters in patient's history.
		 * 
		 */
		LetterHandler letterHandler = new LetterHandler();
		EntryTypeRegister.registerHandler(LetterHandler.ENTRY_TYPE, letterHandler);
		
		setToolTipText(Translatrix.getTranslationString("LetterTemplateModule"));
		
	}
	
	
	protected void initModule()
	{
		// Standard Method of a GECAMedModule
		// InitComponents creates the content of the module
		initComponents();
	}
	
	
	public void initComponents()
	{
		/*
		 * Creating the content of the Module A List with the templates, besides
		 * a panel that shows the details of a selected template
		 * 
		 */
		
		this.contentPane = new JPanel(new FormLayout(
				"5px,f:100px:g,5px,180dlu,5px", 
				"5px,p,10dlu,f:p:g,5px"));
		
		cc = new CellConstraints();
		
		// Title and Searchfield
		JPanel pTemplateSearch = new JPanel(new FormLayout("p, 15px, p, 10px, f:p:g", "p"));
		pTemplateSearch.setOpaque(false);
//		pTemplateSearch.setBackground(new Color(163, 186, 208));
//		pTemplateSearch.setBorder(new LineBorder(Color.black, 1));
		
		JLabel lTemplates = new JLabel(
				Translatrix.getTranslationString("LetterTemplateModule.module.search"),
				GECAMedModule.getMediumIcon(GECAMedIconNames.SEARCH),
				SwingConstants.LEFT);
//		lTemplates.setFont(new Font("Helvetica", Font.BOLD, 16));
		pTemplateSearch.add(lTemplates, cc.xy(1, 1));
		
		/*
		 * ComboBox filter type of templates
		 */
		
		// cbModel = new ComboBoxTypeModel((ArrayList<String>) types_template);
		cbModel = new ComboBoxSearchTypeModel();
		cbModel.queryTemplateTypes();
//		cbSearchModel = new ComboBoxSearchTypeModel(cbModel);
		
		cbType = new JComboBox(cbModel);
		cbModel.addListDataListener(cbType);
		cbType.setSelectedIndex(0);
		
		cbType.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				filter();
			}
		});
		pTemplateSearch.add(new NamedComponent(
				Translatrix.getTranslationString("LetterTemplateModule.module.typeFilter"), cbType), 
				cc.xy(3, 1));
		
		tSearch = new JTextField();
		tSearch.addCaretListener(new CaretListener()
		{
			public void caretUpdate(CaretEvent e)
			{
				filter();
			}
		});
		pTemplateSearch.add(new NamedComponent(
				Translatrix.getTranslationString("LetterTemplateModule.module.nameFilter"), tSearch), 
				cc.xy(5, 1));
		
//		JLabel lSearch = new JLabel();
//		lSearch.setIcon(GECAMedModule.getMediumIcon(GECAMedIconNames.SEARCH));
//		pTemplateSearch.add(lSearch, cc.xy(6, 1));
		
		this.contentPane.add(pTemplateSearch, cc.xy(2, 2));
				
		// Details Panel, showing details of a selected template
		details = new TemplateDetailsPanel();
		this.contentPane.add(details, cc.xy(4, 4));
		
		// a List with templates
		initList();

		filter();
		// creating the list or showing the label if no template exists
		updateList(0);
		
		this.contentPane.add(listPane, cc.xy(2, 4));
		
//		this.titleLabel.setOpaque(false);
//		contentPane.setBackground(new Color(212, 235, 249));
		contentPane.setBackground(GECAMedColors.c_GECAMedBackground);
		this.setContentPanel(contentPane);
	}
	
	
	protected List<LetterTemplate> filter ()
	{
		List<LetterTemplate>	templates;
		Physician				physician	= GECAMedModule.getCurrentPhysician();;
		String					typeFilter	= (String)cbType.getSelectedItem();
		String					nameFilter	= tSearch.getText();
		// -1 would be nothing selected, 0 would be "All" selected
		boolean					filterByType= cbType.getSelectedIndex() > 0;
		boolean					filterByName= nameFilter != null && !nameFilter.trim().equals("");
		
		
		templates = templateManager.getFilteredTemplates(
				physician != null	? physician.getId()			: null,
				filterByType		? typeFilter				: null,
				filterByName		? nameFilter.toLowerCase()	: null);
		
//		templates = new ArrayList<LetterTemplate>();
		
		listModel.setTemplates(templates);
		
		return templates;
	}
	
	
//	protected void filterName()
//	{
//		ArrayList<LetterTemplate> result = new ArrayList<LetterTemplate>();
//		if (tSearch.getText().equalsIgnoreCase(""))
//		{
//			listModel.setTemplates(filtered_templates);
//		}
//		else
//		{
//			for (int i = 0; i < filtered_templates.size(); i++)
//			{
//				if (filtered_templates.get(i).getName().toLowerCase().startsWith(tSearch.getText().toLowerCase()))
//				{
//					result.add(templates.get(i));
//				}
//			}
//			listModel.setTemplates(result);
//		}
//	}
//	
//	
//	protected void filterType()
//	{
//		ArrayList<LetterTemplate> result = new ArrayList<LetterTemplate>();
//		if (cbType.getSelectedIndex() != -1 && cbType.getSelectedItem() != null)
//		{
//			if (cbType.getSelectedItem().toString().equalsIgnoreCase(ALL))
//			{
//				filtered_templates = (ArrayList<LetterTemplate>) templates;
//			}
//			else
//			{
//				for (int i = 0; i < templates.size(); i++)
//				{
//					if (templates.get(i).getType().toLowerCase().equals(cbType.getSelectedItem().toString().toLowerCase()))
//					{
//						result.add(templates.get(i));
//					}
//				}
//				filtered_templates = result;
//			}
//			filterName();
//		}
//	}
	
	
	
	public void initList()
	{
		// A list with all templates corresponding to a physician
		
		menu = new JPopupMenu();
		
		JMenuItem open = new JMenuItem(Translatrix.getTranslationString("LetterTemplateModule.menu.open"), 
				GECAMedModule.getMiniIcon(GECAMedIconNames.OPEN));
		open.addActionListener(openTemplateAction);
		menu.add(open);
		
		JMenuItem copy = new JMenuItem(Translatrix.getTranslationString("LetterTemplateModule.menu.copy"), 
				GECAMedModule.getMiniIcon(GECAMedIconNames.COPY));
		copy.addActionListener(copyTemplateAction);
		menu.add(copy);
		
		JMenuItem delete = new JMenuItem(Translatrix.getTranslationString("LetterTemplateModule.menu.delete"), 
				GECAMedModule.getMiniIcon(GECAMedIconNames.REMOVE));
		delete.addActionListener(deleteTemplateAction);
		menu.add(delete);
		
//		JMenuItem rename = new JMenuItem(Translatrix.getTranslationString("LetterTemplateModule.menu.rename"), GECAMedModule.getMiniIcon(GECAMedIconNames.RENAME));
//		rename.addActionListener(new RenameTemplateListener());
//		menu.add(rename);
		
		updateVersionMenuItem = new JMenuItem(new AbstractAction(
				Translatrix.getTranslationString("LetterTemplateModule.menu.update"), 
				GECAMedModule.getMiniIcon(GECAMedIconNames.BUG))
		{
			private static final long	serialVersionUID	= 1L;
			
			
			public void actionPerformed(ActionEvent e)
			{
				updateTemplateVersion();
			}
		});
		menu.add(updateVersionMenuItem);
		
		list = new JList(listModel);
		list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		list.setBackground(Color.WHITE);
		list.setCellRenderer(new ListRenderer());
		list.addListSelectionListener(new TemplateListSelectionListener(details));
		list.addMouseListener(new MouseListener()
		{
			public void mouseClicked(MouseEvent e)
			{
				if (e.getClickCount() == 2)
					openTemplateAction.actionPerformed(null);
			}
			
			
			public void mousePressed(MouseEvent e)
			{
				if (e.isPopupTrigger())
				{
					showMenu(e);
				}
			}
			
			
			public void mouseReleased(MouseEvent e)
			{
				if (e.isPopupTrigger())
				{
					showMenu(e);
				}
			}
			
			public void mouseEntered(MouseEvent e) {}
			
			public void mouseExited(MouseEvent e) {}
		});
		listPane = new JScrollPane(list);
		listPane.getViewport().setBackground(Color.WHITE);
	}
	
	
	protected void showMenu(MouseEvent e)
	{
		LetterTemplate t;
		
		
		list.setSelectedIndex(list.locationToIndex(e.getPoint()));
		t = (LetterTemplate) list.getSelectedValue();
		
		if (t == null)
			return;
		
		updateVersionMenuItem.setVisible(t.getPlaceholderVersion() < DocumentController.PH_VERSION_NEW);
		menu.show(list, e.getX(), e.getY());
	}
	
	
//	public void initBlank()
//	{
//		// Label containing the information that no template exists
//		panel = new JPanel(new FormLayout("fill:pref:grow", "fill:pref:grow"));
//		panel.setBorder(new LineBorder(Color.BLACK, 1));
//		JLabel lEmpty = new JLabel(Translatrix.getTranslationString("LetterTemplateModule.module.notemplates"));
//		lEmpty.setHorizontalAlignment(JLabel.CENTER);
//		lEmpty.setVerticalAlignment(JLabel.CENTER);
//		panel.setBackground(Color.WHITE);
//		panel.add(lEmpty, new CellConstraints().xy(1, 1));
//		this.listPane.add(panel, "empty");
//	}
	
	
	public void updateList(int index)
	{		
		if (list != null)
		{
			list.clearSelection();
		}
		else
		{
			initComponents();
		}
		
//		listModel.setTemplates(templates);
				
		try
		{
			if (index >= 0)
				list.setSelectedIndex(index);
			else
				list.setSelectedIndex(list.getFirstVisibleIndex());
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
	
	
	public static TemplateListModel getListModel()
	{
		return listModel;
	}
	
	
	private void registeringActions()
	{
		// Action that SAVES the template meta data
		saveTemplateAction = new SaveTemplateAction(this, "LetterTemplateModule.module.save", 
				IconFetcher.getNormalIcon(GECAMedModule.class, GECAMedIconNames.SAVE), 
				KeyEvent.VK_S, true, true, false);
		saveTemplateAction.add(true);
		saveTemplateAction.setEnabled(false);
		
		// Action that OPENS a template
		openTemplateAction = new OpenTemplateAction(this, "LetterTemplateModule.module.open", 
				IconFetcher.getNormalIcon(GECAMedModule.class, GECAMedIconNames.OPEN), 
				KeyEvent.VK_O, true, true, false);
		openTemplateAction.add(true);
		
		// Action that COPIES a template
		copyTemplateAction = new CopyTemplateAction(this, "LetterTemplateModule.module.copy", 
				IconFetcher.getNormalIcon(GECAMedModule.class, GECAMedIconNames.COPY), 
				KeyEvent.VK_C, true, true, false);
		copyTemplateAction.add(true);
		
		// Action that ADDs a template
		addTemplateAction = new AddTemplateAction(this, "LetterTemplateModule.module.add", 
				IconFetcher.getNormalIcon(GECAMedModule.class, GECAMedIconNames.ADD), 
				KeyEvent.VK_A, true, true, false);
		addTemplateAction.add(true);
		
		// Action that deletes and removes a template
		deleteTemplateAction = new DeleteTemplateAction(this, "LetterTemplateModule.module.delete", 
				IconFetcher.getNormalIcon(GECAMedModule.class, GECAMedIconNames.REMOVE), 
				KeyEvent.VK_D, true, true, false);
		deleteTemplateAction.add(true);
		
	
		new GECAMedAction(this, "LetterTemplateModule.module.reload", GECAMedModule.getIcon(GECAMedModule.RELOAD), KeyEvent.VK_F5, true, true, false, KeyEvent.VK_F5) {
					private static final long serialVersionUID = 1L;
					public void actionPerformed(ActionEvent e) {
						refresh();			
					}
		}.add();
	}
	
	
	public void physicianChanged(Physician physician)
	{
		// When physician changes, update the list in order to show only
		// templates for that physician
		// details.renderManually();
		
		refreshTemplateTypes();
		refresh();
	}
	
	
	public static LetterTemplateModule getInstance()
	{
		return letterTemplateModule;
	}
	
	
	public JPanel getContentPane()
	{
		return contentPane;
	}
	
	
	public JList getList()
	{
		return list;
	}
	
	
	public LetterTemplateInterface getManager()
	{
		return templateManager;
	}
	
	
	public void setManager(LetterTemplateInterface manager)
	{
		this.templateManager = manager;
	}
	
	
	public ComboBoxTypeModel getCbModel()
	{
		return cbModel;
	}
	
	
	public TemplateDetailsPanel getDetails()
	{
		return details;
	}
	
	
	public void setDetails(TemplateDetailsPanel details)
	{
		this.details = details;
	}
	
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see lu.tudor.santec.gecamed.core.gui.GECAMedModule#afterShowup()
	 */
	@Override
	protected void afterShowup()
	{
		if (!isShowing())
			return;
		
		String tps = (String) LetterTemplateModule.getInstance().letterSettings.getValue(LetterTemplateSettings.TPS);
		Boolean allowOO = (Boolean) LetterTemplateModule.getInstance().letterSettings.getValue(LetterTemplateSettings.ALLOW_OO);
		
		if (tps.equals(LetterTemplateSettings.WORD) && SystemInfo.getOperatingSystem() != SystemInfo.SYSTEM_WINDOWS && ! allowOO)
		{
			JOptionPane.showMessageDialog(this, Translatrix.getTranslationString("LetterTemplateModule.dialog.error.conflict"));
		}
	}
	
	
	public LetterTemplateSettings getLetterSettings()
	{
		return letterSettings;
	}
	
	
	public void setLetterSettings(LetterTemplateSettings letterSettings)
	{
		this.letterSettings = letterSettings;
	}
	
	
	public void updateTemplateVersion()
	{
		openTemplateAction.openTemplate(true);
	}
	
	
	public void setModified (boolean modified)
	{
		this.isModified = modified;
		saveTemplateAction.setEnabled(modified);
		
		if (modified)
			 super.titlePanel.setColor(MODIFIED_COLOR);
		else super.titlePanel.setColor(LETTER_MODULE_COLOR);
	}
	
	
	@Override
	public boolean isModified()
	{
		return this.isModified;
	}
	
	
	public void save ()
	{
		LetterTemplate template = details.getChangedTemplate();
		LetterTemplateInterface	manager = (LetterTemplateInterface) ManagerFactory.getRemote(LetterTemplateBean.class);
		
		if (template != null)
			template = manager.saveDetails(template);
		
		refreshTemplateTypes();
		filter();
		
		this.setModified(false);
//		this.list.repaint();
	}
	
	
	public void refreshTemplateTypes ()
	{
		if (details.getCbModel() != null)
			details.getCbModel().queryAllTemplateTypes();
		if (cbModel != null)
		{
			String selectedType = (String) cbModel.getSelectedItem();
			cbModel.queryTemplateTypes();
			cbModel.setSelectedItem(selectedType);
		}
	}
	
	
	public void refresh ()
	{
		filter();
	}
	
	
	public Vector<String> getLetterStatuses ()
	{
		return letterSettings.getLetterStates();
	}
	
	/*
	 * return the, by the settings, selected controller.
	 */
	public static DocumentController getController()
	{
		String tps = (String) LetterTemplateModule.getInstance().getLetterSettings().getValue(LetterTemplateSettings.TPS);
		Boolean allowOO = false;
		try {
			allowOO = (Boolean) LetterTemplateModule.getInstance().letterSettings.getValue(LetterTemplateSettings.ALLOW_OO);			
		} catch (Exception e) {}
		
		return ControllerConfig.getController(tps, allowOO);
	}
}
