package lu.tudor.santec.gecamed.reporting.gui.listing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashSet;

import javax.swing.AbstractAction;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;

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.MainFrame;
import lu.tudor.santec.gecamed.core.gui.widgets.GECAMedBaseDialogImpl;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.reporting.ejb.entity.beans.Report;
import lu.tudor.santec.gecamed.reporting.ejb.entity.beans.ReportParameter;
import lu.tudor.santec.gecamed.reporting.ejb.session.beans.ReportManagerBean;
import lu.tudor.santec.gecamed.reporting.ejb.session.interfaces.ReportManagerInterface;
import lu.tudor.santec.gecamed.reporting.gui.ReportModule;
import lu.tudor.santec.gecamed.reporting.gui.creator.ReportCreatorDialog;
import lu.tudor.santec.gecamed.reporting.gui.designer.ReportDesignerDialog;
import lu.tudor.santec.i18n.Translatrix;

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

public class ReportList extends JPanel implements MouseListener
{
	/* ======================================== */
	// 		CONSTANTS
	/* ======================================== */
	
	private static final long	serialVersionUID	= 1L;
	
	/** the logger Object for this class */
	private static Logger logger = Logger.getLogger(ReportList.class.getName());
	
	
	
	/* ======================================== */
	// 		MEMBERS
	/* ======================================== */
	
	private static ReportManagerInterface	reportManager;
	
	
	private ReportDesignerDialog	reportDesigner;
	
	private ReportCreatorDialog		reportCreator;
	
	private	ReportListModel			model;
	
	private JList					list;
	
	private JPopupMenu				popupMenu;
	
	
	
	/* ======================================== */
	// 		CONSTRUCTORS
	/* ======================================== */
	
	public ReportList ()
	{
		super(new BorderLayout());
		
		JScrollPane	scroller;
		
		this.model	= new ReportListModel();
		this.list	= new JList(model);
		this.list.setCellRenderer(new ReportTemplateListRenderer());
		this.list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		this.list.addMouseListener(this);
		scroller	= new JScrollPane(list);
		scroller.setOpaque(false);
		scroller.getViewport().setOpaque(false);
		
		createPopupMenu();
		
		this.add(scroller, BorderLayout.CENTER);
	}
	
	
	
	/* ======================================== */
	// 		GETTER & SETTER
	/* ======================================== */
	
	public ReportDesignerDialog getDesingerDialog ()
	{
		if (this.reportDesigner == null)
			this.reportDesigner	= new ReportDesignerDialog();
		
		return this.reportDesigner;
	}
	
	
	public ReportCreatorDialog getCreatorDialog ()
	{
		if (this.reportCreator == null)
			this.reportCreator	= new ReportCreatorDialog();
		
		return this.reportCreator;
	}
	
	
	public JList getList ()
	{
		return this.list;
	}
	
	
	public boolean isReportSelected ()
	{
		return !this.list.isSelectionEmpty();
	}
	
	
	
	/* ======================================== */
	// 		CLASS BODY
	/* ======================================== */
	
	/**
	 * Reloads the reports from the database.
	 */
	public void reload ()
	{
		this.model.refresh();
	}
	
	
	/**
	 * Creates a new report with the selected template.<br> 
	 * A dialog to configure the report will be shown.
	 */
	public void createReportFromSelectedTemplate ()
	{
		getCreatorDialog().setReport((Report) list.getSelectedValue());
	}
	
	
	/**
	 * Creates and adds a new report template.<br>
	 * A dialog to configure the report template will be shown.
	 */
	public void addReportTemplate ()
	{
		Report	report	= getDesingerDialog().editReport(null);
		
		
		if (report == null)
			return;
		
		try
		{
			// save the report
			report	= getManager().saveReport(report);
			model.add(report);
		}
		catch (Exception e)
		{
			logger.log(Level.ERROR, e.getMessage(), e);
		}
	}
	
	
	/**
	 * Shows a dialog to edit the selected report template.
	 */
	public void editSelectedReportTemplate ()
	{
		Report	report;
		
		
		report	= (Report) list.getSelectedValue();
		report	= getDesingerDialog().editReport(report);
		
		if (report == null)
			return;
		
		try
		{
			// save the report
			report	= getManager().saveReport(report);
			model.refresh(report);
		}
		catch (Exception e)
		{
			logger.log(Level.ERROR, e.getMessage(), e);
		}
	}
	
	
	/**
	 * Removes the selected report template.
	 */
	public void removeSelectedReportTemplate ()
	{
		Report	report;
		String	message;
		int 	option;
		
		
		report	= (Report) list.getSelectedValue();
		
		if (report == null)
			return;
		
		message	= Translatrix.getTranslationString(
				"ReportModule.ReportList.removeReportTemplateMessage", 
				new String[] { report.getName() });
		option	= GECAMedBaseDialogImpl.showMessageDialog(this, 
				Translatrix.getTranslationString("ReportModule.ReportList.removeReportTemplateTitle"), 
				message, 
				GECAMedBaseDialogImpl.YES_NO_BUTTON_MODE, 
				GECAMedModule.getMediumIcon(GECAMedIconNames.WARNING));
		
		if (option == GECAMedBaseDialogImpl.YES_OPTION)
		{
			try
			{
				// delete the report
				if (getManager().deleteReport(report)
						&& !model.remove(report))
					model.remove(list.getSelectedIndex());
				
				validate();
				repaint();
			}
			catch (Exception e)
			{
				logger.log(Level.ERROR, e.getMessage(), e);
			}
		}
	}
	
	
	public void copySelectedReport ()
	{
		Report			reportToCopy	= (Report) list.getSelectedValue();
		Report			newReport		= (Report) reportToCopy.clone();
		String			newName			= newReport.getName();
		HashSet<String> reportNames		= getManager().getAllReportNames();
		
		while (true)
		{
			newName		= GECAMedBaseDialogImpl.showInputMessageDialog(
					MainFrame.getInstance(), 
					Translatrix.getTranslationString("ReportModule.copyReportTitle"), 
					Translatrix.getTranslationString("ReportModule.copyReportMessage"), 
					newName);
			
			if (newName == null)
				// cancel button was pressed - end
				return;
			// else: OK button was pressed - check name & proceed
			
			if (!reportNames.contains(newName))
				break;
			// else: show error message & continue until cancel was pressed or name is valid
			
			GECAMedBaseDialogImpl.showMessageDialog(MainFrame.getInstance(), 
					Translatrix.getTranslationString("ReportModule.copyReportErrorTitle"), 
					Translatrix.getTranslationString("ReportModule.copyReportErrorMessage"),
					GECAMedBaseDialogImpl.OK_BUTTON_MODE, 
					GECAMedModule.getIcon(GECAMedIconNames.ERROR));
		}
		
		newReport.setId(null);
		for (ReportParameter p : newReport.getParameter())
			p.setId(null);
		
		newReport.setName(newName);
		newReport	= getManager().saveReport(newReport);
		model.add(newReport);
		
		repaint();
		validate();
	}
	
	
	public void mouseClicked(MouseEvent e)
	{
		if (!e.isPopupTrigger() && e.getClickCount() > 1)
		{
			createReportFromSelectedTemplate();
		}
	}
	
	
	public void mousePressed(MouseEvent e) 
	{
		showPopupMenu(e);
	}
	
	
	public void mouseReleased(MouseEvent e) 
	{
		showPopupMenu(e);
	}
	
	
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	
	
	
	/* ======================================== */
	// 		HELP METHODS
	/* ======================================== */
	
	private ReportManagerInterface getManager ()
	{
		if (reportManager == null)
			reportManager	= (ReportManagerInterface) ManagerFactory.getRemote(ReportManagerBean.class);
		
		return reportManager;
	}
	
	
	private void createPopupMenu ()
	{
		JMenuItem	menuItem;
		
		
		popupMenu	= new JPopupMenu();
		popupMenu.setBackground(Color.WHITE);
		
		// create report menu item
		menuItem	= new JMenuItem(new AbstractAction(
				Translatrix.getTranslationString("ReportModule.createReport"), 
				IconFetcher.getMiniIcon(ReportModule.class, "reportmodule.png"))
		{
			private static final long	serialVersionUID	= 1L;

			public void actionPerformed(ActionEvent e)
			{
				if (isReportSelected())
					createReportFromSelectedTemplate();
			}
		});
		menuItem.setOpaque(false);
		popupMenu.add(menuItem);
		
		if (GECAMedModule.userHasPermission(ReportModule.PERMISSION_CREATE))
		{
			// edit report menu item
			menuItem	= new JMenuItem(new AbstractAction(
					Translatrix.getTranslationString("ReportModule.editReport"), 
					IconFetcher.getMiniIcon(ReportModule.class, "edit.png"))
			{
				private static final long	serialVersionUID	= 1L;
	
				public void actionPerformed(ActionEvent e)
				{
					if (isReportSelected())
						editSelectedReportTemplate();
				}
			});
			menuItem.setOpaque(false);
			popupMenu.add(menuItem);
			
			// copy report menu item
			menuItem	= new JMenuItem(new AbstractAction(
					Translatrix.getTranslationString("ReportModule.copyReport"),
					IconFetcher.getMiniIcon(GECAMedModule.class, GECAMedIconNames.COPY))
			{
				private static final long	serialVersionUID	= 1L;
	
				public void actionPerformed(ActionEvent e)
				{
					copySelectedReport();
				}
			});
			menuItem.setOpaque(false);
			popupMenu.add(menuItem);
			
			// remove report menu item
			menuItem	= new JMenuItem(new AbstractAction(
					Translatrix.getTranslationString("ReportModule.removeReport"), 
					IconFetcher.getMiniIcon(GECAMedModule.class, "remove.png"))
			{
				private static final long	serialVersionUID	= 1L;
	
				public void actionPerformed(ActionEvent e)
				{
					if (isReportSelected())
						removeSelectedReportTemplate();
				}
			});
			menuItem.setOpaque(false);
			popupMenu.add(menuItem);
		}
	}
	
	
	private void showPopupMenu (MouseEvent e)
	{
		if (e.isPopupTrigger())
		{
			list.setSelectedIndex(list.locationToIndex(e.getPoint()));
			popupMenu.show(list, e.getX(), e.getY());
		}
	}
}
