package siprp.medicina.processo.ui;

import static com.evolute.utils.strings.UnicodeLatin1Map.atilde;
import static com.evolute.utils.strings.UnicodeLatin1Map.ccedil;
import static com.evolute.utils.strings.UnicodeLatin1Map.iacute;
import static com.evolute.utils.strings.UnicodeLatin1Map.otilde;
import static info.clearthought.layout.TableLayoutConstants.FILL;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.CREATE_CONSULTA_MARCACAO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.CREATE_CONSULTA_MARCACAO_EMAIL;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.CREATE_CONSULTA_MARCACAO_EMAIL_VACINAS;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.CREATE_CONSULTA_MARCACAO_OBSERVACOES;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.CREATE_EXAME_MARCACAO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.CREATE_EXAME_MARCACAO_EMAIL;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.CREATE_EXAME_MARCACAO_OBSERVACOES;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.CREATE_PROCESSO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.LOAD_TRABALHADOR;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SAVE_CONSULTA_MARCACAO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SAVE_CONSULTA_MARCACAO_OBSERVACOES;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SAVE_EXAME_MARCACAO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SAVE_EXAME_MARCACAO_OBSERVACOES;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SAVE_PROCESSO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_CONSULTA;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_CONSULTA_MARCACAO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_CONSULTA_MARCACAO_EMAIL;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_CONSULTA_MARCACAO_OBSERVACAO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_EXAME;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_EXAME_MARCACAO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_EXAME_MARCACAO_EMAIL;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_EXAME_MARCACAO_OBSERVACAO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_FICHA;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_PROCESSO;
import static siprp.medicina.processo.logic.MedicinaProcessoLogic.SELECT_TRABALHADOR;
import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstraints;

import java.awt.CardLayout;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

import leaf.data.OrderedMap;
import leaf.ui.LeafCalendarDialog;
import leaf.ui.LeafInputField;
import leaf.ui.LeafOptionDialog;
import leaf.ui.LeafTextDialog;
import leaf.ui.LeafWindow;
import leaf.ui.LeafLogic.LeafUIActionBinding;
import leaf.ui.LeafWindow.ActionActivation;
import siprp.CompanyDataLoader;
import siprp.MedicinaConstants;
import siprp.ProcessoConstants;
import siprp.SingletonConstants;
import siprp.database.cayenne.objects.Contactos;
import siprp.database.cayenne.objects.Estabelecimentos;
import siprp.database.cayenne.objects.Prestadores;
import siprp.database.cayenne.objects.PrtGruposProtocolo;
import siprp.database.cayenne.objects.Trabalhadores;
import siprp.database.cayenne.objects.TrabalhadoresConsultas;
import siprp.database.cayenne.objects.TrabalhadoresConsultasDatas;
import siprp.database.cayenne.objects.TrabalhadoresConsultasDatasEmails;
import siprp.database.cayenne.objects.TrabalhadoresConsultasDatasObservacoes;
import siprp.database.cayenne.objects.TrabalhadoresEcd;
import siprp.database.cayenne.objects.TrabalhadoresEcds;
import siprp.database.cayenne.objects.TrabalhadoresEcdsDatas;
import siprp.database.cayenne.objects.TrabalhadoresEcdsDatasEmails;
import siprp.database.cayenne.objects.TrabalhadoresEcdsDatasObservacoes;
import siprp.database.cayenne.objects.TrabalhadoresFichasAptidao;
import siprp.database.cayenne.objects.TrabalhadoresProcesso;
import siprp.medicina.MedicinaDataProvider;
import siprp.medicina.processo.mail.MailDialog;

import com.evolute.utils.Singleton;

public class ProcessoDadosPanel extends JPanel
{
	private static final long serialVersionUID = 1L;
	private final LeafWindow parentWindow;

	private static final String PANEL_START_NAME = "START_PANEL";

	private static final String PANEL_TRABALHADOR_NAME = "TRABALHADOR_PANEL";

	private static final String PANEL_PROCESSO_NAME = "PROCESSO_PANEL";

	private static final String PANEL_FICHA_NAME = "PANEL_FICHA_NAME";

	private static final String PANEL_CONSULTA_NAME = "PANEL_CONSULTA_NAME";
	private static final String PANEL_CONSULTA_MARCACAO_NAME = "PANEL_CONSULTA_MARCACAO_NAME";
	private static final String PANEL_CONSULTA_MARCACAO_EMAIL_NAME = "PANEL_CONSULTA_MARCACAO_EMAIL_NAME";
	private static final String PANEL_CONSULTA_MARCACAO_OBSERVACOES_NAME = "PANEL_CONSULTA_MARCACAO_OBSERVACOES_NAME";

	private static final String PANEL_EXAME_NAME = "EXAME_PANEL";
	private static final String PANEL_EXAME_MARCACAO_NAME = "PANEL_EXAME_MARCACAO_NAME";
	private static final String PANEL_EXAME_MARCACAO_EMAIL_NAME = "PANEL_EXAME_MARCACAO_EMAIL_NAME";
	private static final String PANEL_EXAME_MARCACAO_OBSERVACAO_NAME = "PANEL_EXAME_MARCACAO_OBSERVACAO_NAME";

	private final CardLayout cardLayout = new CardLayout();

	// panels
	private final JPanel panelExame = new JPanel();
	private final JPanel panelExameMarcacao = new JPanel();
	private final JPanel panelExameMarcacaoEmail = new JPanel();
	private final JPanel panelExameMarcacaoObservacao = new JPanel();

	private final JPanel panelConsulta = new JPanel();
	private final JPanel panelConsultaMarcacao = new JPanel();
	private final JPanel panelConsultaMarcacaoEmail = new JPanel();
	private final JPanel panelConsultaMarcacaoObservacao = new JPanel();

	private final JPanel panelProcesso = new JPanel();

	private final JPanel panelTrabalhador = new JPanel();

	private final JPanel panelFicha = new JPanel();

	private final JPanel panelStart = new JPanel();

	// trabalhador
	private final JLabel labelTrabalhadorNome = new JLabel( "Nome" );
	private final JLabel labelTrabalhadorSexo = new JLabel( "Sexo" );
	private final JLabel labelTrabalhadorDataNascimento = new JLabel( "Data de Nascimento" );
	private final JLabel labelTrabalhadorNacionalidade = new JLabel( "Nacionalidade" );
	private final JLabel labelTrabalhadorBI = new JLabel( "B.I." );
	private final JLabel labelTrabalhadorObservacoes = new JLabel( "Observa" + ccedil + otilde + "es" );
	private final JLabel labelTrabalhadorDataAdmissao = new JLabel( "Data de Admiss" + atilde + "o" );

	public final LeafInputField<String> inputTrabalhadorNome = new LeafInputField<String>();
	public final LeafInputField<HashMap<String, String>> inputTrabalhadorSexo = new LeafInputField<HashMap<String, String>>();
	public final LeafInputField<Date> inputTrabalhadorDataNascimento = new LeafInputField<Date>();
	public final LeafInputField<String> inputTrabalhadorNacionalidade = new LeafInputField<String>();
	public final LeafInputField<String> inputTrabalhadorBI = new LeafInputField<String>();
	public final LeafInputField<String> inputTrabalhadorObservacoes = new LeafInputField<String>();
	public final LeafInputField<Date> inputTrabalhadorDataAdmissao = new LeafInputField<Date>();

	// processo

	private final JLabel labelProcessoEstado = new JLabel( "Estado" );
	private final JLabel labelProcessoDataInicio = new JLabel( "In" + iacute + "cio" );
	private final JLabel labelProcessoDataFim = new JLabel( "Fim" );
	private final JLabel labelProcessoMotivo = new JLabel( "Motivo" );

	public final LeafInputField<HashMap<String, String>> inputProcessoEstado = new LeafInputField<HashMap<String, String>>();
	public final LeafInputField<Date> inputProcessoDataInicio = new LeafInputField<Date>();
	public final LeafInputField<Date> inputProcessoDataFim = new LeafInputField<Date>();
	@ActionActivation(onSelect = "", onChange = SAVE_PROCESSO)
	public final LeafInputField<HashMap<Integer, String>> inputProcessoMotivo = new LeafInputField<HashMap<Integer, String>>();

	// consulta
	private final JLabel labelConsultaEstado = new JLabel( "Estado" );
	private final JLabel labelConsultaData = new JLabel( "Data" );
	private final JLabel labelConsultaPrestador = new JLabel( "Prestador" );

	public final LeafInputField<HashMap<Integer, String>> inputConsultaEstado = new LeafInputField<HashMap<Integer, String>>();
	public final LeafInputField<Date> inputConsultaData = new LeafInputField<Date>();
	public final LeafInputField<String> inputConsultaPrestador = new LeafInputField<String>();

	// marcacao consulta
	private final JLabel labelConsultaMarcacaoEstado = new JLabel( "Estado" );
	private final JLabel labelConsultaMarcacaoData = new JLabel( "Data" );
	private final JLabel labelConsultaMarcacaoPrestador = new JLabel( "Prestador" );

	public final LeafInputField<HashMap<Integer, String>> inputConsultaMarcacaoEstado = new LeafInputField<HashMap<Integer, String>>();
	public final LeafInputField<Date> inputConsultaMarcacaoData = new LeafInputField<Date>();
	@ActionActivation(onSelect = "", onChange = SAVE_CONSULTA_MARCACAO)
	public final LeafInputField<OrderedMap<Prestadores>> inputConsultaMarcacaoPrestador = new LeafInputField<OrderedMap<Prestadores>>();

	// email marcacao consulta
	private final JLabel labelConsultaMarcacaoEmailData = new JLabel( "Data" );
	private final JLabel labelConsultaMarcacaoEmailSubject = new JLabel( "Assunto" );
	private final JLabel labelConsultaMarcacaoEmailBody = new JLabel( "Mensagem" );

	public final LeafInputField<Date> inputConsultaMarcacaoEmailData = new LeafInputField<Date>();
	public final LeafInputField<String> inputConsultaMarcacaoEmailSubject = new LeafInputField<String>();
	public final LeafInputField<String> inputConsultaMarcacaoEmailBody = new LeafInputField<String>();

	// observacao marcacao consulta
	@ActionActivation(onSelect = "", onChange = SAVE_CONSULTA_MARCACAO_OBSERVACOES)
	public final LeafInputField<String> inputConsultaMarcacaoObsMensagem = new LeafInputField<String>();

	// exame
	private final JLabel labelExameEstado = new JLabel( "Estado" );
	private final JLabel labelExameData = new JLabel( "Data" );
	private final JLabel labelExameGruposEcds = new JLabel( "ECDs" );

	public final LeafInputField<HashMap<Integer, String>> inputExameEstado = new LeafInputField<HashMap<Integer, String>>();
	public final LeafInputField<OrderedMap<PrtGruposProtocolo>> inputExameGruposEcds = new LeafInputField<OrderedMap<PrtGruposProtocolo>>();
	public final LeafInputField<Date> inputExameData = new LeafInputField<Date>();

	// marcacao exame
	private final JLabel labelExameMarcacaoEstado = new JLabel( "Estado" );
	private final JLabel labelExameMarcacaoData = new JLabel( "Data" );
	private final JLabel labelExameMarcacaoGruposEcds = new JLabel( "ECDs" );
	private final JLabel labelExameMarcacaoPrestador = new JLabel( "Prestador" );
	private final JLabel labelExameMarcacaoAnalisador = new JLabel( "Analisadores" );
	private final JLabel labelExameMarcacaoDataRecepcao = new JLabel( "Data de recep" + ccedil + atilde + "o" );

	public final LeafInputField<HashMap<Integer, String>> inputExameMarcacaoEstado = new LeafInputField<HashMap<Integer, String>>();
	public final LeafInputField<Date> inputExameMarcacaoData = new LeafInputField<Date>();
	@ActionActivation(onSelect = "", onChange = SAVE_EXAME_MARCACAO)
	public final LeafInputField<Date> inputExameMarcacaoDataRecepcao = new LeafInputField<Date>();
	public final LeafInputField<OrderedMap<PrtGruposProtocolo>> inputExameMarcacaoGruposEcds = new LeafInputField<OrderedMap<PrtGruposProtocolo>>();
	@ActionActivation(onSelect = "", onChange = SAVE_EXAME_MARCACAO)
	public final LeafInputField<OrderedMap<Prestadores>> inputExameMarcacaoPrestador = new LeafInputField<OrderedMap<Prestadores>>();
	@ActionActivation(onSelect = "", onChange = SAVE_EXAME_MARCACAO)
	public final LeafInputField<OrderedMap<PrtGruposProtocolo>> inputExameMarcacaoAnalisador = new LeafInputField<OrderedMap<PrtGruposProtocolo>>();

	// email marcacao exame
	private final JLabel labelExameMarcacaoEmailData = new JLabel( "Data" );
	private final JLabel labelExameMarcacaoEmailSubject = new JLabel( "Assunto" );
	private final JLabel labelExameMarcacaoEmailBody = new JLabel( "Mensagem" );

	public final LeafInputField<Date> inputExameMarcacaoEmailData = new LeafInputField<Date>();
	public final LeafInputField<String> inputExameMarcacaoEmailSubject = new LeafInputField<String>();
	public final LeafInputField<String> inputExameMarcacaoEmailBody = new LeafInputField<String>();

	// observacao marcacao exame
	@ActionActivation(onSelect = "", onChange = SAVE_EXAME_MARCACAO_OBSERVACOES)
	public final LeafInputField<String> inputExameMarcacaoObsMensagem = new LeafInputField<String>();

	public ProcessoDadosPanel(LeafWindow parentWindow)
	{
		this.parentWindow = parentWindow;
		setupLayout();
		setupComponents();
		placeComponents();
	}

	private void setupLayout()
	{
		this.setLayout( cardLayout );
	}

	private void setupComponents()
	{
		setupStartPanel();
		setupTrabalhadorPanel();
		setupProcessoPanel();
		setupFichaPanel();
		setupConsultaPanel();
		setupConsultaMarcacaoPanel();
		setupConsultaMarcacaoEmailPanel();
		setupConsultaMarcacaoObservacoesPanel();
		setupExamePanel();
		setupExameMarcacaoPanel();
		setupExameMarcacaoEmailPanel();
		setupExameMarcacaoObservacoesPanel();
	}

	private void placeComponents()
	{
		add( panelStart, PANEL_START_NAME );
		add( panelTrabalhador, PANEL_TRABALHADOR_NAME );
		add( panelFicha, PANEL_FICHA_NAME );
		add( panelProcesso, PANEL_PROCESSO_NAME );
		add( panelConsulta, PANEL_CONSULTA_NAME );
		add( panelConsultaMarcacao, PANEL_CONSULTA_MARCACAO_NAME );
		add( panelConsultaMarcacaoEmail, PANEL_CONSULTA_MARCACAO_EMAIL_NAME );
		add( panelConsultaMarcacaoObservacao, PANEL_CONSULTA_MARCACAO_OBSERVACOES_NAME );
		add( panelExame, PANEL_EXAME_NAME );
		add( panelExameMarcacao, PANEL_EXAME_MARCACAO_NAME );
		add( panelExameMarcacaoEmail, PANEL_EXAME_MARCACAO_EMAIL_NAME );
		add( panelExameMarcacaoObservacao, PANEL_EXAME_MARCACAO_OBSERVACAO_NAME );
	}

	private int getIdade( Date nascimento )
	{
		int result = 0;
		if( nascimento != null )
		{
			Calendar now = Calendar.getInstance();
			Calendar birth = Calendar.getInstance();
			birth.setTime( nascimento );
			int birthYear = birth.get( Calendar.YEAR );
			int currentYear = now.get( Calendar.YEAR );
			if( birthYear < currentYear )
			{
				result = currentYear - birthYear;
				birth.add( Calendar.YEAR, result );
				if( birth.after( now ) )
				{
					--result;
				}
			}
		}
		return result;
	}

	@LeafUIActionBinding(action = {
			LOAD_TRABALHADOR, SELECT_TRABALHADOR
	})
	public void setForTrabalhador( Trabalhadores trabalhador )
	{
		if( trabalhador != null )
		{
			inputTrabalhadorDataNascimento.setObject( trabalhador.getDataNascimento() );
			inputTrabalhadorSexo.setObject( trabalhador.getSexos(), trabalhador.getSexo() );
			inputTrabalhadorNome.setObject( trabalhador.getNome() );
			inputTrabalhadorNacionalidade.setObject( trabalhador.getNacionalidade() );
			inputTrabalhadorBI.setObject( trabalhador.getBi() );
			inputTrabalhadorObservacoes.setObject( trabalhador.getObservacoesGestao() );
			inputTrabalhadorDataAdmissao.setObject( trabalhador.getDataAdmissao() );
			labelTrabalhadorDataNascimento.setText( "Data de Nascimento (" + getIdade( trabalhador.getDataNascimento() ) + " anos)" );

			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_START_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_PROCESSO)
	public void setForProcesso( TrabalhadoresProcesso processo )
	{
		if( processo != null )
		{
			boolean isFechado = ProcessoConstants.PROCESSO_FECHADO_CODE.equals( processo.getEstado() );
			inputProcessoDataFim.setObject( processo.getDataFim() );
			inputProcessoDataInicio.setObject( processo.getDataInicio() );
			inputProcessoEstado.setObject( processo.getEstados(), processo.getEstado() );
			inputProcessoMotivo.setEditable( !isFechado );
			inputProcessoMotivo.setObject( processo.getMotivos(), processo.getMotivo() );
			cardLayout.show( this, PANEL_PROCESSO_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_FICHA)
	public void setForFicha( TrabalhadoresFichasAptidao ficha )
	{
		if( ficha != null )
		{
			cardLayout.show( this, PANEL_FICHA_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_CONSULTA)
	public void setForConsulta( TrabalhadoresConsultas consulta )
	{
		if( consulta != null )
		{
			inputConsultaEstado.setObject( MedicinaDataProvider.getConsultaEstados(), consulta.getEstado() );
			inputConsultaData.setObject( consulta.getData() == null ? new Date( 0 ) : consulta.getData() );

			inputConsultaPrestador.setObject( (consulta.getToPrestadores() == null || consulta.getToPrestadores().getNome() == null) ? " " : consulta.getToPrestadores().getNome() );

			cardLayout.show( this, PANEL_CONSULTA_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_CONSULTA_MARCACAO)
	public void setForConsultaMarcacao( TrabalhadoresConsultasDatas marcacao )
	{
		if( marcacao != null )
		{
			inputConsultaMarcacaoData.setObject( marcacao.getData() );
			inputConsultaMarcacaoEstado.setObject( MedicinaDataProvider.getConsultaEstados(), marcacao.getEstado() );

			inputConsultaMarcacaoPrestador.setEditable( true );

			Prestadores prestador = marcacao.getToPrestadores();
			List<Prestadores> allPrestadores = Prestadores.getAllPrestadores();
			inputConsultaMarcacaoPrestador.setObject( new OrderedMap<Prestadores>( allPrestadores ), prestador == null ? Prestadores.prestadorNulo : prestador );
			cardLayout.show( this, PANEL_CONSULTA_MARCACAO_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_CONSULTA_MARCACAO_EMAIL)
	public void setForConsultaMarcacaoEmail( TrabalhadoresConsultasDatasEmails email )
	{
		if( email != null )
		{
			inputConsultaMarcacaoEmailBody.setObject( email.getBody() );
			inputConsultaMarcacaoEmailSubject.setObject( email.getSubject() );
			inputConsultaMarcacaoEmailData.setObject( email.getData() );
			cardLayout.show( this, PANEL_CONSULTA_MARCACAO_EMAIL_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_CONSULTA_MARCACAO_OBSERVACAO)
	public void setForConsultaMarcacaoObs( TrabalhadoresConsultasDatasObservacoes obs )
	{
		if( obs != null )
		{
			inputConsultaMarcacaoObsMensagem.setEditable( true );
			inputConsultaMarcacaoObsMensagem.setObject( obs.getObservacao() == null ? "" : obs.getObservacao() );
			cardLayout.show( this, PANEL_CONSULTA_MARCACAO_OBSERVACOES_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_EXAME)
	public void setForExame( TrabalhadoresEcds exame )
	{
		if( exame != null )
		{
			inputExameData.setObject( exame.getData() );
			inputExameEstado.setObject( exame.getEstados(), exame.getEstado() );
			OrderedMap<PrtGruposProtocolo> grupos = exame.getGruposExamesForPerfil();
			inputExameGruposEcds.setCollapseOptions( false );
			inputExameGruposEcds.setObject( grupos, grupos.getFirst() );
			cardLayout.show( this, PANEL_EXAME_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_EXAME_MARCACAO)
	public void setForExameMarcacao( TrabalhadoresEcdsDatas exameMarcacao )
	{
		if( exameMarcacao != null )
		{
			inputExameMarcacaoData.setObject( exameMarcacao.getData() );
			Date dataRecepcao = exameMarcacao.getDataRecepcao();
			inputExameMarcacaoDataRecepcao.setObject( dataRecepcao == null ? new Date(0) : dataRecepcao );
			inputExameMarcacaoDataRecepcao.setEditable( true );
			inputExameMarcacaoEstado.setObject( exameMarcacao.getEstados(), exameMarcacao.getEstado() );
			OrderedMap<PrtGruposProtocolo> grupos = exameMarcacao.getStatesForeGruposExames();
			inputExameMarcacaoGruposEcds.setCollapseOptions( false );
			inputExameMarcacaoGruposEcds.setObject( grupos, grupos.getFirst() );

			Prestadores prestador = exameMarcacao.getToPrestadores();
			List<Prestadores> allPrestadores = Prestadores.getAllPrestadores();

			if( prestador == null )
			{
				prestador = Prestadores.prestadorNulo;
			}

			inputExameMarcacaoPrestador.setEditable( true );
			inputExameMarcacaoPrestador.setObject( new OrderedMap<Prestadores>( allPrestadores ), prestador );

			boolean editable = Prestadores.prestadorNulo.equals( prestador );
			inputExameMarcacaoAnalisador.setCollapseOptions( false );

			List<TrabalhadoresEcd> allECDS = exameMarcacao.getTrabalhadoresEcdArray();
			OrderedMap<PrtGruposProtocolo> analisadoresForGrupos = new OrderedMap<PrtGruposProtocolo>();

			if( allECDS != null )
			{
				for( TrabalhadoresEcd current : allECDS )
				{
					Prestadores currentAnalisador = current.getToAnalisador();

					if( !prestador.equals( Prestadores.prestadorNulo ) )
					{
						currentAnalisador = prestador;
					}
					else if( currentAnalisador == null )
					{
						currentAnalisador = Prestadores.prestadorNulo;
					}

					PrtGruposProtocolo grupo = current.getToPrtTiposElementosProtocolo().getToPrtGruposProtocolo();
					if( !analisadoresForGrupos.containsKey( grupo ) )
					{
						analisadoresForGrupos.putLast( grupo, grupo.getDescricao() );
						LeafInputField<OrderedMap<Prestadores>> leaf = new LeafInputField<OrderedMap<Prestadores>>();
						leaf.setObject( new OrderedMap<Prestadores>( allPrestadores ), currentAnalisador );
						leaf.setEditable( editable );
						analisadoresForGrupos.putLast( grupo, leaf );
					}
				}
			}

			inputExameMarcacaoAnalisador.setObject( analisadoresForGrupos );

			inputExameMarcacaoAnalisador.setEditable( Prestadores.prestadorNulo.equals( prestador ) );

			cardLayout.show( this, PANEL_EXAME_MARCACAO_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_EXAME_MARCACAO_EMAIL)
	public void setForExameMarcacaoEmail( TrabalhadoresEcdsDatasEmails email )
	{
		if( email != null )
		{
			inputExameMarcacaoEmailBody.setObject( email.getBody() );
			inputExameMarcacaoEmailSubject.setObject( email.getSubject() );
			inputExameMarcacaoEmailData.setObject( email.getData() );
			cardLayout.show( this, PANEL_EXAME_MARCACAO_EMAIL_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = SELECT_EXAME_MARCACAO_OBSERVACAO)
	public void setForExameMarcacaoObs( TrabalhadoresEcdsDatasObservacoes obs )
	{
		if( obs != null )
		{
			inputExameMarcacaoObsMensagem.setObject( obs.getObservacao() == null ? "" : obs.getObservacao() );
			inputExameMarcacaoObsMensagem.setEditable( true );
			cardLayout.show( this, PANEL_EXAME_MARCACAO_OBSERVACAO_NAME );
		}
		else
		{
			cardLayout.show( this, PANEL_TRABALHADOR_NAME );
		}
	}

	@LeafUIActionBinding(action = CREATE_PROCESSO)
	public void setForNewProcesso( TrabalhadoresProcesso processo )
	{
		HashMap<Integer, String> tipos = processo.getMotivos();
		LeafOptionDialog<Integer> option = new LeafOptionDialog<Integer>( parentWindow, tipos, "Escolha o tipo de processo:" );
		Integer chosen = option.getOption();
		if( chosen != null )
		{
			processo.setMotivo( chosen );
		}
		inputProcessoMotivo.setObject( tipos, chosen );
		inputProcessoDataInicio.setObject( processo.getDataInicio() );
		inputProcessoDataFim.setObject( processo.getDataFim() );
		inputProcessoEstado.setObject( processo.getEstados(), processo.getEstado() );
	}

	@LeafUIActionBinding(action = CREATE_CONSULTA_MARCACAO)
	public void setForNewConsultaMarcacao( TrabalhadoresConsultasDatas marcacao )
	{
		LeafCalendarDialog calendar = new LeafCalendarDialog( parentWindow, this, false, true );
		Date date = calendar.getDate();
		if( date == null )
		{
			parentWindow.abortAction( true );
		}
		marcacao.setData( date );
	}

	@LeafUIActionBinding(action = CREATE_CONSULTA_MARCACAO_EMAIL)
	public void setForNewConsultaMarcacaoEmail( TrabalhadoresConsultasDatasEmails email )
	{
		if( email != null )
		{
			TrabalhadoresConsultasDatas consultaMarcacao = email.getToTrabalhadoresConsultasDatas();
			if( consultaMarcacao != null )
			{
				TrabalhadoresConsultas consulta = consultaMarcacao.getToTrabalhadoresConsultas();
				if( consulta != null )
				{
					String[] subjectAndBody = MedicinaConstants.ESTADO_REALIZADO == consulta.getEstado() ? sendMail( consulta.getToTrabalhadores(), consultaMarcacao.getDataString(), "", "" ) : sendMail( consulta.getToTrabalhadores(), consultaMarcacao.getDataString(), SingletonConstants.LETTER_CONSULTA, SingletonConstants.SUBJECT_CONSULTA );
					if( subjectAndBody != null )
					{
						email.setSubject( subjectAndBody[0] );
						email.setBody( subjectAndBody[1] );
					}
					else
					{
						parentWindow.abortAction( true );
					}
				}
			}
		}
	}
	
	@LeafUIActionBinding(action = CREATE_CONSULTA_MARCACAO_EMAIL_VACINAS)
	public void setForNewConsultaMarcacaoEmailVacinas( TrabalhadoresConsultasDatasEmails email )
	{
		if( email != null )
		{
			TrabalhadoresConsultasDatas consultaMarcacao = email.getToTrabalhadoresConsultasDatas();
			if( consultaMarcacao != null )
			{
				TrabalhadoresConsultas consulta = consultaMarcacao.getToTrabalhadoresConsultas();
				if( consulta != null )
				{
					String[] subjectAndBody = sendMail( consulta.getToTrabalhadores(), consultaMarcacao.getDataString(), SingletonConstants.LETTER_CONSULTA_VACINAS, SingletonConstants.SUBJECT_CONSULTA_VACINAS );
					if( subjectAndBody != null )
					{
						email.setSubject( subjectAndBody[0] );
						email.setBody( subjectAndBody[1] );
					}
					else
					{
						parentWindow.abortAction( true );
					}
				}
			}
		}
	}

	private String[] sendMail( Trabalhadores trabalhador, String data, String letterName, String subjectName )
	{
		String[] result = null;
		if( trabalhador != null )
		{
			Estabelecimentos estabelecimento = trabalhador.getToEstabelecimentos();
			if( estabelecimento != null )
			{
				String to = "";
				String bcc = "";
				String subject = "";
				String body = "";

				subject = (String) Singleton.getInstance( subjectName );
				if( subject == null )
				{
					subject = "";
				}
				subject = subject.replaceAll( CompanyDataLoader.NOME, trabalhador.getNome() );

				body = (String) Singleton.getInstance( letterName );
				if( body == null )
				{
					body = "";
				}
				body = body.replaceAll( CompanyDataLoader.DATA, data );
				body = body.replaceAll( CompanyDataLoader.NOME, trabalhador.getNome() );
				// body = body.replaceAll( CompanyDataLoader.MORADA, morada );
				body = body.replaceAll( "%0A", "<br>" );

				Contactos estabelecimentoContacto = estabelecimento.getToContactos();
				if( estabelecimentoContacto != null )
				{
					String estabelecimentoEmail = estabelecimentoContacto.getEmail();
					if( estabelecimentoEmail != null )
					{
						to = estabelecimentoEmail;
						try
						{
							MailDialog mailDialog = new MailDialog( parentWindow, to, bcc, subject, body );
							result = new String[2];
							result[0] = mailDialog.getSubject();
							result[1] = mailDialog.getMessage();
						} catch( Exception e )
						{
							e.printStackTrace( System.out );
							e.printStackTrace();
							result = null;
						}
					}
				}
			}
		}
		return result;
	}

	@LeafUIActionBinding(action = CREATE_CONSULTA_MARCACAO_OBSERVACOES)
	public void setForNewConsultaMarcacaoObservacoes( TrabalhadoresConsultasDatasObservacoes observacoes )
	{
		LeafTextDialog textDialog = new LeafTextDialog( parentWindow, this, "", true );
		String text = textDialog.getText();
		observacoes.setObservacao( text );
		inputConsultaMarcacaoObsMensagem.setEditable( true );
	}

	@LeafUIActionBinding(action = CREATE_EXAME_MARCACAO)
	public void setForNewExameMarcacao( TrabalhadoresEcdsDatas marcacao )
	{
		LeafCalendarDialog calendar = new LeafCalendarDialog( parentWindow, this, false, true );
		Date date = calendar.getDate();
		if( date == null )
		{
			parentWindow.abortAction( true );
		}
		marcacao.setData( date );

		OrderedMap<PrtGruposProtocolo> allGrupos = marcacao.getToTrabalhadoresEcds().getGruposExamesForPerfil();
		OrderedMap<PrtGruposProtocolo> grupos = new OrderedMap<PrtGruposProtocolo>();
		Map<PrtGruposProtocolo, Boolean> gruposSelected = new HashMap<PrtGruposProtocolo, Boolean>();
		for( int row = 0; row < allGrupos.rows(); ++row )
		{
			List<Object> grupo = allGrupos.getRow( row );
			if( grupo != null && grupo.size() > 1 )
			{
				String estado = grupo.get( 1 ).toString();
				if( MedicinaConstants.ESTADOS_EXAME_STR[MedicinaConstants.ESTADO_POR_MARCAR].equals( estado ) )
				{
					PrtGruposProtocolo key = allGrupos.getKeyForValue( grupo );
					gruposSelected.put( key, true );
					grupos.addRow( key, grupo );
				}
			}
		}
		LeafOptionDialog<PrtGruposProtocolo> gruposChosen = new LeafOptionDialog<PrtGruposProtocolo>( parentWindow, grupos, gruposSelected, null, "Escolha os ECDs para esta marca" + ccedil + atilde + "o", "Marcar >>" );
		for( PrtGruposProtocolo grupo : gruposChosen.getSelected() )
		{
			marcacao.marcarGrupoExames( grupo );
		}
	}

	@LeafUIActionBinding(action = CREATE_EXAME_MARCACAO_EMAIL)
	public void setForNewExameMarcacaoEmail( TrabalhadoresEcdsDatasEmails email )
	{
		if( email != null )
		{
			TrabalhadoresEcdsDatas exameMarcacao = email.getToTrabalhadoresEcdsDatas();
			if( exameMarcacao != null )
			{
				TrabalhadoresEcds exame = exameMarcacao.getToTrabalhadoresEcds();
				if( exame != null )
				{
					String[] subjectAndBody = MedicinaConstants.ESTADO_REALIZADO == exame.getEstado() ?
							sendMail( exame.getToTrabalhadores(), exame.getDataString(), "", "" )
							:
								sendMail( exame.getToTrabalhadores(), exameMarcacao.getDataString(), SingletonConstants.LETTER_EXAMES, SingletonConstants.SUBJECT_EXAMES );
					if( subjectAndBody != null )
					{
						email.setSubject( subjectAndBody[0] );
						email.setBody( subjectAndBody[1] );
					}
					else
					{
						parentWindow.abortAction( true );
					}
				}
			}
		}
	}

	@LeafUIActionBinding(action = CREATE_EXAME_MARCACAO_OBSERVACOES)
	public void setForNewExameMarcacaoObservacoes( TrabalhadoresEcdsDatasObservacoes observacoes )
	{
		LeafTextDialog textDialog = new LeafTextDialog( parentWindow, this, "", true );
		String text = textDialog.getText();
		observacoes.setObservacao( text );
		inputExameMarcacaoObsMensagem.setEditable( true );
	}

	@LeafUIActionBinding(action = SAVE_PROCESSO)
	public void updateToSaveProcesso( TrabalhadoresProcesso processo )
	{
		processo.setMotivo( (Integer) inputProcessoMotivo.getSelectedObject() );
	}

	@LeafUIActionBinding(action = SAVE_CONSULTA_MARCACAO)
	public void updateToSaveConsultaMarcacao( TrabalhadoresConsultasDatas marcacao )
	{
		Prestadores prestador = (Prestadores) inputConsultaMarcacaoPrestador.getSelectedObject();
		prestador = Prestadores.prestadorNulo.equals( prestador ) ? null : prestador;
		marcacao.setToPrestadores( prestador );
	}

	@LeafUIActionBinding(action = SAVE_CONSULTA_MARCACAO_OBSERVACOES)
	public void updateToSaveConsultaMarcacaoObservacoes( TrabalhadoresConsultasDatasObservacoes observacoes )
	{
		observacoes.setObservacao( inputConsultaMarcacaoObsMensagem.getObject() );
	}

	@LeafUIActionBinding(action = SAVE_EXAME_MARCACAO)
	public void updateToSaveExameMarcacao( TrabalhadoresEcdsDatas marcacao )
	{
		Date dataRecepcao = inputExameMarcacaoDataRecepcao.getObject();
		if( dataRecepcao == null || dataRecepcao.getTime() == 0l )
		{
			marcacao.setDataRecepcao( null );
		}
		else
		{
			marcacao.setDataRecepcao( dataRecepcao );
		}
		Prestadores prestador = (Prestadores) inputExameMarcacaoPrestador.getSelectedObject();
		prestador = Prestadores.prestadorNulo.equals( prestador ) ? null : prestador;
		marcacao.setToPrestadores( prestador );

		List<TrabalhadoresEcd> allEcd = marcacao.getTrabalhadoresEcdArray();
		if( allEcd != null )
		{
			OrderedMap<PrtGruposProtocolo> map = inputExameMarcacaoAnalisador.getObject();
			for( TrabalhadoresEcd ecd : allEcd )
			{
				PrtGruposProtocolo grupo = ecd.getToPrtTiposElementosProtocolo().getToPrtGruposProtocolo();
				Object value = map.getValue( grupo, 1 );
				if( value != null )
				{
					LeafInputField<OrderedMap<Prestadores>> leaf = (LeafInputField<OrderedMap<Prestadores>>) value;
					Prestadores ecdAnalisador = Prestadores.prestadorNulo.equals( (Prestadores) leaf.getSelectedObject() ) ? null : ((Prestadores) leaf.getSelectedObject());
					ecd.setToAnalisador( ecdAnalisador );
				}
			}
		}
	}

	@LeafUIActionBinding(action = SAVE_EXAME_MARCACAO_OBSERVACOES)
	public void updateToSaveExameMarcacaoObservacoes( TrabalhadoresEcdsDatasObservacoes observacoes )
	{
		observacoes.setObservacao( inputExameMarcacaoObsMensagem.getObject() );
	}

	private void setupStartPanel()
	{
	}

	private void setupSimpleDataPanel( JPanel panel, String name, JComponent... field )
	{
		double[] cols = new double[] {
			FILL
		};
		double[] rows = new double[field.length];
		for( int i = 0; i < field.length; rows[i++] = TableLayout.PREFERRED )
			;
		rows[rows.length - 1] = FILL;
		TableLayout layout = new TableLayout( cols, rows );
		layout.setHGap( 5 );
		layout.setVGap( 5 );
		panel.setLayout( layout );
		if( name != null )
		{
			panel.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), name ) );
		}

		for( int i = 0; i < field.length; ++i )
		{
			panel.add( field[i], new TableLayoutConstraints( 0, i ) );
		}
	}

	private void setupTrabalhadorPanel()
	{
		setupSimpleDataPanel( panelTrabalhador, "Trabalhador", labelTrabalhadorNome, inputTrabalhadorNome, labelTrabalhadorSexo, inputTrabalhadorSexo, labelTrabalhadorBI, inputTrabalhadorBI, labelTrabalhadorNacionalidade, inputTrabalhadorNacionalidade, labelTrabalhadorDataNascimento, inputTrabalhadorDataNascimento, labelTrabalhadorDataAdmissao, inputTrabalhadorDataAdmissao, labelTrabalhadorObservacoes, inputTrabalhadorObservacoes );
	}

	private void setupProcessoPanel()
	{
		setupSimpleDataPanel( panelProcesso, "Processo", labelProcessoEstado, inputProcessoEstado, labelProcessoDataInicio, inputProcessoDataInicio, labelProcessoDataFim, inputProcessoDataFim, labelProcessoMotivo, inputProcessoMotivo, new JPanel() );
	}

	private void setupConsultaPanel()
	{
		setupSimpleDataPanel( panelConsulta, "Consulta", labelConsultaEstado, inputConsultaEstado, labelConsultaData, inputConsultaData, labelConsultaPrestador, inputConsultaPrestador, new JPanel() );
	}

	private void setupFichaPanel()
	{
		setupSimpleDataPanel( panelFicha, "Ficha de Aptid" + atilde + "o", new JPanel() );
	}

	private void setupConsultaMarcacaoPanel()
	{
		setupSimpleDataPanel( panelConsultaMarcacao, "Marca" + ccedil + atilde + "o de Consulta", labelConsultaMarcacaoEstado, inputConsultaMarcacaoEstado, labelConsultaMarcacaoData, inputConsultaMarcacaoData, labelConsultaMarcacaoPrestador, inputConsultaMarcacaoPrestador, new JPanel() );
	}

	private void setupConsultaMarcacaoEmailPanel()
	{
		setupSimpleDataPanel( panelConsultaMarcacaoEmail, "Email", labelConsultaMarcacaoEmailData, inputConsultaMarcacaoEmailData, labelConsultaMarcacaoEmailSubject, inputConsultaMarcacaoEmailSubject, labelConsultaMarcacaoEmailBody, inputConsultaMarcacaoEmailBody );
	}

	private void setupConsultaMarcacaoObservacoesPanel()
	{
		setupSimpleDataPanel( panelConsultaMarcacaoObservacao, "Observa" + ccedil + otilde + "es", inputConsultaMarcacaoObsMensagem );
	}

	private void setupExamePanel()
	{
		setupSimpleDataPanel( panelExame, "Exame", labelExameEstado, inputExameEstado, labelExameData, inputExameData, labelExameGruposEcds, inputExameGruposEcds, new JPanel() );
	}

	private void setupExameMarcacaoPanel()
	{
		setupSimpleDataPanel( panelExameMarcacao, "Marca" + ccedil + atilde + "o de Exame", labelExameMarcacaoEstado, inputExameMarcacaoEstado, labelExameMarcacaoData, inputExameMarcacaoData, labelExameMarcacaoGruposEcds, inputExameMarcacaoGruposEcds, labelExameMarcacaoPrestador, inputExameMarcacaoPrestador, labelExameMarcacaoAnalisador, inputExameMarcacaoAnalisador, labelExameMarcacaoDataRecepcao, inputExameMarcacaoDataRecepcao, new JPanel() );
	}

	private void setupExameMarcacaoEmailPanel()
	{
		setupSimpleDataPanel( panelExameMarcacaoEmail, "Email", labelExameMarcacaoEmailData, inputExameMarcacaoEmailData, labelExameMarcacaoEmailSubject, inputExameMarcacaoEmailSubject, labelExameMarcacaoEmailBody, inputExameMarcacaoEmailBody );
	}

	private void setupExameMarcacaoObservacoesPanel()
	{
		setupSimpleDataPanel( panelExameMarcacaoObservacao, "Observa" + ccedil + otilde + "es", inputExameMarcacaoObsMensagem );
	}
}
