/**
 * 
 */


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


import static org.junit.Assert.assertNotNull;
import gov.va.med.cds.integration.AbstractEndToEndReadTiuTest;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareSpringRunner;
import gov.va.med.cds.testharness.vhim400.TemplateIdHelper;
import gov.va.med.cds.uniqueidentifier.UniqueIdentifier;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.junit.Assert;
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/nonWeblogicFailingVistADataSourcesContext.xml" } )
public class EndToEndPartialReadTiuTest
    extends
        AbstractEndToEndReadTiuTest
{
    private static String PATIENTIDENTITY_1 = "1";
    private static String PATIENTIDENTITY_2 = "1";
    private static String ASSIGNINGFACILITY_SUCCESS_1 = "580";
    private static String ASSIGNINGFACILITY_SUCCESS_2 = "578";
    private static String ASSIGNINGFACILITY_FAILURE_1 = "503";
    private static String ASSIGNINGFACILITY_FAILURE_2 = "504";
    private static String DOCUMENT_CLASS_VALUE = "3";
    private static String[] DOCUMENT_TYPE_VALUES = {};
    private static String XPATH_ERRORSECTION_WARNINGS = "/clinicaldata:ClinicalData/errorSection/warnings";
    private static String XPATH_ERRORSECTION_WARNING = "/clinicaldata:ClinicalData/errorSection/warnings/warning";
    private static String XPATH_ERRORSECTION_FATALERROR = "/clinicaldata:ClinicalData/errorSection/fatalErrors/fatalError";
    private static String XPATH_ERRORSECTION_FATALERRORCODE = "/clinicaldata:ClinicalData/errorSection/fatalErrors/fatalError/errorCode";
    private static String XPATH_ERRORSECTION_WARNINGERRORCODE = "/clinicaldata:ClinicalData/errorSection/warnings/warning/errorCode";

    private static final String READ_REQUEST_ALL_DATASOURCES_FAILED = "READ_REQUEST_ALL_DATASOURCES_FAILED";
    private static final String READ_REQUEST_DATA_SOURCE_FAILURE = "READ_REQUEST_DATA_SOURCE_FAILURE";


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = { "checkintest" } )
    public void testTiuPartialListRead_TwoFailures( )
        throws Exception
    {
        // set to validate against schema
        requestProcessor.setValidateReadResponseXML( true );

        Document clinicalDataDocument = requestProcessor.readClinicalData( getTiuListReadTemplateID(), getFilterXmlForPartialReads_TwoFailures(),
                        getTiuListReadFilterID(), new UniqueIdentifier().toString() );
        assertNotNull( clinicalDataDocument );

        //make sure we were able to read data successfully
        List<Node> clinicalDocumentNodes = clinicalDataDocument.selectNodes( XPATH_DOMAINENTRYPOINT );
        Assert.assertTrue( clinicalDocumentNodes.size() > 0 );

        //make sure there is only one outer warnings node..This should be validated by template schema validation as well
        List<Node> warningsNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_WARNINGS );
        Assert.assertTrue( warningsNodes.size() == 1 );

        //make sure we reported two READ_REQUEST_DATA_SOURCE_FAILURE's successfully as a warning
        List<Node> warningNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_WARNING );
        Assert.assertTrue( warningNodes.size() == 2 );

        for ( Node warningNode : warningNodes )
        {
            Element warningElement = ( Element )warningNode;
            Element errorCodeElement = warningElement.element( "errorCode" );
            Assert.assertNotNull( errorCodeElement );
            Assert.assertTrue( errorCodeElement.getText().equals( READ_REQUEST_DATA_SOURCE_FAILURE ) );
        }
    }


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = { "checkintest" } )
    public void testTiuPartialListRead_SingleFailure( )
        throws Exception
    {
        // set to validate against schema
        requestProcessor.setValidateReadResponseXML( true );

        Document clinicalDataDocument = requestProcessor.readClinicalData( getTiuListReadTemplateID(), getFilterXmlForPartialReads_SingleFailure(),
                        getTiuListReadFilterID(), new UniqueIdentifier().toString() );
        assertNotNull( clinicalDataDocument );

        //make sure we were able to read data successfully
        List<Node> clinicalDocumentNodes = clinicalDataDocument.selectNodes( XPATH_DOMAINENTRYPOINT );
        Assert.assertTrue( clinicalDocumentNodes.size() > 0 );

        //make sure we reported one  READ_REQUEST_DATA_SOURCE_FAILURE successfully as a warning
        List<Node> warningNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_WARNING );
        Assert.assertTrue( warningNodes.size() == 1 );

        Node errorCodeNode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_WARNINGERRORCODE );
        Assert.assertTrue( errorCodeNode.getText().contains( READ_REQUEST_DATA_SOURCE_FAILURE ) );
    }


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = { "checkintest" } )
    public void testCompleteFailureListRead_OneSite( )
        throws Exception
    {
        // set to validate against schema
        requestProcessor.setValidateReadResponseXML( true );

        Document clinicalDataDocument = requestProcessor.readClinicalData( getTiuListReadTemplateID(), getFilterXmlForCompleteFailure_OneSite(),
                        getTiuListReadFilterID(), new UniqueIdentifier().toString() );
        assertNotNull( clinicalDataDocument );

        //make sure no data was read from any site...
        List<Node> clinicalDocumentNodes = clinicalDataDocument.selectNodes( XPATH_DOMAINENTRYPOINT );
        Assert.assertTrue( clinicalDocumentNodes.size() == 0 );

        //make sure we reported a fatal error for READ_REQUEST_ALL_DATA_SOURCES_FAILED
        List<Node> warningNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_FATALERROR );
        Assert.assertTrue( warningNodes.size() == 1 );
        Node errorCodeNode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_FATALERRORCODE );
        Assert.assertTrue( errorCodeNode.getText().contains( READ_REQUEST_ALL_DATASOURCES_FAILED ) );
    }


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = { "checkintest" } )
    public void testCompleteFailureListRead_TwoSites( )
        throws Exception
    {

        // set to validate against schema
        requestProcessor.setValidateReadResponseXML( true );
        Document clinicalDataDocument = requestProcessor.readClinicalData( getTiuListReadTemplateID(), getFilterXmlForCompleteFailure_TwoSites(),
                        getTiuListReadFilterID(), new UniqueIdentifier().toString() );
        assertNotNull( clinicalDataDocument );

        //make sure no data was read from any site...
        List<Node> clinicalDocumentNodes = clinicalDataDocument.selectNodes( XPATH_DOMAINENTRYPOINT );
        Assert.assertTrue( clinicalDocumentNodes.size() == 0 );

        //make sure we reported a fatal error for READ_REQUEST_ALL_DATA_SOURCES_FAILED        
        List<Node> warningNodes = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_FATALERROR );
        Assert.assertTrue( warningNodes.size() == 1 );
        Node errorCodeNode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_FATALERRORCODE );
        Assert.assertTrue( errorCodeNode.getText().equals( READ_REQUEST_ALL_DATASOURCES_FAILED ) );
    }


    @SuppressWarnings( "unchecked" )
    @Test
    @Suite( groups = { "checkintest" } )
    public void testTiuDetailReadFailure( )
        throws Exception
    {
        // set to validate against schema
        requestProcessor.setValidateReadResponseXML( true );
        Document clinicalDataDocument = requestProcessor.readClinicalData( getTiuDetailReadTemplateID(), getFilterXmlForTiuDetailReadFailure(),
                        getTiuDetailReadFilterID(), new UniqueIdentifier().toString() );
        assertNotNull( clinicalDataDocument );

        //make sure no data was read from any site...
        List<Node> clinicalDocumentNodes = clinicalDataDocument.selectNodes( XPATH_DOMAINENTRYPOINT );
        Assert.assertTrue( clinicalDocumentNodes.size() == 0 );

        //make sure we reported a fatal error for READ_REQUEST_ALL_DATA_SOURCES_FAILED        
        List<Node> fatalErrors = clinicalDataDocument.selectNodes( XPATH_ERRORSECTION_FATALERROR );
        Assert.assertTrue( fatalErrors.size() == 1 );
        Node errorCodeNode = clinicalDataDocument.selectSingleNode( XPATH_ERRORSECTION_FATALERRORCODE );
        assertNotNull( errorCodeNode );
        Assert.assertTrue( errorCodeNode.getText().equals( READ_REQUEST_ALL_DATASOURCES_FAILED ) );
    }


    protected String getFilterXmlForPartialReads_SingleFailure( )
    {
        Map<String, String> assigningFacilityAndPatientIdentityMap = new HashMap<String, String>();
        //success
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_SUCCESS_1, PATIENTIDENTITY_1 );
        //failure
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_FAILURE_1, PATIENTIDENTITY_2 );
        String filterXml = createTiuSinglePatientListDataFilter( assigningFacilityAndPatientIdentityMap, ASSIGNINGAUTHORITY,
                        TemplateIdHelper.TIU_SINGLE_PATIENT_LIST_DATA_FILTER, DOCUMENT_CLASS_VALUE, DOCUMENT_TYPE_VALUES, null, null, null, TIU_LIST_REQUIRED_XQUERY_CRITERIA );
        return filterXml;
    }


    protected String getFilterXmlForPartialReads_TwoFailures( )
    {
        Map<String, String> assigningFacilityAndPatientIdentityMap = new HashMap<String, String>();
        //success
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_SUCCESS_1, PATIENTIDENTITY_1 );
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_SUCCESS_2, PATIENTIDENTITY_1 );

        //failure
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_FAILURE_1, PATIENTIDENTITY_2 );
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_FAILURE_2, PATIENTIDENTITY_2 );
        String filterXml = createTiuSinglePatientListDataFilter( assigningFacilityAndPatientIdentityMap, ASSIGNINGAUTHORITY,
                        TemplateIdHelper.TIU_SINGLE_PATIENT_LIST_DATA_FILTER, DOCUMENT_CLASS_VALUE, DOCUMENT_TYPE_VALUES, null, null, null, TIU_LIST_REQUIRED_XQUERY_CRITERIA );
        return filterXml;
    }


    protected String getFilterXmlForCompleteFailure_OneSite( )
    {
        Map<String, String> assigningFacilityAndPatientIdentityMap = new HashMap<String, String>();
        //failure
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_FAILURE_1, PATIENTIDENTITY_1 );
        String filterXml = createTiuSinglePatientListDataFilter( assigningFacilityAndPatientIdentityMap, ASSIGNINGAUTHORITY,
                        TemplateIdHelper.TIU_SINGLE_PATIENT_LIST_DATA_FILTER, DOCUMENT_CLASS_VALUE, DOCUMENT_TYPE_VALUES, null, null, null, TIU_LIST_REQUIRED_XQUERY_CRITERIA );
        return filterXml;
    }


    protected String getFilterXmlForTiuDetailReadFailure( )
    {
        Map<String, String> assigningFacilityAndPatientIdentityMap = new HashMap<String, String>();
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_FAILURE_1, PATIENTIDENTITY_1 );
        String filterXml = createTiuSinglePatientListDataFilterIdentifiers( assigningFacilityAndPatientIdentityMap, ASSIGNINGAUTHORITY,
                        TemplateIdHelper.TIU_SINGLE_PATIENT_DETAIL_DATA_FILTER, RECORDIDENTIFIER1, NAMESPACEID1, null );
        return filterXml;
    }


    protected String getFilterXmlForCompleteFailure_TwoSites( )
    {
        Map<String, String> assigningFacilityAndPatientIdentityMap = new HashMap<String, String>();
        //success
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_FAILURE_1, PATIENTIDENTITY_1 );
        //failure
        assigningFacilityAndPatientIdentityMap.put( ASSIGNINGFACILITY_FAILURE_2, PATIENTIDENTITY_2 );
        String filterXml = createTiuSinglePatientListDataFilter( assigningFacilityAndPatientIdentityMap, ASSIGNINGAUTHORITY,
                        TemplateIdHelper.TIU_SINGLE_PATIENT_LIST_DATA_FILTER, DOCUMENT_CLASS_VALUE, DOCUMENT_TYPE_VALUES, null, null, null, TIU_LIST_REQUIRED_XQUERY_CRITERIA );
        return filterXml;
    }

}
