/*
 * MedicinaDataProvider.java
 *
 * Created on January 29, 2006, 12:27 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package siprp.medicina;

import java.util.*;

import com.evolute.utils.*;
import com.evolute.utils.arrays.*;
import com.evolute.utils.data.*;
import com.evolute.utils.db.*;
import com.evolute.utils.metadb.*;
import com.evolute.utils.sql.*;
import com.evolute.utils.tables.*;

import siprp.*;
import siprp.data.*;
/**
 *
 * @author fpalma
 */
public class MedicinaDataProvider extends MetaProvider
		implements MedicinaConstants
{
	

	public static final String TIPOS_CONSULTAS[] = 
		new String[]{ "", MOTIVO_ADMISSAO_STR, MOTIVO_PERIODICO_STR, MOTIVO_OCASIONAL_STR, "", MOTIVO_PERIODICO_INICIAL_STR };
	
	public static final HashMap<Integer,String> MOTIVOS_BY_ID =
			new HashMap<Integer,String>();
	
	public static final HashMap<Integer,String> SUB_MOTIVOS_BY_ID =
			new HashMap<Integer,String>();
	
	public static final HashMap<Integer,Integer[]> SUB_MOTIVOS_IDS_BY_MOTIVO_ID =
			new HashMap<Integer,Integer[]>();
	
//	public static final String  ESTADOS_EXAME_STR[] = 
//			new String[]{ "Por realizar", "Parcialmente realizado", "Realizado",
//							"Desmarcado trabalhador", 
//							"Desmarcado " + Singleton.getInstance( SingletonConstants.COMPANY_ACRONYM ),
//							"Faltou" };
//	
//	public static final String  ESTADOS_CONSULTA_STR[] = 
//			new String[]{ "Por realizar", "Parcialmente realizada", "Realizada",
//							"Desmarcada trabalhador", 
//							"Desmarcada " + Singleton.getInstance( SingletonConstants.COMPANY_ACRONYM ),
//							"Faltou" };
	
	private static final Object LOCK = new Object();
	private static MedicinaDataProvider instance = null;
	
	static
	{
		MOTIVOS_BY_ID.put( MOTIVO_ADMISSAO_INTEGER, MOTIVO_ADMISSAO_STR );
		MOTIVOS_BY_ID.put( MOTIVO_PERIODICO_INTEGER, MOTIVO_PERIODICO_STR );
		MOTIVOS_BY_ID.put( MOTIVO_OCASIONAL_INTEGER, MOTIVO_OCASIONAL_STR );
		MOTIVOS_BY_ID.put( MOTIVO_PERIODICO_INICIAL_INTEGER, MOTIVO_PERIODICO_INICIAL_STR );
		
		SUB_MOTIVOS_BY_ID.put( SUB_MOTIVO_APOS_DOENCA_INTEGER, SUB_MOTIVO_APOS_DOENCA_STR );
		SUB_MOTIVOS_BY_ID.put( SUB_MOTIVO_APOS_ACIDENTE_INTEGER, SUB_MOTIVO_APOS_ACIDENTE_STR );
		SUB_MOTIVOS_BY_ID.put( SUB_MOTIVO_PEDIDO_TRABALHADOR_INTEGER, SUB_MOTIVO_PEDIDO_TRABALHADOR_STR );
		SUB_MOTIVOS_BY_ID.put( SUB_MOTIVO_PEDIDO_SERVICO_INTEGER, SUB_MOTIVO_PEDIDO_SERVICO_STR );
		SUB_MOTIVOS_BY_ID.put( SUB_MOTIVO_MUDANCA_FUNCAO_INTEGER, SUB_MOTIVO_MUDANCA_FUNCAO_STR );
		SUB_MOTIVOS_BY_ID.put( SUB_MOTIVO_ALTERACAO_CONDICOES_INTEGER, SUB_MOTIVO_ALTERACAO_CONDICOES_STR );
		SUB_MOTIVOS_BY_ID.put( SUB_MOTIVO_OUTRO_INTEGER, SUB_MOTIVO_OUTRO_STR );
		
		SUB_MOTIVOS_IDS_BY_MOTIVO_ID.put( MOTIVO_OCASIONAL_INTEGER,
				new Integer[]{ SUB_MOTIVO_APOS_DOENCA_INTEGER, SUB_MOTIVO_APOS_ACIDENTE_INTEGER, 
								SUB_MOTIVO_PEDIDO_TRABALHADOR_INTEGER, SUB_MOTIVO_PEDIDO_SERVICO_INTEGER, 
								SUB_MOTIVO_MUDANCA_FUNCAO_INTEGER, SUB_MOTIVO_ALTERACAO_CONDICOES_INTEGER, 
								SUB_MOTIVO_OUTRO_INTEGER } );
	}
	
	private final Executer executer;
	
	/** Creates a new instance of MedicinaDataProvider */
	public MedicinaDataProvider()
		throws Exception
	{
		DBManager dbm = ( DBManager ) Singleton.getInstance( Singleton.DEFAULT_DBMANAGER /*SingletonConstants.DBMANAGER*/ );
		executer = dbm.getSharedExecuter( this );
	}
	
	public static MetaProvider getProvider()
		throws Exception
	{
		synchronized( LOCK )
		{
			if( instance == null )
			{
				instance = new MedicinaDataProvider();
			}
		}
		return instance;
	}
	
	public String []getEmpresaEstabelecimento( Integer empresaID, Integer estabelecimentoID )
		throws Exception
	{
		String nomes[] = new String[ 2 ];
		Select select = new Select( new String[]{ "empresas" }, 
									new String[]{ "designacao_social" },
									new Field( "id" ).isEqual( empresaID ) );
		Virtual2DArray array = executer.executeQuery( select );
		nomes[ 0 ] = ( String ) array.get( 0, 0 );
		
		select = new Select( new String[]{ "estabelecimentos" }, 
									new String[]{ "nome" },
									new Field( "id" ).isEqual( estabelecimentoID ) );
		array = executer.executeQuery( select );
		nomes[ 1 ] = ( String ) array.get( 0, 0 );
		
		return nomes;
	}
	
	public IDObject[] getDetalhesValidosTrabalhador( Integer empresaID, Integer trabalhadorID )
		throws Exception
	{
		Select select = 
				new Select( new String[]{ "trabalhadores" },
							new String[]{ "perfil" },
							new Field( "id" ).isEqual( trabalhadorID ) );
		Virtual2DArray array = executer.executeQuery( select );
		Integer perfil = ( Integer ) array.get( 0, 0 );
		if( perfil == null )
		{
			return new IDObject[ 0 ];
		}
		select = 
			new Select( new String[]{ "prt_elementos_protocolo", "prt_tipos_elementos_protocolo",
										"prt_grupos_protocolo" },
						new String[]{ "prt_grupos_protocolo.id" , "prt_grupos_protocolo.descricao", 
										"prt_grupos_protocolo.ordem"},
						new Field( "prt_elementos_protocolo.empresa_id" ).isEqual( empresaID ).and(
						new Field( "prt_elementos_protocolo.tipo_elemento_protocolo_id" ).isEqual( 
							new Field( "prt_tipos_elementos_protocolo.id" ) ) ).and(
						new Field( "prt_tipos_elementos_protocolo.grupo_protocolo_id" ).isEqual( 
							new Field( "prt_grupos_protocolo.id" ) ) ).and(
						new Field( "prt_elementos_protocolo.numero_perfil" ).isEqual( perfil ) ),
						new String[]{ "prt_grupos_protocolo.ordem" },
						null );
		array = executer.executeQuery( select );
		Vector detalhes = new Vector();
		Integer oldID = null;
		for( int n = 0; n < array.columnLength(); n++ )
		{
			Integer id = ( Integer ) array.get( n, 0 );
			if( id.equals( oldID ) )
			{
				continue;
			}
			oldID = id;
			String descricao = ( String ) array.get( n, 1 );
			detalhes.add( new MappableObject( id, descricao ) );
		}
		return ( IDObject[] ) detalhes.toArray( new IDObject[ detalhes.size() ] );
	}
	
	public void setDetalhesRealziadosForMarcacao( Integer marcacaoID, Integer detalhes[] )
		throws Exception
	{
		Delete delete = 
				new Delete( "marcacoes_grupos_realizados",
							new Field( "marcacao_trabalhador_id" ).isEqual( marcacaoID ) );
		executer.executeQuery( delete );
		Insert insert =
				new Insert( "marcacoes_grupos_realizados",
							new Assignment[]{ 
								new Assignment( new Field( "marcacao_trabalhador_id" ), marcacaoID ),
								new Assignment( new Field( "grupo_protocolo_id" ), detalhes ) } );
		executer.executeQuery( insert, null );
	}
	
	public Integer[] getDetalhesRealizadosForMarcacao( Integer marcacaoID )
		throws Exception
	{
		Select select = 
				new Select( new String[]{ "marcacoes_grupos_realizados" },
							new String[]{ "grupo_protocolo_id" },
							new Field( "marcacao_trabalhador_id" ).isEqual( marcacaoID ) );
		Virtual2DArray array = executer.executeQuery( select );
		Integer ids[] = new Integer[ array.columnLength() ];
		for( int n = 0; n < array.columnLength(); n++ )
		{
			ids[ n ] = ( Integer ) array.get( n, 0 );
		}
		return ids;
	}
	
	public Integer[] getDetalhesRealizadosForEstadosMarcacao( Integer marcacaoID )
		throws Exception
	{
		Select select = 
				new Select( new String[]{ "marcacoes_grupos_realizados", "marcacoes_trabalhador_estados" },
							new String[]{ "grupo_protocolo_id" },
							new Field( "marcacoes_trabalhador_estados.marcacao_id" ).isEqual( marcacaoID ).and( 
							new Field( "marcacoes_trabalhador_estados.id" ).isEqual( 
										new Field( "marcacoes_grupos_realizados.marcacoes_trabalhador_estado_id" ) ) ) );
		Virtual2DArray array = executer.executeQuery( select );
		Integer ids[] = new Integer[ array.columnLength() ];
		for( int n = 0; n < array.columnLength(); n++ )
		{
			ids[ n ] = ( Integer ) array.get( n, 0 );
		}
		return ids;
	}
	
	public void deleteDetalhesRealizadosForMarcacao( Integer marcacaoID )
		throws Exception
	{
		Delete delete = 
				new Delete( "marcacoes_grupos_realizados",
							new Field( "marcacao_trabalhador_id" ).isEqual( marcacaoID ) );
		executer.executeQuery( delete );
	}
	
	public Object[][] getExamesTrabalhador( Integer trabalhadorID )
		throws Exception
	{
		Select select = 
				new Select( new String[]{ "marcacoes_trabalhador" },
							new String[]{ "id", "data", "estado" },
							new Field( "trabalhador_id" ).isEqual( trabalhadorID ).and(
							new Field( "tipo" ).isEqual( new Integer( Marcacao.TIPO_MARCACAO_TRABALHADOR_EXAMES ) ) ),
							new String[]{ "data desc" },
							null );
		Virtual2DArray array = executer.executeQuery( select );
		Object data[][] = array.getObjects();
		for( int n = 0; n < data.length; n++ )
		{
			int estado = ( ( Integer ) data[ n ][ 2 ] ).intValue();
			data[ n ][ 2 ] = ESTADOS_EXAME_STR[ estado ];
		}
		return data;
	}
	
	public Object[][] getConsultasTrabalhador( Integer trabalhadorID )
		throws Exception
	{
		Select select = 
				new Select( new String[]{ "marcacoes_trabalhador" },
							new String[]{ "id", "data", "estado" },
							new Field( "trabalhador_id" ).isEqual( trabalhadorID ).and(
							new Field( "tipo" ).isEqual( new Integer( Marcacao.TIPO_MARCACAO_TRABALHADOR_CONSULTA ) ) ),
							new String[]{ "data desc" },
							null );
		Virtual2DArray array = executer.executeQuery( select );
		Object data[][] = array.getObjects();
		for( int n = 0; n < data.length; n++ )
		{
			int estado = ( ( Integer ) data[ n ][ 2 ] ).intValue();
			data[ n ][ 2 ] = ESTADOS_CONSULTA_STR[ estado ];
		}

		return data;
	}
	
	public ColumnizedMappable[] getAllEmpresas()
		throws Exception
	{
		Select select =
				new Select( new String[]{ "empresas" },
							new String[]{ "id", "designacao_social", "designacao_social_plain" },
							new Field( "inactivo" ).isDifferent( "y" ),
							new String[]{ "designacao_social_plain" },
							null );
		Virtual2DArray array = executer.executeQuery( select );
		ColumnizedMappable empresas[] = new ColumnizedMappable[ array.columnLength() ];
		for( int n = 0; n < empresas.length; n++ )
		{
			Integer id = ( Integer ) array.get( n, 0 );
			String designacao = ( String ) array.get( n, 1 );
			empresas[ n ] = new ColumnizedMappable( id, designacao );
		}
		return empresas;
	}
	
	public ColumnizedMappable[] getAllEstabelecimentosForEmpresa( Integer empresaID )
		throws Exception
	{
		Select select =
				new Select( new String[]{ "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 );
		ColumnizedMappable estabelecimentos[] = new ColumnizedMappable[ array.columnLength() ];
		for( int n = 0; n < estabelecimentos.length; n++ )
		{
			Integer id = ( Integer ) array.get( n, 0 );
			String nome = ( String ) array.get( n, 1 );
			estabelecimentos[ n ] = new ColumnizedMappable( id, nome );
		}
		return estabelecimentos;
	}
	
	public ColumnizedMappable[] getAllTrabalhadoresForEstabelecimento( Integer estabelecimentoID )
		throws Exception
	{
		Select select =
				new Select( new String[]{ "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 );
		ColumnizedMappable trabalhadores[] = new ColumnizedMappable[ array.columnLength() ];
		for( int n = 0; n < trabalhadores.length; n++ )
		{
			Integer id = ( Integer ) array.get( n, 0 );
			String nome = ( String ) array.get( n, 1 );
			trabalhadores[ n ] = new ColumnizedMappable( id, nome );
		}
		return trabalhadores;
	}
	
	/**
	 * Devolve o identificador da consulta de um trabalhador para um dado motivo e dia.
	 *
	 * @param trabalhadorID o identificador do trabalhador
	 * @param motivo o identificador do motivo da marcacao
	 * @param data a data da marcacao
	 * @return o identificador da consulta ou <code>null</code> se n&atilde;o houver nenhuma
	 * @throws Exception se houver um erro na liga&ccedil;o &agrave; Base de Dados
	 */
	public Integer getConsultaIDByTrabalhadorMotivoAndDate( Integer trabalhadorID, Integer motivo, Date data )
		throws Exception
	{
		Integer motivos[];
		if( motivo != null && ( motivo.intValue() == MOTIVO_PERIODICO || motivo.intValue() == MOTIVO_PERIODICO_INICIAL ) )
		{
			motivos = new Integer[]{ MOTIVO_PERIODICO_INTEGER, MOTIVO_PERIODICO_INICIAL_INTEGER };
		}
		else
		{
			motivos = new Integer[]{ motivo };
		}
		Select select = 
				new Select( new String[]{ "marcacoes_trabalhador" },
							new String[]{ "id" },
							new Field( "trabalhador_id" ).isEqual( trabalhadorID ).and(
							new Field( "tipo" ).isEqual( new Integer( Marcacao.TIPO_MARCACAO_TRABALHADOR_CONSULTA ) ) ).and(
							new Field( "data" ).isEqual( data ) ).and(
							new Field( "motivo" ).in( motivos ) ) );
		Virtual2DArray array = executer.executeQuery( select );
		Integer id;
		if( array.columnLength() == 0 || array.get( 0, 0 ) == null )
		{
			id = null;
		}
		else
		{
			id = ( Integer ) array.get( 0, 0 );
		}
		return id;
	}
	
	/**
	 * Devolve o identificador da primeira consulta de um trabalhador n&&atilde;o realizada depois de um diapara um dado motivo.
	 *
	 * @param trabalhadorID o identificador do trabalhador
	 * @param motivo o identificador do motivo da marcacao
	 * @param data a data de in&iacute;cio de procura
	 * @return o identificador da consulta ou <code>null</code> se n&atilde;o houver nenhuma
	 * @throws Exception se houver um erro na liga&ccedil;o &agrave; Base de Dados
	 */
	public Integer getProximaConsultaIDByTrabalhadorMotivoAndDate( Integer trabalhadorID, Integer motivo, Date data )
		throws Exception
	{
		Select select = 
				new Select( new String[]{ "marcacoes_trabalhador" },
							new String[]{ "id", "data" },
							new Field( "trabalhador_id" ).isEqual( trabalhadorID ).and(
							new Field( "tipo" ).isEqual( new Integer( Marcacao.TIPO_MARCACAO_TRABALHADOR_CONSULTA ) ) ).and(
							new Field( "data" ).isGreater( data ) ).and(
							new Field( "motivo" ).isEqual( motivo ) ).and(
							new Field( "estado" ).isEqual( new Integer( 0 ) ) ),
							new String[]{ "data" },
							null );
		Virtual2DArray array = executer.executeQuery( select );
		Integer id;
		if( array.columnLength() == 0 || array.get( 0, 0 ) == null )
		{
			id = null;
		}
		else
		{
			id = ( Integer ) array.get( 0, 0 );
		}
		return id;
	}
	
	public Object[][] getListaConsultasByData( Date data )
		throws Exception
	{
		Select2 select = 
				new Select2( new String[]{ "marcacoes_trabalhador", "trabalhadores", "estabelecimentos", "empresas" },
								new Integer[]{ Select2.JOIN_INNER, Select2.JOIN_INNER, Select2.JOIN_INNER },
								new Expression[]{ 
									new Field( "marcacoes_trabalhador.trabalhador_id" ).isEqual( new Field( "trabalhadores.id" ) ),
									new Field( "trabalhadores.estabelecimento_id" ).isEqual( new Field( "estabelecimentos.id" ) ),
									new Field( "estabelecimentos.empresa_id" ).isEqual( new Field( "empresas.id" ) ) },
								new String[]{ "marcacoes_trabalhador.id", "trabalhadores.nome", "trabalhadores.nome_plain", 
												"empresas.designacao_social", "marcacoes_trabalhador.tipo", "prestador_id" },
								new Field( "marcacoes_trabalhador.data" ).isEqual( data ).and(
									new Field( "marcacoes_trabalhador.estado" ).isEqual( 
												new Integer( Marcacao.ESTADO_POR_REALIZAR ) ) ).and( 
								new Field( "marcacoes_trabalhador.tipo" ).isEqual( new Integer( Marcacao.TIPO_MARCACAO_TRABALHADOR_CONSULTA ) ) ),
								null,
								null,
								null,
								null );
		Virtual2DArray array = executer.executeQuery( select );
		return array.getObjects();
	}
	
	public Object[][] getListaECDsByData( Date data )
		throws Exception
	{
		Select2 select = 
				new Select2( new String[]{ "marcacoes_trabalhador", "trabalhadores", "estabelecimentos", "empresas" },
								new Integer[]{ Select2.JOIN_INNER, Select2.JOIN_INNER, Select2.JOIN_INNER },
								new Expression[]{ 
									new Field( "marcacoes_trabalhador.trabalhador_id" ).isEqual( new Field( "trabalhadores.id" ) ),
									new Field( "trabalhadores.estabelecimento_id" ).isEqual( new Field( "estabelecimentos.id" ) ),
									new Field( "estabelecimentos.empresa_id" ).isEqual( new Field( "empresas.id" ) ) },
								new String[]{ "marcacoes_trabalhador.id", "trabalhadores.nome", "trabalhadores.nome_plain", 
												"empresas.designacao_social", "marcacoes_trabalhador.tipo", "prestador_id" },
								new Field( "marcacoes_trabalhador.data" ).isEqual( data ).and(
									new Field( "marcacoes_trabalhador.estado" ).isEqual( 
												new Integer( Marcacao.ESTADO_POR_REALIZAR ) ) ).and( 
								new Field( "marcacoes_trabalhador.tipo" ).isEqual( new Integer( Marcacao.TIPO_MARCACAO_TRABALHADOR_EXAMES ) ) ),
								null,
								null,
								null,
								null );
		Virtual2DArray array = executer.executeQuery( select );
		return array.getObjects();
	}
	
	public Integer getTrabalhadorIDByMarcacaoID( Integer marcacaoID )
		throws Exception
	{
		Select select =
			new Select( new String[]{ "marcacoes_trabalhador" },
						new String[]{ "trabalhador_id" },
						new Field( "id" ).isEqual( marcacaoID ) );
		Virtual2DArray array  = executer.executeQuery( select );
		return ( Integer ) array.get( 0, 0 );
	}
}
