/*
 * FichaDataProvider.java
 *
 * Created on 30 de Marco de 2004, 11:31
 */

package siprp;

import java.text.DateFormat;
import java.util.Date;
import java.util.Hashtable;

import siprp.data.AvisoConstants;
import siprp.data.Marcacao;

import com.evolute.utils.Singleton;
import com.evolute.utils.arrays.Virtual2DArray;
import com.evolute.utils.data.IDObject;
import com.evolute.utils.data.MappableObject;
import com.evolute.utils.db.DBException;
import com.evolute.utils.db.DBManager;
import com.evolute.utils.db.Executer;
import com.evolute.utils.sql.Assignment;
import com.evolute.utils.sql.Expression;
import com.evolute.utils.sql.Field;
import com.evolute.utils.sql.Select;
import com.evolute.utils.sql.Select2;
import com.evolute.utils.sql.Update;
import com.evolute.utils.strings.StringPlainer;
import com.evolute.utils.ui.search.SearchDialog;
import com.evolute.utils.ui.search.SearchExecuter;

/**
 *
 * @author  pars
 */
public class FichaDataProvider 
	implements SearchExecuter {

	private static final Object LOCK = new Object();
	private static FichaDataProvider instance = null;
	private final Executer executer;

	public static final String SIPRP = "SIPRP - Sociedade Ib\u00e9rica de Preven\u00e7\u00e3o de Riscos Profissionais";
	
	// empresas
	public static final String T_EMPRESAS = "empresas";
	public static final String ID = "id";
	public static final String DESIGNACAO_SOCIAL = "designacao_social";
	public static final String SERVICO_SAUDE_TIPO = "servico_saude_tipo";
	public static final String SERVICO_SAUDE_DESIGNACAO = "servico_saude_designacao";
	public static final String SERVICO_HIGIENE_TIPO = "servico_higiene_tipo";
	public static final String SERVICO_HIGIENE_DESIGNACAO = "servico_higiene_designacao";
	public static final String INACTIVO = "inactivo";

//	public static final DBTable EMPRESAS =
//			new DBTable( T_EMPRESAS,
//					new String[]{ DESIGNACAO_SOCIAL,
//							SERVICO_SAUDE_TIPO,
//							SERVICO_SAUDE_DESIGNACAO,
//							SERVICO_HIGIENE_TIPO,
//							SERVICO_HIGIENE_DESIGNACAO,
//							INACTIVO },
//					ID );
	
	// estabelecimentos
	public static final String T_ESTABELECIMENTOS = "estabelecimentos";
	// ID
	public static final String NOME = "nome";
	public static final String LOCALIDADE = "localidade";
	public static final String EMPRESA_ID = "empresa_id";
	// INACTIVO

//	public static final DBTable ESTABELECIMENTOS =
//			new DBTable( T_ESTABELECIMENTOS,
//					new String[]{ NOME, LOCALIDADE, EMPRESA_ID, INACTIVO },
//					ID );

	// trabalhadores
	public static final String T_TRABALHADORES = "trabalhadores";
	// ID
	// public static final String NOME = "nome";
	public static final String SEXO = "sexo";
	public static final String DATA_NASCIMENTO = "data_nascimento";
	public static final String NACIONALIDADE = "nacionalidade";
	public static final String NUMERO_MECANOGRAFICO = "numero_mecanografico";
	public static final String DATA_ADMISSAO = "data_admissao";
	public static final String CATEGORIA = "categoria";
	public static final String LOCAL_TRABALHO = "local_trabalho";
	public static final String FUNCAO_PROPOSTA = "funcao_proposta";
	public static final String DATA_ADMISSAO_FUNCAO = "data_admissao_funcao";
	public static final String OBSERVACOES = "observacoes";
	public static final String ESTABELECIMENTO_ID = "estabelecimento_id";
	// INACTIVO

//	public static final DBTable TRABALHADORES =
//			new DBTable( T_TRABALHADORES,
//					new String[]{ NOME, SEXO, DATA_NASCIMENTO,
//							NACIONALIDADE, NUMERO_MECANOGRAFICO,
//							DATA_ADMISSAO, CATEGORIA, LOCAL_TRABALHO,
//							FUNCAO_PROPOSTA, DATA_ADMISSAO_FUNCAO,
//							OBSERVACOES, ESTABELECIMENTO_ID, INACTIVO },
//					ID );
	
	//medicos
	public static final String T_MEDICOS = "medicos";
	
	public static final String NUMERO_CEDULA = "numero_cedula";
	
//	public static final DBTable MEDICOS =
//			new DBTable( T_MEDICOS,
//					new String[]{ NOME, NUMERO_CEDULA }, ID );
		
	// exames
	public static final String T_EXAMES = "exames";
	// ID
	public static final String DATA = "data";
	public static final String TIPO = "tipo";
	public static final String OCASIONAL = "ocasional";
	public static final String OUTRO_TIPO = "outro_tipo";
	public static final String RESULTADO = "resultado";
	public static final String OUTRA_FUNCAO_1 = "outra_funcao_1";
	public static final String OUTRA_FUNCAO_2 = "outra_funcao_2";
	public static final String OUTRA_FUNCAO_3 = "outra_funcao_3";
	public static final String OUTRA_FUNCAO_4 = "outra_funcao_4";
	public static final String PROXIMO_EXAME = "proximo_exame";
	public static final String OUTRAS_RECOMENDACOES = "outras_recomendacoes";
	public static final String TRABALHADOR_ID = "trabalhador_id";	
	public static final String MEDICO_ID = "medico_id";	
	public static final String PDF = "pdf";

//	public static final DBTable EXAMES =
//			new DBTable( T_EXAMES,
//					new String[]{ DATA, TIPO, OCASIONAL,
//							OUTRO_TIPO, RESULTADO, OUTRA_FUNCAO_1,
//							OUTRA_FUNCAO_2, OUTRA_FUNCAO_3,
//							OUTRA_FUNCAO_4, PROXIMO_EXAME,
//							OUTRAS_RECOMENDACOES, TRABALHADOR_ID, MEDICO_ID, PDF, INACTIVO },
//					ID );
//
//	public static DBReference R_ESTABELECIMENTO_EMPRESA = new DBReference( ESTABELECIMENTOS.getFieldByName( EMPRESA_ID ) );
//	public static DBReference R_TRABALHADOR_ESTABELECIMENTO = new DBReference( TRABALHADORES.getFieldByName( ESTABELECIMENTO_ID ) );
//	public static DBReference R_EXAME_TRABALHADOR = new DBReference( EXAMES.getFieldByName( TRABALHADOR_ID ) );
//	public static DBReference R_EXAME_MEDICO = new DBReference( EXAMES.getFieldByName( MEDICO_ID ) );
//	static
//	{
//		try
//		{
//			EXAMES.addRelation( MEDICOS,
//						new DBField[]{ EXAMES.getFieldByName( MEDICO_ID ) },
//						"R_EXAMES_MEDICOS" );
//			EXAMES.addRelation( TRABALHADORES,
//						new DBField[]{ EXAMES.getFieldByName( TRABALHADOR_ID ) },
//						"R_EXAMES_TRABALHADORES" );
//			TRABALHADORES.addRelation( ESTABELECIMENTOS,
//						new DBField[]{ TRABALHADORES.getFieldByName( ESTABELECIMENTO_ID ) },
//						"R_TRABALHADORES_ESTABELECIMENTOS" );
//			ESTABELECIMENTOS.addRelation( EMPRESAS,
//						new DBField[]{ ESTABELECIMENTOS.getFieldByName( EMPRESA_ID ) },
//						"R_ESTABELECIMENTOS_EMPRESAS" );
//			EMPRESAS.disableSave( INACTIVO );
//			ESTABELECIMENTOS.disableSave( INACTIVO );
//			TRABALHADORES.disableSave( INACTIVO );
//			EXAMES.disableSave( PDF );
//		}
//		catch( Exception e )
//		{
//			throw new RuntimeException( e );
//		}
//	}
	
	public static final int SEARCH_EMPRESAS = 0;
	public static final int SEARCH_ESTABELECIMENTOS = 1;
	public static final int SEARCH_TRABALHADORES = 2;
	public static final int SEARCH_EXAMES = 3;
	private int SEARCH = 0;
	private int SEARCH_EMPRESAS_ID = -1;
	private int SEARCH_ESTABELECIMENTOS_ID = -1;
	private int SEARCH_TRABALHADORES_ID = -1;
	private int SEARCH_EXAMES_ID = -1;
	
	protected final Hashtable medicosEstabelecimentosHash = new Hashtable();

	/** Creates a new instance of FichaDataProvider */
	public FichaDataProvider()
		throws Exception
	{
		DBManager dbm = ( DBManager ) Singleton.getInstance( Singleton.DEFAULT_DBMANAGER /*SingletonConstants.DBMANAGER*/ );
		executer = dbm.getSharedExecuter( this );

//		setDBTable( EXAMES );
		
	}
	
//	public static MetaProvider getProvider()
//		throws Exception
//	{
//		synchronized( LOCK )
//		{
//			if( instance == null )
//			{
//				instance = new FichaDataProvider();
//			}
//		}
//		return instance;
//	}
	
	public static FichaDataProvider getProvider()
		throws Exception
	{
		synchronized( LOCK )
		{
			if( instance == null )
			{
				instance = new FichaDataProvider();
			}
		}
		return instance;
	}
	
	public String[] getColumnNames() {
		return new String[]{ "Nome" };
	}
	
	public String getSearchTitle() {
		switch( SEARCH )
		{
			case SEARCH_EMPRESAS:
				return "Procurar empresa";
			case SEARCH_ESTABELECIMENTOS:
				return "Procurar estabelecimento";
			case SEARCH_TRABALHADORES:
				return "Procurar trabalhador";
			case SEARCH_EXAMES:
				return "Procurar exame";
		}
		return "";
	}
	
	public boolean hasDetails() {
		return false;
	}

	public void setSearch( int what )
	{
		switch( what )
		{
			case SEARCH_EMPRESAS:
			case SEARCH_ESTABELECIMENTOS:
			case SEARCH_TRABALHADORES:
			case SEARCH_EXAMES:
				SEARCH = what;
				break;
		}
	}

	public void setSearchID( int what, int id )
	{
		switch( what )
		{
			case SEARCH_EMPRESAS:
				SEARCH_EMPRESAS_ID = id;
				break;
			case SEARCH_ESTABELECIMENTOS:
				SEARCH_ESTABELECIMENTOS_ID = id;
				break;
			case SEARCH_TRABALHADORES:
				SEARCH_TRABALHADORES_ID = id;
				break;
			case SEARCH_EXAMES:
				SEARCH_EXAMES_ID = id;
				break;
		}
	}

	public Virtual2DArray search( String pattern ) throws Exception {
		switch( SEARCH )
		{
			case SEARCH_EMPRESAS:
				return searchEmpresas( pattern );
			case SEARCH_ESTABELECIMENTOS:
				return searchEstabelecimentos( pattern );
			case SEARCH_TRABALHADORES:
				return searchTrabalhadores( pattern );
			case SEARCH_EXAMES:
				return searchExames( pattern );
		}
		return null;
	}
	
	public Virtual2DArray searchEmpresas( String pattern ) throws Exception {
		Select select = new Select( new String[]{ T_EMPRESAS },
							new String[]{ ID, DESIGNACAO_SOCIAL, "designacao_social_plain" },
							new Field( "designacao_social_plain" ).isLike( "%" + StringPlainer.convertString( pattern, false, false ) + "%" ).and(
							new Field( INACTIVO ).isDifferent( "y" ) ),
							new String[]{ "designacao_social_plain" }, null );
//		Select select = new Select( "SELECT e.id, e.designacao_social FROM empresas e ORDER BY lower( e.designacao_social );" );
		return executer.executeQuery( select );
	}

	public Virtual2DArray searchEstabelecimentos( String pattern ) throws Exception {
//		Select select = new Select( "SELECT e.id, e.nome FROM estabelecimentos e WHERE empresa_id = " + SEARCH_EMPRESAS_ID
//									+ " ORDER BY lower( e.nome )");
		Select select = new Select( new String[]{ T_ESTABELECIMENTOS },
							new String[]{ ID, NOME, "nome_plain" },
							new Field( "nome_plain" ).isLike( "%" + StringPlainer.convertString( pattern, false, false ) + "%" ).and(
							new Field( EMPRESA_ID ).isEqual( new Integer( SEARCH_EMPRESAS_ID ) ) ).and(
							new Field( INACTIVO ).isDifferent( "y" ) ),
							new String[]{ "nome_plain" }, null );
		return executer.executeQuery( select );
	}

	public Virtual2DArray searchTrabalhadores( String pattern ) throws Exception {
//		Select select = 
//			new Select( "SELECT t.id, t.nome FROM trabalhadores t, estabelecimentos es "
//						+ " WHERE t.estabelecimento_id = es.id "
//						+ " AND es.empresa_id = " + SEARCH_EMPRESAS_ID + " ORDER BY lower(t.nome);" );
		Select select = new Select( new String[]{ T_TRABALHADORES, T_ESTABELECIMENTOS },
							new String[]{ T_TRABALHADORES + "." + ID, T_TRABALHADORES + "." + NOME },
							new Field( T_TRABALHADORES + ".nome_plain" ).isLike( "%" + StringPlainer.convertString( pattern, false, false ) + "%" ).and(
							new Field( ESTABELECIMENTO_ID ).isEqual( new Field( T_ESTABELECIMENTOS + "." + ID ) ) ).and(
							new Field( ESTABELECIMENTO_ID ).isEqual( new Integer( SEARCH_ESTABELECIMENTOS_ID ) ) ).and(
							new Field( EMPRESA_ID ).isEqual( new Integer( SEARCH_EMPRESAS_ID ) ) ).and(
							new Field( T_TRABALHADORES + "." + INACTIVO ).isDifferent( "y" ) ),
							new String[]{ T_TRABALHADORES + ".nome_plain" }, null );
		return executer.executeQuery( select );
	}

	public Virtual2DArray searchExames( String pattern ) throws Exception {
		Select select = new Select( "SELECT e.id, e.data FROM exames e "
									+ " WHERE e.trabalhador_id = " + SEARCH_TRABALHADORES_ID 
									+ " ORDER BY e.data DESC;" );
		return executer.executeQuery( select );
	}

	public void showDetails(SearchDialog dialog, Object o) throws Exception {
	}
	
	public Object [][]getAllMedicos()
		throws Exception 
	{
		Select select = new Select( new String[]{ T_MEDICOS },
									new String[]{ ID, NOME, NUMERO_CEDULA },
									null, new String[]{ NOME }, null );
		Virtual2DArray array = executer.executeQuery( select );
		return array.getObjects();
	}
	
//	public void savePDF( MetaObject exame )
//		throws Exception
//	{
//		if( exame == null )
//		{
//			return;
//		}
//		DBKey key = exame.getPrimaryKeyValue();
//		DBField fields[] = EXAMES.getPrimaryKey();
//		Integer id = new Integer( ((Number)key.getFieldValue( fields[ 0 ] )).intValue() );
//		if( id == null )
//		{
//			throw new Exception( "Error saving pdf: id is null" );
//		}
//		byte []pdf = (byte[]) exame.getProperty( PDF );
//		BlobUpdate bUpdate = new BlobUpdate( T_EXAMES, PDF, pdf, new Field( ID ).isEqual( id ) );
//		executer.executeQuery( bUpdate );
//	}
	
	public Integer getLastExameIDForTrabalhador( Integer trabalhadorID )
		throws Exception
	{
		Select select = new Select( new String[]{ T_EXAMES },
									new String[]{ ID, DATA },
									new Field( TRABALHADOR_ID ).isEqual( trabalhadorID ),
									new String[]{ DATA + " DESC", ID + " DESC" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		if( array.columnLength() == 0 )
		{
			return null;
		}
		return new Integer( ( (Number) array.get( 0, 0 ) ).intValue() );
	}
	
	public IDObject []getAllFichasForTrabalhador( Integer trabalhadorID )
		throws Exception
	{
		Select select = 
				new Select( new String[]{ T_EXAMES }, new String[]{ "MAX("+ID+")", DATA },
							new Field( TRABALHADOR_ID ).isEqual( trabalhadorID ).and(
							new Field( INACTIVO ).isEqual( "n" ) ),
							new String[]{ DATA + " DESC" }, new String[]{ DATA } );
		Virtual2DArray array = executer.executeQuery( select );
		IDObject exames[] = new IDObject[ array.columnLength() ];
		DateFormat df = DateFormat.getDateInstance( DateFormat.SHORT );
		for( int n = 0; n < exames.length; n++ )
		{
			Date date = (Date)array.get( n, 1 );
			Integer id = new Integer( ((Number)array.get( n, 0 )).intValue() );
			exames[ n ] = new MappableObject( id, date != null? df.format( date ): "" );
		}
		return exames;
	}
	
	public IDObject []getAllEstabelecimentosForEmpresa( Integer empresaID )
		throws Exception
	{
		Select select = new Select( new String[]{ T_ESTABELECIMENTOS },
							new String[]{ ID, NOME, "nome_plain" },
							new Field( EMPRESA_ID ).isEqual( empresaID ).and(
							new Field( INACTIVO ).isDifferent( "y" ) ),
							new String[]{ "nome_plain" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		IDObject objects[] = new IDObject[ array.columnLength() ];
		for( int n = 0; n < objects.length; n++ )
		{
			Integer id = new Integer( ((Number)array.get( n, 0 )).intValue() );
			String desc = (String)array.get( n, 1 );
			objects[ n ] = new MappableObject( id, desc );
		}
		return objects;
	}
	
	public IDObject []getAllTrabalhadoresForEmpresa( Integer empresaID )
		throws Exception
	{
		Select select = new Select( new String[]{ T_TRABALHADORES, T_ESTABELECIMENTOS },
							new String[]{ T_TRABALHADORES + "." + ID, 
											T_TRABALHADORES + "." + NOME,
											T_TRABALHADORES + ".nome_plain" },
							new Field( T_ESTABELECIMENTOS + "." + EMPRESA_ID ).isEqual( empresaID ).and( 
							new Field( T_TRABALHADORES + "." + ESTABELECIMENTO_ID ).isEqual( 
							new Field( T_ESTABELECIMENTOS + "." + ID ) ) ),
							new String[]{ T_TRABALHADORES + ".nome_plain" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		IDObject objects[] = new IDObject[ array.columnLength() ];
		for( int n = 0; n < objects.length; n++ )
		{
			Integer id = new Integer( ((Number)array.get( n, 0 )).intValue() );
			String desc = (String)array.get( n, 1 );
			objects[ n ] = new MappableObject( id, desc );
		}
		return objects;
	}
	
	public IDObject []getAllTrabalhadoresForEstabelecimento( Integer estabelecimentoID )
		throws Exception
	{
		Select select = new Select( new String[]{ T_TRABALHADORES },
							new String[]{ ID, NOME, "nome_plain" },
							new Field( ESTABELECIMENTO_ID ).isEqual( estabelecimentoID ).and( 
							new Field( INACTIVO ).isDifferent( "y" ) ),
							new String[]{ "nome_plain" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		IDObject objects[] = new IDObject[ array.columnLength() ];
		for( int n = 0; n < objects.length; n++ )
		{
			Integer id = new Integer( ((Number)array.get( n, 0 )).intValue() );
			String desc = (String)array.get( n, 1 );
			objects[ n ] = new MappableObject( id, desc );
		}
		return objects;
	}
	
	public Integer getEstabelecimentoIDForTrabalhador( Integer trabalhadorID )
		throws Exception
	{
		Select select = new Select( new String[]{ T_TRABALHADORES },
							new String[]{ ESTABELECIMENTO_ID },
							new Field( ID ).isEqual( trabalhadorID ).and( 
							new Field( INACTIVO ).isDifferent( "y" ) ),
							null, null );
		Virtual2DArray array = executer.executeQuery( select );
		Integer estabelecimentoID = null;
		if( array != null && array.columnLength() > 0 )
		{
			estabelecimentoID = ( Integer )array.get( 0, 0 );
		}
		return estabelecimentoID;
	}
	
	public Integer getEmpresaIDForEstabelecimento( Integer estabelecimentoID )
		throws Exception
	{
		Select select = new Select( new String[]{ T_ESTABELECIMENTOS },
							new String[]{ EMPRESA_ID },
							new Field( ID ).isEqual( estabelecimentoID ).and( 
							new Field( INACTIVO ).isDifferent( "y" ) ),
							null, null );
		Virtual2DArray array = executer.executeQuery( select );
		Integer empresaID = null;
		if( array != null && array.columnLength() > 0 )
		{
			empresaID = ( Integer )array.get( 0, 0 );
		}
		return empresaID;
	}
	
	public Integer []getAvisosIDByTipoAndDate( Integer tipo, Date date )
		throws Exception
	{
		Select select = new Select( new String[]{ "avisos" }, new String[]{ "id", "data_evento" },
									new Field( "tipo" ).isEqual( tipo ).and( 
									new Field( "data_aviso" ).isLessOrEqual( date )),
									new String[]{ "data_evento" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		Integer ids[] = new Integer[ array.columnLength() ];
		for( int n = 0; n < ids.length; n++ )
		{
			ids[ n ] = new Integer( ((Number)array.get( n, 0 )).intValue() );
		}
		return ids;
	}
	
	public Object [][]getAvisosTrabalhadorByDate( Date date )
		throws Exception
	{
		Select select = new Select( new String[]{ "avisos", "empresas", "estabelecimentos", "trabalhadores" }, 
									new String[]{ "avisos.id", "avisos.data_evento", "avisos.descricao",
													"empresas.designacao_social", "estabelecimentos.nome",
													"trabalhadores.nome", "data_aviso" },
									new Field( "tipo" ).isEqual( new Integer( AvisoConstants.TIPO_TRABALHADOR ) ).and( 
									new Field( "data_aviso" ).isLessOrEqual( date ) ).and(
									new Field( "avisos.empresa_id" ).isEqual( new Field( "empresas.id" ) ) ).and(
									new Field( "avisos.estabelecimento_id" ).isEqual( new Field( "estabelecimentos.id" ) ) ).and(
									new Field( "avisos.trabalhador_id" ).isEqual( new Field( "trabalhadores.id" ) ) ),
									new String[]{ "data_evento" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		return array.getObjects();
	}
	
	public Object [][]getAvisosEstabelecimentoByDate( Date date )
		throws Exception
	{
		Select select = new Select( new String[]{ "avisos", "empresas", "estabelecimentos" }, 
									new String[]{ "avisos.id", "avisos.data_evento", "avisos.descricao",
													"empresas.designacao_social", "estabelecimentos.nome", "data_aviso" },
									new Field( "tipo" ).isEqual( new Integer( AvisoConstants.TIPO_ESTABELECIMENTO ) ).and( 
									new Field( "data_aviso" ).isLessOrEqual( date ) ).and(
									new Field( "avisos.empresa_id" ).isEqual( new Field( "empresas.id" ) ) ).and(
									new Field( "avisos.estabelecimento_id" ).isEqual( new Field( "estabelecimentos.id" ) ) ),
									new String[]{ "data_evento" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		return array.getObjects();
	}
	
	public Object [][]getAvisosEmpresaByDate( Date date )
		throws Exception
	{
		Select select = new Select( new String[]{ "avisos", "empresas" }, 
									new String[]{ "avisos.id", "avisos.data_evento", "avisos.descricao",
													"empresas.designacao_social", "data_aviso" },
									new Field( "tipo" ).isEqual( new Integer( AvisoConstants.TIPO_EMPRESA ) ).and( 
									new Field( "data_aviso" ).isLessOrEqual( date ) ).and(
									new Field( "avisos.empresa_id" ).isEqual( new Field( "empresas.id" ) ) ),
									new String[]{ "data_evento" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		return array.getObjects();
	}
	
	public Integer getMarcacaoIDByTrabalhador( Integer trabalhadorID )
		throws Exception 
	{
		Select realizadaSelect = 
			new Select( new String[]{ "marcacoes_trabalhador" },
						new String[]{ "MAX(data)" },
						new Field( "trabalhador_id" ).isEqual( trabalhadorID ).and(
						new Field( "estado" ).isEqual( new Integer( 2 ) ) ).and(
						new Field( "tipo" ).isEqual( new Integer( siprp.data.MarcacaoTrabalhadorData.TIPO_CONSULTA ) ) ) );
		Virtual2DArray realizadaArray = executer.executeQuery( realizadaSelect );
		Date realizada = (Date) realizadaArray.get( 0, 0 );
		Select select;
		if( realizada == null )
		{
			select = new Select( new String[]{ "marcacoes_trabalhador" },
								new String[]{ "MIN(id)" },
								new Field( "trabalhador_id" ).isEqual( trabalhadorID ).and(
								new Field( "estado" ).isEqual( new Integer( 0 ) ) ).and(
								new Field( "tipo" ).isEqual( new Integer( siprp.data.MarcacaoTrabalhadorData.TIPO_CONSULTA ) ) ) );
		}
		else
		{
			select = new Select( new String[]{ "marcacoes_trabalhador" },
								new String[]{ "MIN(id)" },
								new Field( "trabalhador_id" ).isEqual( trabalhadorID ).and(
								new Field( "estado" ).isEqual( new Integer( 0 ) ) ).and(
								new Field( "data" ).isGreater( realizada ) ).and(
								new Field( "tipo" ).isEqual( new Integer( siprp.data.MarcacaoTrabalhadorData.TIPO_CONSULTA ) ) ) );
		}
		Virtual2DArray array = executer.executeQuery( select );
		if( array.columnLength() == 0 || array.get( 0, 0 ) == null )
		{
			return null;
		}
		return new Integer( ( ( Number ) array.get( 0, 0 ) ).intValue() );
	}
	
	public IDObject[] getAllEmpresasDeleted()
		throws Exception
	{
		Select select = new Select( new String[]{ T_EMPRESAS },
									new String[]{ ID, DESIGNACAO_SOCIAL, "designacao_social_plain" },
									new Field( INACTIVO ).isEqual( "y" ),
									new String[]{ "designacao_social_plain" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		IDObject empresas[] = new IDObject[ array.columnLength() ];
		for( int n = 0; n < array.columnLength(); n++ )
		{
			Integer id = new Integer( ((Number)array.get( n, 0 )).intValue() );
			String designacao = ( String ) array.get( n, 1 );
			empresas[ n ] = new MappableObject( id, designacao );
		}
		return empresas;
	}
	
	public IDObject []getAllEstabelecimentosDeletedForEmpresa( Integer empresaID )
		throws Exception
	{
		Select select = new Select( new String[]{ T_ESTABELECIMENTOS },
							new String[]{ ID, NOME, "nome_plain" },
							new Field( EMPRESA_ID ).isEqual( empresaID ).and(
							new Field( INACTIVO ).isEqual( "y" ) ),
							new String[]{ "nome_plain" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		IDObject objects[] = new IDObject[ array.columnLength() ];
		for( int n = 0; n < objects.length; n++ )
		{
			Integer id = new Integer( ((Number)array.get( n, 0 )).intValue() );
			String desc = (String)array.get( n, 1 );
			objects[ n ] = new MappableObject( id, desc );
		}
		return objects;
	}
	
	public IDObject []getAllTrabalhadoresDeletedForEstabelecimento( Integer estabelecimentoID )
		throws Exception
	{
		Select select = new Select( new String[]{ T_TRABALHADORES },
							new String[]{ ID, NOME, "nome_plain" },
							new Field( ESTABELECIMENTO_ID ).isEqual( estabelecimentoID ).and( 
							new Field( INACTIVO ).isEqual( "y" ) ),
							new String[]{ "nome_plain" }, null );
		Virtual2DArray array = executer.executeQuery( select );
		IDObject objects[] = new IDObject[ array.columnLength() ];
		for( int n = 0; n < objects.length; n++ )
		{
			Integer id = new Integer( ((Number)array.get( n, 0 )).intValue() );
			String desc = (String)array.get( n, 1 );
			objects[ n ] = new MappableObject( id, desc );
		}
		return objects;
	}

	public Object[] getDadosUltimaMarcacao( Integer trabalhadorID )
		throws Exception
	{
		Select select = 
			new Select( new String[]{ "marcacoes_trabalhador" },
						new String[]{ "MAX( data )" },
						new Field( "trabalhador_id" ).isEqual( trabalhadorID ).and(
						new Field( "tipo" ).isEqual( new Integer( Marcacao.TIPO_MARCACAO_TRABALHADOR_CONSULTA ) ) ).and(
						new Field( "realizada" ).isEqual( "y" ).or(
							new Field( "estado" ).isEqual( new Integer( 2 ) ) ) ) );
		Virtual2DArray array = executer.executeQuery( select );
		if( array.columnLength() == 0 || array.get( 0, 0 ) == null )
		{
			return new Object[]{ null, null };
		}
		Date data = ( Date ) array.get( 0, 0 );
		select = 
			new Select( new String[]{ "marcacoes_trabalhador" },
						new String[]{ "motivo", "id" },
						new Field( "data" ).isEqual( data ).and( 
						new Field( "trabalhador_id" ).isEqual( trabalhadorID ) ).and(
						new Field( "tipo" ).isEqual( new Integer( Marcacao.TIPO_MARCACAO_TRABALHADOR_CONSULTA ) ) ).and(
						new Field( "realizada" ).isEqual( "y" ).or(
							new Field( "estado" ).isEqual( new Integer( 2 ) ) ) ),
						new String[]{ "id" }, null );
		array = executer.executeQuery( select );
		Integer tipo = ( Integer ) array.get( 0, 0 );
		if( tipo.intValue() == 5 )
		{
			tipo = new Integer( 2 );
		}
		return new Object[]{ data, tipo };
	}	
	
	public void setMedicoForEstabelecimento( Integer estabelecimentoID, Integer medicoID )
		throws Exception
	{
		Integer medicoAntigo = ( Integer ) medicosEstabelecimentosHash.get( estabelecimentoID );
		if( !medicoID.equals( medicoAntigo ) )
		{
			Update update = 
				new Update( "estabelecimentos",
							new Assignment[]{
								new Assignment( new Field( "medico_id" ), medicoID ) },
							new Field( "id" ).isEqual( estabelecimentoID ) );
			executer.executeQuery( update );
				medicosEstabelecimentosHash.put( estabelecimentoID, medicoID );
		}
	}
	
	public Integer getMedicoForEstabelecimento( Integer estabelecimentoID )
		throws Exception
	{
		if( !medicosEstabelecimentosHash.containsKey( estabelecimentoID ) )
		{
			Select select = 
				new Select( new String[]{ "estabelecimentos" },
							new String[]{ "medico_id" },
							new Field( "id" ).isEqual( estabelecimentoID ) );
			Virtual2DArray array = executer.executeQuery( select );
			Integer medicoID = ( Integer ) array.get( 0, 0 );
			if( medicoID == null )
			{
				medicoID = new Integer( -1 );
			}
			medicosEstabelecimentosHash.put( estabelecimentoID, medicoID );
		}
		return ( Integer ) medicosEstabelecimentosHash.get( estabelecimentoID );
	}

	public Long countTrabalhadoresActivosForEmpresa( Integer empresaID )
	{
		Long result = 0L;
		try
		{
			Select2 query = new Select2(  new String[]{ "trabalhadores", "estabelecimentos", "empresas" },
					new Integer[]{ Select2.JOIN_INNER, Select2.JOIN_INNER },
					new Expression[]{
					                 new Field("estabelecimentos.id").isEqual(new Field("trabalhadores.estabelecimento_id")),
					                 new Field("empresas.id").isEqual( new Field("estabelecimentos.empresa_id") ) },
					new String[]{"count(trabalhadores.id)" },
					new Field("empresas.id").isEqual( empresaID ).
					and( new Field("trabalhadores.inactivo").isEqual( "n" ) ).
					and( new Field("trabalhadores.data_demissao").isEqual( null )),
					null, null, null, null);
			Virtual2DArray returned = executer.executeQuery( query );
			if( returned.columnLength() > 0 )
			{
				result = (Long) returned.get( 0, 0 );
			}
		}
		catch (DBException e) {
			e.printStackTrace();
		}
		return result;
	}
}
