package siprp.higiene.relatorio;

import static com.evolute.utils.strings.UnicodeLatin1Map.aacute;
import static com.evolute.utils.strings.UnicodeLatin1Map.atilde;
import static com.evolute.utils.strings.UnicodeLatin1Map.ccedil;
import static com.evolute.utils.strings.UnicodeLatin1Map.eacute;
import static com.evolute.utils.strings.UnicodeLatin1Map.iacute;
import static com.evolute.utils.strings.UnicodeLatin1Map.oacute;
import static com.evolute.utils.strings.UnicodeLatin1Map.otilde;
import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstraints;

import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.EventObject;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import leaf.ui.LeafButton;
import leaf.ui.LeafError;
import leaf.ui.LeafIconButton;
import siprp.database.cayenne.objects.HsEmailEstabelecimento;
import siprp.database.cayenne.objects.HsRelatorio;
import siprp.database.cayenne.objects.MarcacoesEstabelecimento;
import siprp.database.cayenne.objects.MarcacoesTecnicosHst;
import siprp.higiene.gestao.equipamentos.AdicionarEquipamentosPanel;
import siprp.logic.HigieneSegurancaLogic;
import siprp.medicina.processo.mail.MailDialog;
import siprp.planoactuacao.print.PlanoActuacaoPDFCreator;

import com.evolute.utils.ui.calendar.JCalendarPanel;

public class PanelRelatorio extends JPanel implements CaretListener, ChangeListener, ActionListener
{

	private static final long serialVersionUID = 1L;

	private static final String ICON_NAME_SAVE = "siprp/higiene/gestao/riscos/save.png";
	private static final String ICON_NAME_REVERT = "siprp/higiene/gestao/riscos/revert.png";
	private static final String ICON_NAME_SUBMIT = "siprp/higiene/relatorio/submit.png";
	private static final String ICON_NAME_PDF = "siprp/higiene/relatorio/adobe_reader.png";
	private static final String ICON_NAME_UNDO = "siprp/higiene/relatorio/revert.png";

	private final JCalendarPanel dataRelatorio = new JCalendarPanel( null );

	private final JRadioButton radioInicial = new JRadioButton( "Inicial" );
	private final JRadioButton radioPeriodica = new JRadioButton( "Peri" + oacute + "dica" );

	private final JTextField fieldTecnico = new JTextField();

	private final JPanel panelAcompanhantes = new JPanel();

	private final JTextField fieldNome1 = new JTextField();
	private final JTextField fieldNome2 = new JTextField();

	private final JTextField fieldFuncao1 = new JTextField();
	private final JTextField fieldFuncao2 = new JTextField();

	private final LeafIconButton buttonSave = LeafIconButton.createButton( ICON_NAME_SAVE );
	private final LeafIconButton buttonRevertText = LeafIconButton.createButton( ICON_NAME_REVERT );
	private final LeafIconButton buttonSubmit = LeafIconButton.createButton( "Submeter", ICON_NAME_SUBMIT );
	private final LeafIconButton buttonPdfPlano = LeafIconButton.createButton( "Plano de actua" + ccedil + atilde + "o", ICON_NAME_PDF );
	private final LeafIconButton buttonPdfRelatorio = LeafIconButton.createButton( "Relat" + oacute + "rio", ICON_NAME_PDF );
	private final LeafButton buttonRevertPlano = LeafIconButton.createButton( "Recarregar", ICON_NAME_UNDO );
	
	private final AdicionarEquipamentosPanel panelEquipamentos = new AdicionarEquipamentosPanel();

	private final JTabbedPane tabs = new JTabbedPane();

	private final PlanoActuacaoPanel panelPlano = new PlanoActuacaoPanel();

	private final RelatorioLegislacaoPanel panelLegislacao = new RelatorioLegislacaoPanel();
	
	private final RelatorioNormalizacaoPanel panelNormalizacao = new RelatorioNormalizacaoPanel();
	
	ButtonGroup bg = new ButtonGroup();

	private HsRelatorio relatorio = null;

	public PanelRelatorio()
	{
		setupListeners();
		startupComponents();
		startupLayout();
		placeComponents();
	}

	private void startupComponents()
	{
		buttonPdfRelatorio.setEnabled( false );
		dataRelatorio.setPreferredSize( new Dimension( 150, 0 ) );
		panelEquipamentos.setPreferredSize( new Dimension( 400, 0 ) );
		bg.add( radioInicial );
		bg.add( radioPeriodica );
		panelAcompanhantes.setBorder( BorderFactory.createTitledBorder( "Pessoas que acompanharam" ) );
		panelEquipamentos.setBorder( BorderFactory.createTitledBorder( "Equipamentos de medi"+ccedil+atilde+"o" ) );
		tabs.addTab( "Plano de actua" + ccedil + atilde + "o", panelPlano );
		tabs.addTab( "Legisla" + ccedil + atilde + "o", panelLegislacao );
		tabs.addTab( "Normaliza" + ccedil + atilde + "o", panelNormalizacao );
		buttonSave.setToolTipText( "Guardar" );
		buttonRevertText.setToolTipText( "Reverter" );
		buttonRevertPlano.setToolTipText( "Carregar dados do estabelecimento" );
	}

	private void startupLayout()
	{
		TableLayout layout = new TableLayout( new double[] {
				TableLayout.MINIMUM, TableLayout.MINIMUM, TableLayout.MINIMUM, TableLayout.PREFERRED, TableLayout.FILL, TableLayout.MINIMUM, TableLayout.MINIMUM, TableLayout.PREFERRED
		}, new double[] {
				TableLayout.MINIMUM, TableLayout.MINIMUM, TableLayout.MINIMUM, TableLayout.MINIMUM, TableLayout.FILL
		} );
		layout.setVGap( 5 );
		layout.setHGap( 5 );
		setLayout( layout );

		layout = new TableLayout( new double[] {
				TableLayout.MINIMUM, TableLayout.FILL, TableLayout.MINIMUM, TableLayout.FILL
		}, new double[] {
				TableLayout.MINIMUM, TableLayout.MINIMUM
		} );
		layout.setVGap( 5 );
		layout.setHGap( 5 );
		panelAcompanhantes.setLayout( layout );
	}

	private void placeComponents()
	{
		panelAcompanhantes.add( new JLabel( "Nome" ), new TableLayoutConstraints( 0, 0 ) );
		panelAcompanhantes.add( fieldNome1, new TableLayoutConstraints( 1, 0 ) );
		panelAcompanhantes.add( new JLabel( "Fun" + ccedil + atilde + "o" ), new TableLayoutConstraints( 2, 0 ) );
		panelAcompanhantes.add( fieldFuncao1, new TableLayoutConstraints( 3, 0 ) );
		panelAcompanhantes.add( new JLabel( "Nome" ), new TableLayoutConstraints( 0, 1 ) );
		panelAcompanhantes.add( fieldNome2, new TableLayoutConstraints( 1, 1 ) );
		panelAcompanhantes.add( new JLabel( "Fun" + ccedil + atilde + "o" ), new TableLayoutConstraints( 2, 1 ) );
		panelAcompanhantes.add( fieldFuncao2, new TableLayoutConstraints( 3, 1 ) );
		
		TableLayout layout = new TableLayout( new double[] {
				TableLayout.MINIMUM, TableLayout.MINIMUM, TableLayout.FILL, TableLayout.MINIMUM, TableLayout.MINIMUM, TableLayout.MINIMUM, TableLayout.MINIMUM
		}, new double[] {
				TableLayout.MINIMUM
		} );
		layout.setVGap( 5 );
		layout.setHGap( 5 );
		JPanel panel = new JPanel();
		panel.setLayout( layout );

		panel.add( buttonSave, new TableLayoutConstraints( 0, 0 ) );
		panel.add( buttonRevertText, new TableLayoutConstraints( 1, 0 ) );
		panel.add( buttonPdfRelatorio, new TableLayoutConstraints( 3, 0 ) );
		panel.add( buttonPdfPlano, new TableLayoutConstraints( 4, 0 ) );
		panel.add( buttonRevertPlano, new TableLayoutConstraints( 5, 0 ) );
		panel.add( buttonSubmit, new TableLayoutConstraints( 6, 0 ) );
		
		add( panel, new TableLayoutConstraints( 0, 0, 7, 0 ) );
		add( new JLabel( "Data do relat" + oacute + "rio" ), new TableLayoutConstraints( 0, 1, 2, 1 ) );
		add( dataRelatorio, new TableLayoutConstraints( 3, 1 ) );
		JLabel labelAvaliacao = new JLabel( "Avalia" + ccedil + atilde + "o" );
		labelAvaliacao.setHorizontalAlignment( JLabel.RIGHT );
		add( labelAvaliacao , new TableLayoutConstraints( 4, 1 ) );
		add( radioInicial, new TableLayoutConstraints( 5, 1 ) );
		add( radioPeriodica, new TableLayoutConstraints( 6, 1 ) );
		add( new JLabel( "T" + eacute + "cnico Superior de H.S." ), new TableLayoutConstraints( 0, 2, 2, 2 ) );
		add( fieldTecnico, new TableLayoutConstraints( 3, 2, 6, 2 ) );
		add( panelEquipamentos, new TableLayoutConstraints( 7, 1, 7, 3 ) );
		add( panelAcompanhantes, new TableLayoutConstraints( 0, 3, 6, 3 ) );
		add( tabs, new TableLayoutConstraints( 0, 4, 7, 4 ) );
	}

	private void setupListeners()
	{
		fieldFuncao1.addCaretListener( this );
		fieldFuncao2.addCaretListener( this );
		fieldNome1.addCaretListener( this );
		fieldNome2.addCaretListener( this );
		dataRelatorio.addChangeListener( this );
		radioInicial.addActionListener( this );
		radioPeriodica.addActionListener( this );
		buttonSave.addActionListener( new ActionListener()
		{
			@Override
			public void actionPerformed( ActionEvent e )
			{
				save();
			}
		} );
		buttonRevertText.addActionListener( new ActionListener()
		{
			@Override
			public void actionPerformed( ActionEvent e )
			{
				revert();
			}
		} );
		buttonSubmit.addActionListener( new ActionListener()
		{
			@Override
			public void actionPerformed( ActionEvent e )
			{
				if( isValidEmail() || JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(null, "Emails n" + atilde + "o preenchidos para este estabelecimento!\nContinuar?", "Aviso", JOptionPane.YES_NO_OPTION ) )
				{
					if( isValidPlano() && confirmSubmit() )
					{
						submit();
					}
				}
			}
		} );
		buttonPdfPlano.addActionListener( new ActionListener()
		{
			@Override
			public void actionPerformed( ActionEvent e )
			{
				pdf();
			}
		} );
		buttonRevertPlano.addActionListener( new ActionListener()
		{
			@Override
			public void actionPerformed( ActionEvent e )
			{
				revert(true);
			}
		} );
	}
	
	protected void revert( boolean ask )
	{
		if( relatorio != null )
		{
			int ret = ask == false ? JOptionPane.YES_OPTION : JOptionPane.showConfirmDialog( this, "Todas as altera" + ccedil + otilde + "es ao plano de actua" + ccedil + atilde + "o ser" + atilde + "o perdidas\nTem a certeza?","Carregar dados do estabelecimento",JOptionPane.YES_NO_OPTION);
			if( JOptionPane.YES_OPTION == ret )
			{
				HigieneSegurancaLogic.reverterRelatorio(relatorio);
				setRelatorio( relatorio, false );
			}
		}
	}
	
	private boolean isValidEmail()
	{
		boolean result = false;
		List<HsEmailEstabelecimento> emails = relatorio.getToHsMarcacoesEstabelecimento().getToEstabelecimentos().getHsEmailEstabelecimento();
		result = emails != null && emails.size() > 0;
		return result;
	}
	
	private boolean isValidPlano()
	{
		boolean result = false;
		result = panelPlano.isValidPlano();
		if( !result )
		{
			JOptionPane.showMessageDialog( null, "Todos os riscos devem ser preenchidos antes da submiss"+ atilde + "o do plano de actua" + ccedil + atilde+ "o!", "Erro", JOptionPane.ERROR_MESSAGE, null );
		}
		return result;
	}
	
	private boolean confirmSubmit()
	{
		return JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog( this, "Ao submeter o Plano de Actua"+ccedil+atilde+"o n"+atilde+"o ser"+aacute+" mais poss"+iacute+"vel alter"+aacute+"-lo. Deseja continuar?" );
	}
	
	private void submit()
	{
		try
		{
			if( relatorio != null )
			{
				relatorio.setIsSubmetido( new Date() );
				relatorio.save();
				sendMail( relatorio );
				refresh();
				setRelatorio( relatorio, false );
			}
		} catch( Exception e )
		{
			LeafError.error(e);
		}
	}
	
	private boolean confirmDelete( File file )
	{
		boolean result = false;
		result = JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog( this, "Ficheiro j" + aacute + " existente, deseja substituir?", "Aviso", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null );
		return result;
	}
	
	private void pdf()
	{
		try
		{
			setCursor( new Cursor(Cursor.WAIT_CURSOR) );
			PlanoActuacaoPDFCreator creator = new PlanoActuacaoPDFCreator();
			byte [] pdf = creator.createPDF( relatorio.getId(), false );
			if( pdf != null )
			{
				JFileChooser fileChooser = new JFileChooser(  );
				if( fileChooser.showSaveDialog( this ) == JFileChooser.APPROVE_OPTION )
				{
					File file = fileChooser.getSelectedFile();
					String path = file.getAbsolutePath();
					if( !path.toUpperCase().endsWith( ".PDF" ) )
					{
						path += ".pdf";
						file = new File( path );
					}
					if( file != null )
					{
						if( file.exists() && confirmDelete( file ) )
						{
							file.delete();
						}
						FileOutputStream a = new FileOutputStream(file);
						a.write( pdf );
						a.close();
					}
				}
			}
		}
		catch( Exception e )
		{
			LeafError.error( e );
		}
		finally
		{
			setCursor( new Cursor(Cursor.DEFAULT_CURSOR) );
		}
	}
	
	private JFrame getFrame( )
	{
		Component comp = this;
		JFrame frame = null;
		while( comp != null )
		{
			if( comp.getParent() instanceof JFrame )
			{
				frame = (JFrame) comp.getParent();
				break;
			}
			comp = comp.getParent();
		}
		return frame;
	}
	
	private void sendMail( HsRelatorio relatorio )
	{
		try
		{
			
			List<HsEmailEstabelecimento> rels = relatorio.getToHsMarcacoesEstabelecimento().getToEstabelecimentos().getHsEmailEstabelecimento();
			String to = "";
			for( HsEmailEstabelecimento rel : rels )
			{
				to += rel.getToHsEmail().getEmail() + (to.length() == 0 ? "" : ", ");
			}
			if( to.length() > 0 && to.contains( "@" ) )
			{
				String nomeEstabelecimento = relatorio.getToHsMarcacoesEstabelecimento().getToEstabelecimentos().getNome();
				MarcacoesTecnicosHst tecnico = relatorio.getToHsMarcacoesEstabelecimento().getToMarcacoesTecnicosHst();
				String nomeTecnico = tecnico == null ? "" : tecnico.getNome();
				Date dataVisita = relatorio.getToHsMarcacoesEstabelecimento().getData();
				String dataVisitaString = new SimpleDateFormat("dd/MM/yyyy").format( dataVisita );
				String subject = "Relatório da Avaliação de Riscos Laborais e Plano de Actuação de " + nomeEstabelecimento + " - auditoria de " + dataVisitaString;
				String body =	"<html>Exmos. Senhores" +
								"<br>" +
								"<br>" +
								"<br>" +
								"Junto enviamos o relatório de avaliação de riscos laborais e " +
								"respectivo plano de actuação da auditoria realizada no dia " +
								dataVisitaString + 
								"ao vosso estabelecimento de(o) " +
								nomeEstabelecimento +
								". Aconselhamos que tenham em conta as não conformidades indicadas " +
								"nestes documentos e que preencham o plano de actuação por forma a " +
								"auxiliar-vos na planificação das medidas correctivas e para poderem " +
								"apresentá-los em caso de inspecção da ACT – Autoridade para as Condições do Trabalho." +
								"<br>" +
								"<br>" +
								"<br>" +
								"Caso pretendam o nosso apoio ou necessitem de qualquer esclarecimento, contactem-nos, por favor, através do telefone (+351) 213 504 540." +
								"<br>" +
								"<br>" +
								"<br>" +
								"Com os melhores cumprimentos, " +
								"<br>" +
								"<br>" +
								"<br>" +
								nomeTecnico + 
								"<br>" +
								"SIPRP - Sociedade Ibérica de Prevenção de Riscos Profissionais " +
								"<br>" +
								"Atrium Saldanha - Praça Duque de Saldanha, 1 - 9º G - 1050-094 Lisboa " +
								"<br>" +
								"Telefone: (+351) 213 504 540 " +
								"<br>" +
								"Fax: (+351) 213 504 549 " +
								"<br>" +
								"E-mail: geral@siprp.pt " +
								"<br>" +
								"URL: www.siprp.com " +
								"<br>" +
								"<br>" +
								"<br>" +
								"Esta é uma mensagem gerada automaticamente pelo nosso sistema, por favor não responda.</html>";
				new MailDialog( getFrame(), to, "", subject, body );
			}
		}
		catch( Exception ex )
		{
			ex.printStackTrace();
		}
	}
	
	private void save()
	{
		try
		{
			if( relatorio != null )
			{
				relatorio.setData( dataRelatorio.getDate() );
				relatorio.setAvaliacaoInicial( radioInicial.isSelected() );
			}
			relatorio.setAcompanhante1( fieldNome1.getText() );
			relatorio.setAcompanhante2( fieldNome2.getText() );
			
			relatorio.setFuncaoAcompanhante1(fieldFuncao1.getText());
			relatorio.setFuncaoAcompanhante2(fieldFuncao2.getText());
			relatorio.save();
			refresh();
			buttonRevertText.setEnabled( false );
			buttonSave.setEnabled( false );
		} catch( Exception e )
		{
			LeafError.error(e);
		}
	}
	
	private void revert()
	{
		refresh();
		buttonRevertText.setEnabled( false );
		buttonSave.setEnabled( false );
	}

	private void refresh()
	{
		dataRelatorio.setDate( relatorio == null ? null : relatorio.getData() );
		if( relatorio == null || relatorio.getAvaliacaoInicial() == null )
		{
			bg.clearSelection();
		}
		else
		{
			radioInicial.setSelected( relatorio.getAvaliacaoInicial() );
			radioPeriodica.setSelected( !relatorio.getAvaliacaoInicial() );
		}
		String tecnicoName = null;
		if(relatorio != null)
		{
			MarcacoesEstabelecimento marcacao = relatorio.getToHsMarcacoesEstabelecimento();
			if( marcacao != null )
			{
				MarcacoesTecnicosHst tecnico = marcacao.getToMarcacoesTecnicosHst();
				if( tecnico != null )
				{
					tecnicoName = tecnico.getNome();
				}
			}
		}
		fieldTecnico.setText( tecnicoName );
		fieldNome1.setText( relatorio == null ? null : relatorio.getAcompanhante1() );
		fieldNome2.setText( relatorio == null ? null : relatorio.getAcompanhante2() );
		fieldFuncao1.setText( relatorio == null ? null : relatorio.getFuncaoAcompanhante1() );
		fieldFuncao2.setText( relatorio == null ? null : relatorio.getFuncaoAcompanhante2() );
	}
	
	private void setEnabled()
	{
		boolean enabled = relatorio != null && relatorio.getIsSubmetido() == null;
		dataRelatorio.setEnabled( enabled );
		radioInicial.setEnabled( enabled );;
		radioPeriodica.setEnabled( enabled );
		fieldTecnico.setEnabled( false );
		fieldNome1.setEnabled( enabled );
		fieldNome2.setEnabled( enabled );
		fieldFuncao1.setEnabled( enabled );
		fieldFuncao2.setEnabled( enabled );
		buttonSubmit.setEnabled( enabled );
		buttonPdfPlano.setEnabled( enabled );
		buttonRevertPlano.setEnabled( enabled );
	}
	
	public void setRelatorio( HsRelatorio relatorio,boolean create )
	{
		this.relatorio = relatorio;
		buttonSave.setEnabled( false );
		buttonRevertText.setEnabled( false );
		panelEquipamentos.setRelatorio( relatorio );
		panelPlano.setRelatorio( relatorio );
		panelLegislacao.setRelatorio( relatorio );
		panelNormalizacao.setRelatorio( relatorio );
		if( create )
		{
			this.revert(false);
		}
		refresh();
		setEnabled();
	}
	
	private void updated( EventObject e )
	{
		Object source = e.getSource();
		if( source instanceof Component )
		{
			if( ( (Component) source).isEnabled() )
			{
				buttonSave.setEnabled( true );
				buttonRevertText.setEnabled( true );
			}
		}
	}

	@Override
	public void caretUpdate( CaretEvent e )
	{
		updated(e);
	}
	
	@Override
	public void stateChanged( ChangeEvent e )
	{
		updated(e);
	}

	@Override
	public void actionPerformed( ActionEvent e )
	{
		updated(e);
	}

}
