/*
 * ProcessoDataProvider.java
 *
 * Created on March 20, 2007, 5:14 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package siprp.medicina.processo;

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.DBManager;
import com.evolute.utils.db.Executer;
import com.evolute.utils.jdo.JDOProvider;
import com.evolute.utils.sql.Assignment;
import com.evolute.utils.sql.Expression;
import com.evolute.utils.sql.Field;
import com.evolute.utils.sql.Insert;
import com.evolute.utils.sql.Select;
import com.evolute.utils.sql.Select2;
import com.evolute.utils.sql.Update;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Vector;
import siprp.medicina.MedicinaConstants;
import siprp.medicina.processo.data.TrabalhadoresConsultasData;
import siprp.medicina.processo.data.TrabalhadoresConsultasDatasData;
import siprp.medicina.processo.data.TrabalhadoresEcdsData;
import siprp.medicina.processo.data.TrabalhadoresEcdsDatasData;
import siprp.medicina.processo.data.TrabalhadoresProcessoData;

/**
 *
 * @author fpalma
 */
public class ProcessoDataProvider
	implements MedicinaConstants, ProcessoConstants
{
	private static final DateFormat D_F = DateFormat.getDateInstance( DateFormat.SHORT, new Locale( "pt", "PT" ) );
	
	public static final HashMap<String,String> ESTADO_PROCESSO_BY_CODE = 
			new HashMap<String,String>();
	
	static
	{
		ESTADO_PROCESSO_BY_CODE.put( PROCESSO_ABERTO_CODE, PROCESSO_ABERTO_DESCRIPTION );
		ESTADO_PROCESSO_BY_CODE.put( PROCESSO_FECHADO_CODE, PROCESSO_FECHADO_DESCRIPTION );
		ESTADO_PROCESSO_BY_CODE.put( PROCESSO_CANCELADO_CODE, PROCESSO_CANCELADO_DESCRIPTION );
	}
	
	private static final Object LOCK = new Object();
	private static ProcessoDataProvider instance = null;
	private Executer EXECUTER;
	private JDOProvider JDO;
	
	/** Creates a new instance of ProcessoDataProvider */
	public ProcessoDataProvider()
		throws Exception
	{
		DBManager dbm = ( DBManager ) Singleton.getInstance( Singleton.DEFAULT_DBMANAGER );
		EXECUTER = dbm.getSharedExecuter( this );
		JDO = ( JDOProvider ) Singleton.getInstance( Singleton.DEFAULT_JDO_PROVIDER );
	}
	
	public static ProcessoDataProvider getProvider()
		throws Exception
	{
		synchronized( LOCK )
		{
			if( instance == null )
			{
				instance = new ProcessoDataProvider();
			}
		}
		return instance;
	}
	
	public Integer[] getIDsProcessosByTrabalhador( Integer trabalhadorID )
		throws Exception
	{
		Select select =
				new Select2( new String[]{ "trabalhadores_processo" },
								new Integer[ 0 ],
								new Expression[ 0 ],
								new String[]{ "id", "data_inicio" },
								new Field( "trabalhadores_processo.trabalhador_id" ).isEqual( trabalhadorID ),
								new String[]{ "data_inicio DESC" },
								null,
								null,
								null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		Integer ids[] = new Integer[ array.columnLength() ];
		for( int n = 0; n < ids.length; n++ )
		{
			ids[ n ] = ( Integer ) array.get( n, 0 );
		}
		return ids;
	}
	
	public TrabalhadoresProcessoData getProcessoByID( Integer id )
		throws Exception
	{
		return ( TrabalhadoresProcessoData ) JDO.load( TrabalhadoresProcessoData.class, id );
	}
	
	public void saveProcesso( TrabalhadoresProcessoData processo )
		throws Exception
	{
		processo.save();
	}
	
	public String getDescricaoEstadoProcessoByCodigo( String codigo )
	{
		return ESTADO_PROCESSO_BY_CODE.get( codigo );
	}
	
	public Object[][] getElementosProcesso( Integer processoID )
		throws Exception
	{
		Vector<Object[]> elementosVector = new Vector<Object[]>();
		
		Select select =
			new Select2( new String[]{ "trabalhadores_ecds" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id", "data", "estado", "" + TIPO_ECDS },
							new Field( "processo_id" ).isEqual( processoID ),
							new String[]{ "data", "id" },
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		elementosVector.addAll( Arrays.asList( array.getObjects() ) );
		
		select =
			new Select2( new String[]{ "trabalhadores_consultas" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id", "data", "estado", "" + TIPO_CONSULTA },
							new Field( "processo_id" ).isEqual( processoID ),
							new String[]{ "data", "id" },
							null,
							null,
							null );
		array = EXECUTER.executeQuery( select );
		elementosVector.addAll( Arrays.asList( array.getObjects() ) );

		select =
			new Select2( new String[]{ "trabalhadores_fichas_aptidao", "exames" },
							new Integer[]{ Select2.JOIN_INNER },
							new Expression[]{ new Field( "trabalhadores_fichas_aptidao.exame_id" ).isEqual( new Field( "exames.id" ) ) },
							new String[]{ "exames.id", "exames.data", "resultado", "" + TIPO_FICHA_APTIDAO },
							new Field( "trabalhadores_fichas_aptidao.processo_id" ).isEqual( processoID ).and(
							new Field( "exames.inactivo" ).isDifferent( "y" ) ),
							new String[]{ "exames.data", "exames.id" },
							null,
							null,
							null );
		array = EXECUTER.executeQuery( select );
		elementosVector.addAll( Arrays.asList( array.getObjects() ) );
		
		Object elementos[][] = elementosVector.toArray( new Object[ elementosVector.size() ][] );
		Arrays.sort( elementos, new Comparator(){
			public int compare( Object o1, Object o2 )
			{
				return ( (Date)( ( Object[] ) o1 )[ 1 ] ).compareTo( ( (Date)( ( Object[] ) o2 )[ 1 ] ) );
			}
		} );
		return elementos;
	}
	
	public Object[][] getDatasConsulta( Integer consultaID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_consultas_datas" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id", "data", "prestador_id", "estado" },
							new Field( "trabalhadores_consultas_id" ).isEqual( consultaID ),
							new String[]{ "data DESC" },
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		return array.getObjects();
	}
	
	public Object[][] getDatasECDs( Integer consultaID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_ecds_datas" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id", "data", "estado" },
							new Field( "consulta_id" ).isEqual( consultaID ),
							new String[]{ "data DESC" },
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		return array.getObjects();
	}
	
	public IDObject getObservacoesConsultaData( Integer consultaDataID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_consultas_datas_observacoes" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id", "observacao" },
							new Field( "trabalhadores_consultas_datas_id" ).isEqual( consultaDataID ),
							null,
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		if( array.columnLength() == 0 || array.get( 0, 0 ) == null )
		{                                                                                
			return null;
		}
		else
		{
			return new MappableObject( ( Integer ) array.get( 0, 0 ), ( String ) array.get( 0, 1 ) );
		}
	}
	
	public void saveObservacoesConsultaData( Integer consultaDataID, String observacao )
		throws Exception
	{
		IDObject observacaoAntiga = getObservacoesConsultaData( consultaDataID );
		if( observacaoAntiga != null )
		{
			Update update = 
					new Update( "trabalhadores_consultas_datas_observacoes",
								new Assignment[]{
									new Assignment( "observacao", observacao ) },
								new Field( "id" ).isEqual( observacaoAntiga.getID() ) );
			EXECUTER.executeQuery( update );
		}
		else
		{
			Insert insert = 
					new Insert( "trabalhadores_consultas_datas_observacoes",
								new Assignment[]{
									new Assignment( "observacao", observacao ),
									new Assignment( "trabalhadores_consultas_datas_id", consultaDataID ) } );
			EXECUTER.executeQuery( insert );
		}
	}
		
	public IDObject[] getEmailConsultaData( Integer consultaDataID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_consultas_datas_emails" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id", "data", "subject" },
							new Field( "trabalhadores_consultas_datas_id" ).isEqual( consultaDataID ),
							new String[]{ "data DESC" },
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		IDObject mails[] = new IDObject[ array.columnLength() ];
		for( int n = 0; n < mails.length; n++ )
		{
			Date data = ( Date ) array.get( n, 1 );
			String desc = D_F.format( data ) + " : " + array.get( n, 2 );
			mails[ n ] = new MappableObject( ( Integer ) array.get( n, 0 ), desc );
		}
		return mails;
	}
	
	public void saveEmailConsultaData( Integer consultaDataID, String destination,
										String subject, String body )
		throws Exception
	{
		Insert insert = 
				new Insert( "trabalhadores_consultas_datas_emails",
							new Assignment[]{
								new Assignment( "destination", destination ),
								new Assignment( "subject", subject ),
								new Assignment( "body", body ),
								new Assignment( "data", new Date() ),
								new Assignment( "trabalhadores_consultas_datas_id", consultaDataID ) } );
		EXECUTER.executeQuery( insert );
	}
	
	public Integer getLastConsultaDataIDForConsulta( Integer consultaID )
		throws Exception
	{
		Select select = 
				new Select2( new String[]{ "trabalhadores_consultas_datas" },
								new Integer[]{},
								new Expression[]{},
								new String[]{ "MAX( id )" },
								new Field( "trabalhadores_consultas_id" ).isEqual( consultaID ),
								null,
								null,
								null,
								null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		if( array.columnLength() == 0 || array.get( 0, 0 ) == null )
		{
			return null;
		}
		else
		{
			return ( Integer ) array.get( 0, 0 );
		}
	}
	
	public IDObject getObservacoesECDsData( Integer ecdsDataID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_consultas_datas_observacoes" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id", "observacao" },
							new Field( "trabalhadores_ecds_datas_id" ).isEqual( ecdsDataID ),
							null,
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		if( array.columnLength() == 0 || array.get( 0, 0 ) == null )
		{
			return null;
		}
		else
		{
			return new MappableObject( ( Integer ) array.get( 0, 0 ), ( String ) array.get( 0, 1 ) );
		}
	}
	
	public void saveObservacoesECDsData( Integer ecdsDataID, String observacao )
		throws Exception
	{
		IDObject observacaoAntiga = getObservacoesECDsData( ecdsDataID );
		if( observacaoAntiga != null )
		{
			Update update = 
					new Update( "trabalhadores_ecds_datas_observacoes",
								new Assignment[]{
									new Assignment( "observacao", observacao ) },
								new Field( "id" ).isEqual( observacaoAntiga.getID() ) );
			EXECUTER.executeQuery( update );
		}
		else
		{
			Insert insert = 
					new Insert( "trabalhadores_ecds_datas_observacoes",
								new Assignment[]{
									new Assignment( "observacao", observacao ),
									new Assignment( "trabalhadores_ecds_datas_id", ecdsDataID ) } );
			EXECUTER.executeQuery( insert );
		}
	}
	
	public Integer getLastECDsDataIDForECDs( Integer ecdsID )
		throws Exception
	{
		Select select = 
				new Select2( new String[]{ "trabalhadores_ecds_datas" },
								new Integer[]{},
								new Expression[]{},
								new String[]{ "MAX( id )" },
								new Field( "trabalhadores_ecds_id" ).isEqual( ecdsID ),
								null,
								null,
								null,
								null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		if( array.columnLength() == 0 || array.get( 0, 0 ) == null )
		{
			return null;
		}
		else
		{
			return ( Integer ) array.get( 0, 0 );
		}
	}
	
	public boolean getProcessoTemConsultasPorRealizar( Integer processoID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_consultas" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id", "estado" },
							new Field( "processo_id" ).isEqual( processoID ),
							new String[]{ "estado" },
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		return ( array.columnLength() > 0 ) && (  new Integer( ESTADO_POR_REALIZAR ).equals( array.get( 0, 1 ) ) );
	}
	
	public boolean getProcessoTemECDsPorRealizar( Integer processoID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_ecds" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id", "estado" },
							new Field( "processo_id" ).isEqual( processoID ),
							new String[]{ "estado" },
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		return ( array.columnLength() > 0 ) && (  new Integer( ESTADO_POR_REALIZAR ).equals( array.get( 0, 1 ) ) );
	}
	
	public Integer[] getConsultaIDsForProcesso( Integer processoID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_consultas" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id" },
							new Field( "processo_id" ).isEqual( processoID ),
							null,
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		Integer ids[] = new Integer[ array.columnLength() ];
		for( int n = 0; n < ids.length; n++ )
		{
			ids[ n ] = ( Integer ) array.get( n, 0 );
		}
		return ids;
	}
	
	public Integer[] getECDsIDsForProcesso( Integer processoID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_ecds" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id" },
							new Field( "processo_id" ).isEqual( processoID ),
							null,
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		Integer ids[] = new Integer[ array.columnLength() ];
		for( int n = 0; n < ids.length; n++ )
		{
			ids[ n ] = ( Integer ) array.get( n, 0 );
		}
		return ids;
	}
	
	public Integer getConsultaEmAbertoForProcesso( Integer processoID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_consultas" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id" },
							new Field( "processo_id" ).isEqual( processoID ).and( 
								new Field( "estado" ).isDifferent( new Integer( ESTADO_REALIZADO ) ) ),
							null,
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		if( array.columnLength() == 0 )
		{
			return null;
		}
		else
		{
			return ( Integer ) array.get( 0, 0 );
		}
	}
	
	public Integer getECDsEmAbertoForProcesso( Integer processoID )
		throws Exception
	{
		Select select = 
			new Select2( new String[]{ "trabalhadores_ecds" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id" },
							new Field( "processo_id" ).isEqual( processoID ).and( 
								new Field( "estado" ).isDifferent( new Integer( ESTADO_POR_REALIZAR ) ) ),
							null,
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		if( array.columnLength() == 0 )
		{
			return null;
		}
		else
		{
			return ( Integer ) array.get( 0, 0 );
		}
	}
	
	public TrabalhadoresConsultasData getConsultaByID( Integer id )
		throws Exception
	{
		return ( TrabalhadoresConsultasData ) JDO.load( TrabalhadoresConsultasData.class, id );
	}
	
	public void saveConsulta( TrabalhadoresConsultasData consulta )
		throws Exception
	{
		consulta.save();
	}
	
	public TrabalhadoresConsultasDatasData getConsultaDataByID( Integer id )
		throws Exception
	{
		return ( TrabalhadoresConsultasDatasData ) JDO.load( TrabalhadoresConsultasDatasData.class, id );
	}
	
	public void saveConsultaData( TrabalhadoresConsultasDatasData consultaData )
		throws Exception
	{
		consultaData.save();
	}
	
	public TrabalhadoresEcdsData getEcdsByID( Integer id )
		throws Exception
	{
		return ( TrabalhadoresEcdsData ) JDO.load( TrabalhadoresEcdsData.class, id );
	}
	
	public void saveEcds( TrabalhadoresEcdsData ecds )
		throws Exception
	{
		ecds.save();
	}
	
	public TrabalhadoresEcdsDatasData getEcdsDataByID( Integer id )
		throws Exception
	{
		return ( TrabalhadoresEcdsDatasData ) JDO.load( TrabalhadoresEcdsDatasData.class, id );
	}
	
	public void saveEcdsData( TrabalhadoresEcdsDatasData EcdsData )
		throws Exception
	{
		EcdsData.save();
	}
	
	public boolean verificarDataValidaForConsulta( Integer consultaID, Date data )
		throws Exception
	{
		Select select =
			new Select2( new String[]{ "trabalhadores_consultas_datas" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id" },
							new Field( "trabalhadores_consultas_id" ).isEqual( consultaID ).and( 
								new Field( "estado" ).isDifferent( new Integer( ESTADO_POR_REALIZAR ) ) ).and(
								new Field( "data" ).isGreater( data ) ),
							null,
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		return array.columnLength() == 0;
	}
	
	public boolean verificarDataValidaForECDs( Integer ecdsID, Date data )
		throws Exception
	{
		Select select =
			new Select2( new String[]{ "trabalhadores_ecds_datas" },
							new Integer[]{},
							new Expression[]{},
							new String[]{ "id" },
							new Field( "trabalhadores_ecdss_id" ).isEqual( ecdsID ).and( 
								new Field( "estado" ).isDifferent( new Integer( ESTADO_POR_REALIZAR ) ) ).and(
								new Field( "data" ).isGreater( data ) ),
							null,
							null,
							null,
							null );
		Virtual2DArray array = EXECUTER.executeQuery( select );
		return array.columnLength() == 0;
	}
	
	public void saveLigacaoProcessoFichaAptidao( Integer processoID, Integer fichaID )
		throws Exception
	{
	}
}
