

package gov.va.med.cds.client.functional;


import gov.va.med.cds.client.ClinicalDataServiceInterface;
import gov.va.med.cds.client.webservice.ClinicalDataServiceSynchronousInterface;
import gov.va.med.cds.clinicaldata.vhim400.ClinicalDataResponseInterface;
import gov.va.med.cds.junit.runners.SuiteAwareSpringRunner;
import gov.va.med.cds.testharness.AbstractBaseTest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Node;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;

import java.util.List;

import javax.annotation.Resource;


@RunWith( SuiteAwareSpringRunner.class )
@ContextConfiguration( locations = { "classpath:gov/va/med/cds/config/appNamesContext.xml",
                "classpath:gov/va/med/cds/config/staticPropertiesContext.xml" } )
public abstract class AbstractFunctionalTest
    extends
        AbstractBaseTest
{
    protected ClinicalDataServiceSynchronousInterface clinicalDataService;

    @Resource
    protected String cdsAppName;

    @Resource
    protected String pathwaysAppName;


    /**
     * Nodes are detached from Read Result to make it match with ExpectedReadResult XML
     * 
     * @param readResultXML is the XML that is returned after a READ request
     * @return a trimmed READ XMl without resultantIdentifiers and requestedResolvedIdentifiers nodes
     */
    protected String detachNodesFromReadResult( String readResultXML )
    {
        Document document = null;
        String readResult = null;

        try
        {
            // remove elements from Expected Read Result XML that cannot be used for comparison
            document = DocumentHelper.parseText( readResultXML );

            if ( document.getRootElement().element( "requestId" ).asXML().contains( "requestId" ) )
            {
                document.getRootElement().element( "requestId" ).detach();
            }

            while ( document.getRootElement().element( "patient" ).asXML().contains( "requestedNationalId" ) )
            {
                document.getRootElement().element( "patient" ).element( "requestedNationalId" ).detach();
            }

            while ( document.getRootElement().element( "patient" ).asXML().contains( "resultantIdentifiers" ) )
            {
                document.getRootElement().element( "patient" ).element( "resultantIdentifiers" ).detach();
            }

            while ( document.getRootElement().element( "patient" ).asXML().contains( "requestedResolvedIdentifiers" ) )
            {
                document.getRootElement().element( "patient" ).element( "requestedResolvedIdentifiers" ).detach();
            }

            while ( document.getRootElement().element( "patient" ).asXML().contains( "requestedExcludedIdentifiers" ) )
            {
                document.getRootElement().element( "patient" ).element( "requestedExcludedIdentifiers" ).detach();
            }

            readResult = document.asXML();
        }
        catch ( DocumentException e )
        {
            e.printStackTrace();
        }
        return readResult;
    }


    /**
     * Nodes are detached from Read Result to make it match with ExpectedReadResult XML
     * 
     * @param readResultXML is the XML that is returned after a READ request
     * @return a trimmed READ XMl without resultantIdentifiers and requestedResolvedIdentifiers nodes
     */
    protected String detachNodesFromWriteRequest( String createXML )
    {
        Document document = null;
        String createResult = null;

        try
        {

            document = DocumentHelper.parseText( createXML );

            if ( document.getRootElement().element( "clientName" ).asXML().contains( "clientName" ) )
            {
                document.getRootElement().element( "clientName" ).detach();
            }

            if ( document.getRootElement().element( "clientRequestInitiationTime" ).asXML().contains( "clientRequestInitiationTime" ) )
            {
                document.getRootElement().element( "clientRequestInitiationTime" ).detach();
            }

            if ( document.getRootElement().element( "templateId" ).asXML().contains( "templateId" ) )
            {
                document.getRootElement().element( "templateId" ).detach();
            }

            Node node = document.selectSingleNode( "/ClinicalData/patient/requestedNationalId" );

            if ( null != node )
            {
                node.detach();
            }

            createResult = document.asXML();
        }
        catch ( DocumentException e )
        {
            e.printStackTrace();
        }
        return createResult;
    }


    /**
     * Nodes are detached from Read Result to make it match with ExpectedReadResult XML
     * 
     * @param readResultXML is the XML that is returned after a READ request
     * @return a trimmed READ XMl without resultantIdentifiers and requestedResolvedIdentifiers nodes
     */
    protected String detachNodesFromReadResult( String readResultXML, ClinicalDataResponseInterface clinicalDataResponse )
    {
        Document document = null;
        String readResult = null;
        Node node = null;
        List<Node> errorNodes = null;
        int size = 0;

        try
        {
            // remove elements from Expected Read Result XML that cannot be used for comparison
            document = DocumentHelper.parseText( readResultXML );

            if ( clinicalDataResponse.getRequestId( document ) != null )
            {
                clinicalDataResponse.getRequestId( document ).detach();
            }

            while ( clinicalDataResponse.getRequestedNationalId( document ) != null )
            {
                clinicalDataResponse.getRequestedNationalId( document ).detach();
            }

            while ( clinicalDataResponse.getResultantIdentifiers( document ) != null )
            {
                clinicalDataResponse.getResultantIdentifiers( document ).detach();
            }

            while ( clinicalDataResponse.getRequestedResolvedIdentifiers( document ) != null )
            {
                clinicalDataResponse.getRequestedResolvedIdentifiers( document ).detach();
            }

            while ( clinicalDataResponse.getRequestedExcludedIdentifiers( document ) != null )
            {
                clinicalDataResponse.getRequestedExcludedIdentifiers( document ).detach();
            }

            while ( clinicalDataResponse.getErrorSectionRoot( document ) != null )
            {
                node = clinicalDataResponse.getErrorSectionRoot( document ).detach();
                errorNodes = document.selectNodes( "//errorSection" );
                size = errorNodes.size();
                if ( size == 0 )
                {
                    break;
                }
            }

            readResult = document.asXML();
        }
        catch ( DocumentException e )
        {
            e.printStackTrace();
        }
        return readResult;
    }


    /**
     * Nodes are detached from Read Result to make it match with ExpectedReadResult XML
     * 
     * @param readResultXML is the XML that is returned after a READ request
     * @return a trimmed READ XMl without resultantIdentifiers and requestedResolvedIdentifiers nodes
     */
    protected String detachNodesFromWriteResult( String createResultXML, ClinicalDataResponseInterface clinicalDataResponse )
    {
        Document document = null;
        String readResult = null;
        Node node = null;
        List<Node> errorNodes = null;
        int size = 0;

        try
        {
            // remove elements from Expected Read Result XML that cannot be used for comparison
            document = DocumentHelper.parseText( createResultXML );

            if ( clinicalDataResponse.getRequestId( document ) != null )
            {
                clinicalDataResponse.getRequestId( document ).detach();
            }

            while ( clinicalDataResponse.getRequestedNationalId( document ) != null )
            {
                clinicalDataResponse.getRequestedNationalId( document ).detach();
            }

            while ( clinicalDataResponse.getResultantIdentifiers( document ) != null )
            {
                clinicalDataResponse.getResultantIdentifiers( document ).detach();
            }

            while ( clinicalDataResponse.getRequestedResolvedIdentifiers( document ) != null )
            {
                clinicalDataResponse.getRequestedResolvedIdentifiers( document ).detach();
            }

            while ( clinicalDataResponse.getRequestedExcludedIdentifiers( document ) != null )
            {
                clinicalDataResponse.getRequestedExcludedIdentifiers( document ).detach();
            }

            while ( clinicalDataResponse.getErrorSectionRoot( document ) != null )
            {
                node = clinicalDataResponse.getErrorSectionRoot( document ).detach();
                errorNodes = document.selectNodes( "//errorSection" );
                size = errorNodes.size();
                if ( size == 0 )
                {
                    break;
                }
            }

            readResult = document.asXML();
        }
        catch ( DocumentException e )
        {
            e.printStackTrace();
        }
        return readResult;
    }


    /**
     * Nodes are detached from Exams Read Result to make it match with ExpectedReadResult XML
     * 
     * @param readResultXML is the XML that is returned after a READ request
     * @return a trimmed READ XML
     */
    @SuppressWarnings( "unchecked" )
    protected String detachNodesFromExamsReadResult( String readResultXML )
    {
        Document document = null;
        String readResult = null;

        try
        {
            // remove elements from Expected Read Result XML that cannot be used for comparison
            document = DocumentHelper.parseText( readResultXML );
            List<Node> nodes = document.selectNodes( "/RequestsAndExamsData/patients/patient/examRequests/examRequest/elapsedTime" );
            for ( Node node : nodes )
            {
                node.detach();
            }

            readResult = document.asXML();
        }
        catch ( DocumentException e )
        {
            e.printStackTrace();
        }
        return readResult;
    }


    /**
     * Nodes are detached from VistaWeb Pharmacy Read Result to make it match with ExpectedReadResult XML
     * 
     * @param readResultXML is the XML that is returned after a READ request
     * @return a trimmed READ XML
     */
    @SuppressWarnings( "unchecked" )
    protected String detachNodesFromVWPharmacyReadResult( String readResultXML )
    {
        Document document = null;
        String readResult = null;

        try
        {
            // remove elements from Expected Read Result XML that cannot be used for comparison
            document = DocumentHelper.parseText( readResultXML );

            Node node = document.selectSingleNode( "/ClinicalData/patient/outpatientMedicationPromises/pharmacyRequest/statusModifier/code" );
            if ( null != node )
            {
                node.detach();
            }

            node = document.selectSingleNode( "/ClinicalData/patient/outpatientMedicationPromises/originalDispense/dispensedDrug/ndc/displayText" );
            if ( null != node )
            {
                node.detach();
            }

            List<Node> list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/refillDispense/quantityDispensed" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/refillDispense/currentProvider" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/refillDispense/division" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/refillDispense/dispensedDrug" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/partialDispense/quantityDispensed" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/partialDispense/currentProvider" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/partialDispense/division" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/partialDispense/dispensedDrug" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            readResult = document.asXML();
        }
        catch ( DocumentException e )
        {
            e.printStackTrace();
        }
        return readResult;
    }


    /**
     * Nodes are detached from VistaWeb Pharmacy Detailed Read Result to make it match with ExpectedReadResult XML
     * 
     * @param readResultXML is the XML that is returned after a READ request
     * @return a trimmed READ XML
     */
    @SuppressWarnings( "unchecked" )
    protected String detachNodesFromVWPharmacyDetailedReadResult( String readResultXML )
    {
        Document document = null;
        String readResult = null;

        try
        {
            // remove elements from Expected Read Result XML that cannot be used for comparison
            document = DocumentHelper.parseText( readResultXML );

            List<Node> list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/originalDispense/dispensedDrug" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/refillDispense/quantityDispensed" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/refillDispense/daysSupply" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/refillDispense/division" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/refillDispense/dispensedDrug/drugUnitPrice" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            list = document.selectNodes( "/ClinicalData/patient/outpatientMedicationPromises/refillDispense/dispensedDrug/ndc" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            readResult = document.asXML();
        }
        catch ( DocumentException e )
        {
            e.printStackTrace();
        }
        return readResult;
    }


    @SuppressWarnings( "unchecked" )
    protected String detachNodesFromHealthAdapterRead1Result( String readResultXML, String domainRecordXPath )
    {
        Document document = null;
        String readResult = null;

        try
        {
            // remove elements from Expected Read Result XML that cannot be used for comparison
            document = DocumentHelper.parseText( readResultXML );

            Node node = document.selectSingleNode( "/ClinicalData/requestId" );
            if ( null != node )
            {
                node.detach();
            }

            List<Node> list = document.selectNodes( "/ClinicalData/patients/patient/resultantIdentifiers" );
            for ( Node detachNode : list )
            {
                detachNode.detach();
            }

            node = document.selectSingleNode( "/ClinicalData/patients/patient/requestedEdiPi" );
            if ( null != node )
            {
                node.detach();
            }

            node = document.selectSingleNode( domainRecordXPath + "/recordVersion" );
            if ( null != node )
            {
                node.detach();
            }

            node = document.selectSingleNode( domainRecordXPath + "/recordUpdateTime" );
            if ( null != node )
            {
                node.detach();
            }

            readResult = document.asXML();
        }
        catch ( DocumentException e )
        {
            e.printStackTrace();
        }
        return readResult;
    }


    @Resource
    public void setClinicalDataService( ClinicalDataServiceSynchronousInterface clinicalDataSource )
    {
        this.clinicalDataService = clinicalDataSource;
    }


    protected ClinicalDataServiceSynchronousInterface getClinicalDataService( )
    {
        return clinicalDataService;
    }
}
