

package gov.va.med.cds.integration.vhim400;


import static org.junit.Assert.assertTrue;
import gov.va.med.cds.integration.AbstractEndToEndTest;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareSpringRunner;
import gov.va.med.cds.request.RequestProcessorInterface;
import gov.va.med.cds.request.TemplateRequestProcessor;
import gov.va.med.cds.testharness.vhim400.TemplateIdHelper;
import gov.va.med.cds.testharness.vhim400.builders.FilterBuilder;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;


//@RunWith( SuiteAwareSpringRunner.class )
//@ContextConfiguration( locations = { "classpath:gov/va/med/cds/config/vistaPersistenceStoredProcedureQueryTimeoutContext.xml",
               // "classpath:gov/va/med/cds/config/nonWeblogicVistaDataSourceContext.xml", "classpath:gov/va/med/cds/config/transactionContext.xml" } )
public class VistAStoredProcedureQueryTimeoutTest
    extends
        AbstractEndToEndTest
{
    private static final String PATIENT_IDENTITY_VISTA_EXAM_REQUEST = "78";
    private static final String PATIENT_IDENTITY_VISTA_EXAM = "78";   
    private static final String ASSIGNING_FACILITY_VISTA_580 = "580";
    private static final String ASSIGNING_AUTHORITY_VISTA = "USVHA";
    private static final String CLIENT_NAME = "HMP";
    private static final String PATIENTIDENTITY_1 = "1";
    private static final String PATIENTIDENTITY_2 = "174";
    private static final String ASSIGNING_FACILITY_1 = "578";
    private static final String ASSIGNING_FACILITY_2 = "578";    
    private static final String XPATH_ERRORSECTION_ERROR_ERRORCODE = "//errorSection/errors/error/errorCode";
    private static final String XPATH_ERRORSECTION_FATAAL_ERROR_ERRORCODE = "//errorSection/fatalErrors/fatalError/errorCode";
    protected static final String XPATH_ERRORSECTION_FATALERRORS_FATALERROR_DISPLAY_MSG = "//errorSection/fatalErrors/fatalError/displayMessage";
    private static final String QUERY_TIMEOUT_MSG = "A query timeout occured during the read request";
    private static final String REQUEST_TIMEOUT_MSG = "Request timed out due to user timeout";
    protected static final String DATASOURCE_FAILURE_ERROR_CODE = "READ_REQUEST_ALL_DATASOURCES_FAILED";  

    @Resource
    private RequestProcessorInterface rpcRequestProcessor = null;
    protected TemplateRequestProcessor templateRequestProcessor;


    //@Before
    //@Suite( groups = { "checkintest" } )
    public void beforeVistAStoredProcedureQueryTimeoutTestClassSetUp( )
        throws Exception
    {
        templateRequestProcessor = ( TemplateRequestProcessor )getRpcRequestProcessor();
    }


    //@Test
    //@Suite( groups = { "timeouttest" } )
    public void testVistaStoredProcedureQueryTimeout( )
        throws Exception
    {
        String TIMOUT_SECONDS = "1";
        String clientRequestInitiationTime = "2011-06-06T12:01:01Z";
        String requestId = TemplateIdHelper.getUniqueIdentifier();

        // build resolved patients
        String[] vistaPatient580_1 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA_580, PATIENT_IDENTITY_VISTA_EXAM_REQUEST };
        String[] vistaPatient580_2 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_VISTA_580, PATIENT_IDENTITY_VISTA_EXAM };
        String[][] patientIdentifiers = { vistaPatient580_1, vistaPatient580_2 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        // build entry point 
        Map<String, String> entryPointFilterMapRequests = new HashMap<String, String>();
        entryPointFilterMapRequests.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "ExamRequest2507" );
        entryPointFilterMapRequests.put( FilterBuilder.QUERY_NAME_KEY, "ExamRequest2507-Standardized" );

        List<Map<String, String>> entryPointFilterMaps = new ArrayList<Map<String, String>>();
        entryPointFilterMaps.add( entryPointFilterMapRequests );

        // build filter
        Element filter = FilterBuilder.buildExamRequestsFilterElementWithResolvedIdentfiers(
                        TemplateIdHelper.REQUESTS_AND_EXAMS_SINGLE_PATIENT_FILTER, entryPointFilterMaps, resolvedPatients, null, null,
                        clientRequestInitiationTime, null );
        filter.element( "entryPointFilter" ).addElement( "queryTimeoutSeconds" ).addText( TIMOUT_SECONDS );
        String filterXml = filter.asXML();
        
        templateRequestProcessor.setValidateReadResponseXML( true );
        Document dataDocument = templateRequestProcessor.readClinicalData( TemplateIdHelper.REQUESTS_EXAMS_READ_TEMPLATE_ID_2, filterXml,
                        TemplateIdHelper.REQUESTS_AND_EXAMS_SINGLE_PATIENT_FILTER, requestId );
        List<Element> elementList = dataDocument.selectNodes( XPATH_ERRORSECTION_FATAAL_ERROR_ERRORCODE );

        assertTrue( elementList.get( 0 ).getText().equals( DATASOURCE_FAILURE_ERROR_CODE ) );
        elementList = dataDocument.selectNodes( XPATH_ERRORSECTION_FATALERRORS_FATALERROR_DISPLAY_MSG );
        assertTrue( elementList.get( 0 ).getText().contains( QUERY_TIMEOUT_MSG ) );

    }


    @SuppressWarnings( "unchecked" )
    //@Test
    //@Suite( groups = { "timeouttest" } )
    public void testVistaGenericStoredProcedureQueryTimeout( )
        throws Exception
    {
        String requestId = TemplateIdHelper.getUniqueIdentifier();

        // build resolved patients
        String[] vistaPatient247 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_1, PATIENTIDENTITY_1 };
        String[] vistaPatient248 = { ASSIGNING_AUTHORITY_VISTA, ASSIGNING_FACILITY_2, PATIENTIDENTITY_2 };
        String[][] patientIdentifiers = { vistaPatient247, vistaPatient248 };
        List<Map<String, String>> resolvedPatients = getResolvedPatients( patientIdentifiers );

        // build entry point 
        Map<String, String> entryPointFilterMap = new HashMap<String, String>();
        entryPointFilterMap.put( FilterBuilder.DOMAIN_ENTRYPOINT_KEY, "GenericObservation" );
        entryPointFilterMap.put( FilterBuilder.QUERY_NAME_KEY, "GenericObservation-Standardized" );

        // build other query parameters
        Map<String, String> otherQueryParametersMap = new HashMap<String, String>();
        otherQueryParametersMap.put( "domain", "PROBLEM" );

        // build filter
        String filterXml = createGenericObservationSinglePatientListDataFilter( entryPointFilterMap, resolvedPatients, "GenericObservation",
                        TemplateIdHelper.GENERIC_VISTA_LIST_DATA_FILTER, CLIENT_NAME, otherQueryParametersMap, null, null );

        Document dataDocument = templateRequestProcessor.readClinicalData( TemplateIdHelper.VISTA_GENERIC_OBSERVATION_TEMPLATE_ID, filterXml,
                        TemplateIdHelper.GENERIC_VISTA_LIST_DATA_FILTER, requestId );

        List<Element> elementList = dataDocument.selectNodes( XPATH_ERRORSECTION_FATAAL_ERROR_ERRORCODE );

        assertTrue( elementList.get( 0 ).getText().equals( DATASOURCE_FAILURE_ERROR_CODE ) );
        elementList = dataDocument.selectNodes( XPATH_ERRORSECTION_FATALERRORS_FATALERROR_DISPLAY_MSG );
        assertTrue( elementList.get( 0 ).getText().contains( REQUEST_TIMEOUT_MSG ) );

    }


    protected String createGenericObservationSinglePatientListDataFilter( Map<String, String> entryPointFilterMap,
                    List<Map<String, String>> resolvedPatients, String entryPoint, String filterId, String clientName,
                    Map<String, String> otherQueryParametersMap, String startDate, String endDate )
    {
        Document filterDocument = FilterBuilder.buildEmptyFilterDocument();
        Element element = filterDocument.getRootElement();
        element.add( FilterBuilder.createFilterId( "filterId", filterId ) );
        element.add( FilterBuilder.createClientName( "clientName", clientName ) );
        element.add( FilterBuilder.createClientRequestInitiationTime( "clientRequestInitiationTime",
                        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format( new Date() ) ) );
        element.add( FilterBuilder.createPatientWithResolvedIdentifiers( "patients", resolvedPatients ) );

        Element entryPointFilterElement = DocumentHelper.createElement( "entryPointFilter" );
        entryPointFilterElement.add( FilterBuilder.createDomainEntryPoint( "domainEntryPoint", entryPoint ) );

        if ( startDate != null && endDate != null )
        {
            entryPointFilterElement.add( FilterBuilder.createDateParameter( "startDate", startDate ) );
            entryPointFilterElement.add( FilterBuilder.createDateParameter( "endDate", endDate ) );
        }

        Iterator<String> keyIter = otherQueryParametersMap.keySet().iterator();
        Element otherQueryParametersElement = DocumentHelper.createElement( "otherQueryParameters" );
        while ( keyIter.hasNext() )
        {
            String key = keyIter.next();
            Element additionalParameterElement = DocumentHelper.createElement( "additionalParameter" );
            additionalParameterElement.addAttribute( "name", key );
            additionalParameterElement.addAttribute( "type", "text" );
            Element valueElement = DocumentHelper.createElement( "value" );
            valueElement.setText( otherQueryParametersMap.get( key ) );
            additionalParameterElement.add( valueElement );
            otherQueryParametersElement.add( additionalParameterElement );
        }

        entryPointFilterElement.add( otherQueryParametersElement );
        entryPointFilterElement.addAttribute( "queryName", "queryName" );

        element.add( entryPointFilterElement );
        element.addAttribute( "vhimVersion", "Vhim_4_00" );
        return element.asXML();
    }


    protected RequestProcessorInterface getRpcRequestProcessor( )
    {
        return rpcRequestProcessor;
    }
}
