

package gov.va.med.cds.persistence.hibernate.common;


import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.filter.EntryFilterInterface;
import gov.va.med.cds.persistence.PersistenceException;
import gov.va.med.cds.persistence.ReadException;

import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate4.SessionFactoryUtils;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.sql.DataSource;


public class OutpatientPharmacyPreQueryExecution
    extends
        AbstractVistaPreQueryExecution
{
    protected static final String DATA_FORMAT_PATTERN = "yyyyMMdd";


    @Override
    public List getRowIds( Session session, EntryFilterInterface entryFilter, List patientIdentifiers )
        throws ReadException
    {
        List idList = null;
        if ( entryFilter.getDomainEntryPoint().equals( domainEntryPoint ) )
        {
            idList = new ArrayList();
            Connection conn = null;
            CallableStatement cstmt = null;
            ResultSet rs = null;
            DataSource dataSource = SessionFactoryUtils.getDataSource( session.getSessionFactory() );
            Query query = session.getNamedQuery( namedQuery );
            for ( Object pid : patientIdentifiers )
            {
                try
                {
                    conn = dataSource.getConnection();
                    cstmt = conn.prepareCall( query.getQueryString() );
                    cstmt.setString( 1, pid.toString() );
                    
                    rs = updateStatement( cstmt, entryFilter ).executeQuery();
                    if ( rs != null )
                    {
                        while ( rs.next() )
                        {
                            idList.add( rs.getString( resultColumnName ) );
                        }
                    }
                }
                catch ( Exception ex )
                {
                    String msg = ex.getMessage();
                    if ( ex.getCause() != null )
                    {
                        msg = String.format( "%s%s%s", ex.getMessage(), ": ", ex.getCause().getMessage() );
                    }

                    throw new PersistenceException( ErrorCodeEnum.READ_REQUEST_PRE_QUERY_FAILURE, pid.toString(), entryFilter.getDomainEntryPoint(),
                                    msg );
                }
                finally
                {
                    if ( rs != null )
                    {
                        try
                        {
                            rs.close();
                        }
                        catch ( Exception er )
                        {
                            er.printStackTrace();
                        }
                        finally
                        {
                            rs = null;
                        }
                    }
                    if ( cstmt != null )
                    {
                        try
                        {
                            cstmt.close();
                        }
                        catch ( SQLException ec )
                        {
                            ec.printStackTrace();
                        }
                        finally
                        {
                            cstmt = null;
                        }
                    }
                    if ( conn != null )
                    {
                        try
                        {
                            conn.close();
                        }
                        catch ( SQLException ep )
                        {
                            ep.printStackTrace();
                        }
                        finally
                        {
                            conn = null;
                        }
                    }
                }
            }
        }
        else
        {
            idList = patientIdentifiers;
        }

        return idList;
    }


    private CallableStatement updateStatement( CallableStatement cstmt, EntryFilterInterface entryFilter )
        throws SQLException
    {
        ParameterMetaData paramMetaData = cstmt.getParameterMetaData();

        // If parameter count is 3, we know that this stored proc is (pid, startdate, enddate)
        // Will need to be refactored if/when we call more Cache stored procs
        if ( paramMetaData.getParameterCount() == 3 )
        {
            // set StartDate <yyyymmdd>
            Calendar startDateCal = entryFilter.getStartDate();
            cstmt.setString( 2, "" );
            if ( startDateCal != null )
            {
                String startDate = new SimpleDateFormat( DATA_FORMAT_PATTERN ).format( startDateCal.getTime() );
                cstmt.setString( 2, startDate );
            }

            // set EndDate <yyyymmdd>
            Calendar endDateCal = entryFilter.getEndDate();
            if (endDateCal != null)
            cstmt.setString( 3, "" );
            {
                String endDate = new SimpleDateFormat( DATA_FORMAT_PATTERN ).format( endDateCal.getTime() );
                cstmt.setString( 3, endDate );
            }
        }

        return cstmt;
    }
}
