

package gov.va.med.cds.filter;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import gov.va.med.cds.common.person.correlation.PersonIdentifierInterface;
import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareSpringRunner;
import gov.va.med.cds.request.ValidationException;
import gov.va.med.cds.testharness.vhim400.TemplateIdHelper;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Calendar;
import java.util.List;
import java.util.Set;


@RunWith( SuiteAwareSpringRunner.class )
public class CdsFilterTest
    extends
        AbstractCdsFilterTest
{
    private static final String RDI_GOOD_FILTER = "RDIGoodFilter";
    private static final String CHDR_ALGY_FILTER = "chdrAlgyFilter";

    private CdsFilterInterface goodFilter;


    /**
     * Get the good filter created from the good xml property
     * 
     * @return a valid CdsFilter created from the good xml property
     * @throws Exception
     */
    private CdsFilterInterface getGoodCdsFilter( )
        throws Exception
    {
        if ( goodFilter == null )
        {
            goodFilter = getCdsFilterByName( GOOD_FILTER, "templateId", "requestId" );
        }

        return goodFilter;
    }


    /*
     * Test method to validate the creation of a CdsFilter object based on valid xml and testing a null CdsFilter object
     * returned from invalid xml
     */
    @Test( expected = ValidationException.class )
    @Suite( groups = { "checkintest" } )
    public void testGoodAndBadFilterXml( )
        throws Exception
    {
        CdsFilterInterface cdsFilter = getGoodCdsFilter();
        assertNotNull( cdsFilter );

        cdsFilter = getCdsFilterByName( BAD_FILTER, "templateId", "requestId" );
        fail( "The filter " + BAD_FILTER + " should have failed" );
    }


    /*
     *
     * Test method to validate the creation of a CdsFilter object based on valid xml with FilterId and testing a null
     * CdsFilter object returned from invalid xml
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGoodFilterXmlWithFilterId( )
        throws Exception
    {
        String filterId = TemplateIdHelper.RDI_IC_RX_CANNED_FILTER_ID;
        CdsFilterInterface cdsFilter = getCdsFilterByNameAndFilterId( RDI_GOOD_FILTER, filterId, "templateId", "requestId" );
        assertNotNull( cdsFilter );
    }


    /*
     * Test method for 'gov.va.med.cds.filter.CdsFilter.getFilterXml()'
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetFilterXml( )
        throws Exception
    {
        String xmlInput = filterProperties.getProperty( GOOD_FILTER );
        CdsFilterInterface cdsFilter = getCdsFilterByXml( xmlInput, "templateId", "requestId" );
        assertNotNull( cdsFilter );

        String xml = cdsFilter.getFilterXml();
        xml = xml.replace( "\n", "" );
        assertEquals( xmlInput, xml );
    }


    /*
     * Test method for 'gov.va.med.cds.filter.CdsFilter.testGetFilterId()'
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetFilterId( )
        throws Exception
    {
        CdsFilterInterface cdsFilter = getGoodCdsFilter();
        assertNotNull( cdsFilter );

        assertEquals( "testFilterId", cdsFilter.getFilterId() );
        assertEquals( "Test_Vhim_X_00", cdsFilter.getVhimVersion() );
        assertNotNull( cdsFilter.getEntryPointFilters() );
        assertNotNull( cdsFilter.getUniqueIdentifier() );
        assertNotNull( cdsFilter.getEntryFilter( "intoleranceQuery" ) );
    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetPatients( )
        throws Exception
    {
        CdsFilterInterface cdsFilter = getGoodCdsFilter();
        assertNotNull( cdsFilter );

        PersonIdentifierInterface personId = cdsFilter.getPersonIdentifiers().get( 0 );
        assertEquals( personId.getIdentity(), "testId-1" );
    }


    @SuppressWarnings( "unused" )
    @Test( expected = ValidationException.class )
    @Suite( groups = { "checkintest" } )
    public void testGetPatientNotFound( )
        throws Exception
    {
        CdsFilter cdsFilter = ( CdsFilter )getCdsFilterByName( "goodFilterUnresolvedNationalId_2", "templateId", "requestId" );
        assertNotNull( cdsFilter );

        PersonIdentifierInterface patient = cdsFilter.getPersonIdentifiers().get( 0 );
    }


    @Test( expected = ValidationException.class )
    @Suite( groups = { "checkintest" } )
    public void testEmptyResolvedIds( )
        throws Exception
    {
        CdsFilter cdsFilter = ( CdsFilter )getCdsFilterByName( "badFilterEmptyResolved_Ids", "templateId", "requestId" );
        assertNotNull( cdsFilter );

        @SuppressWarnings( "unused" )
        PersonIdentifierInterface patient = cdsFilter.getPersonIdentifiers().get( 0 );
    }


    @Test( expected = ValidationException.class )
    @Suite( groups = { "checkintest" } )
    public void testBadDateFormat( )
        throws Exception
    {
        CdsFilter cdsFilter = ( CdsFilter )getCdsFilterByName( "badFilterInvalidDateFormat", "templateId", "requestId" );
        assertNotNull( cdsFilter );

        @SuppressWarnings( "unused" )
        PersonIdentifierInterface patient = cdsFilter.getPersonIdentifiers().get( 0 );
    }


    /*
     * Test method for 'gov.va.med.cds.filter.CdsFilter.testGetStartDate()'
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetStartDate( )
        throws Exception
    {
        CdsFilterInterface cdsFilter = ( CdsFilterInterface )getGoodCdsFilter();
        assertNotNull( cdsFilter );

        EntryFilterInterface entryFilter = ( EntryFilterInterface )cdsFilter.getEntryPointFilters().get( 0 );
        assertNotNull( entryFilter );

        Calendar startDate = entryFilter.getStartDate();
        assertEquals( startDate.get( Calendar.YEAR ), 2005 );
        assertEquals( startDate.get( Calendar.MONTH ), 11 );
        assertEquals( startDate.get( Calendar.DATE ), 31 );
        //assertEquals( startDate.toString(), "2006-01-01" );
    }


    /*
     * Test method for 'gov.va.med.cds.filter.CdsFilter.testGetEndDate()'
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetEndDate( )
        throws Exception
    {
        CdsFilterInterface cdsFilter = ( CdsFilterInterface )getGoodCdsFilter();
        assertNotNull( cdsFilter );

        EntryFilterInterface entryFilter = ( EntryFilterInterface )cdsFilter.getEntryPointFilters().get( 0 );
        assertNotNull( entryFilter );

        Calendar endDate = entryFilter.getEndDate();
        assertEquals( endDate.get( Calendar.YEAR ), 2007 );
        assertEquals( endDate.get( Calendar.MONTH ), 0 );
        assertEquals( endDate.get( Calendar.DATE ), 1 );
        //assertEquals( endDate.toString(), "2006-12-31" );
    }


    /*
     * Test method for 'gov.va.med.cds.filter.CdsFilter.testGetRecords()'
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetRecords( )
        throws Exception
    {
        CdsFilterInterface cdsFilter = ( CdsFilterInterface )getGoodCdsFilter();
        assertNotNull( cdsFilter );

        EntryFilterInterface entryFilter = ( EntryFilterInterface )cdsFilter.getEntryPointFilters().get( 0 );
        assertNotNull( entryFilter );

        List<String> records = entryFilter.getRecordIdentifiers();
        String record1 = records.get( 0 );
        assertTrue( record1.startsWith( "100", 0 ) );
    }


    /*
     * Test method for 'gov.va.med.cds.filter.CdsFilter.testGetXpathQuery()'
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetXpathQuery( )
        throws Exception
    {
        CdsFilterInterface cdsFilter = ( CdsFilterInterface )getGoodCdsFilter();
        assertNotNull( cdsFilter );

        EntryFilterInterface entryFilter = ( EntryFilterInterface )cdsFilter.getEntryPointFilters().get( 0 );
        assertNotNull( entryFilter );

        String xpath = entryFilter.getXpathQuery();
        assertEquals( xpath, "TestXpath" );
        String entryPoint = entryFilter.getDomainEntryPoint();
        assertEquals( entryPoint, "IntoleranceCondition" );

        /*
         * NS: Expect xpath string to be in the std. xpath format
        List<Parameter> parameters = xpathQuery.getParameter();
        Parameter parameter = parameters.get( 1 );
        String parameterName = parameter.getName();
        assertEquals( parameterName, "parameter2" );
        String parameterValue = parameter.getValue();
        assertEquals( parameterValue, "TestValue2" );
        */
    }


    /*
     * Test method for 'gov.va.med.cds.filter.CdsFilter.testGetEntryPoint()'
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetEntryPoint( )
        throws Exception
    {
        CdsFilterInterface cdsFilter = getGoodCdsFilter();
        assertNotNull( cdsFilter );

        Set<String> entryPoints = cdsFilter.getDomainEntryPoints();
        assertEquals( entryPoints.size(), 1 );
        assertEquals( entryPoints.iterator().next(), "IntoleranceCondition" );
    }


    /*
     * Test method for 'gov.va.med.cds.filter.CdsFilter.testGetXpath()'
     */
    @Test
    @Suite( groups = { "checkintest" } )
    public void testGetXpath( )
        throws Exception
    {

        CdsFilterInterface cdsFilter = getGoodCdsFilter();
        assertNotNull( cdsFilter );
        String xpath = cdsFilter.getEntryPointFilters().get( 0 ).getXpathQuery();
        assertEquals( xpath, "TestXpath" );
    }


    @SuppressWarnings( "unused" )
    @Test( expected = ValidationException.class )
    @Suite( groups = { "checkintest" } )
    public void testInvalidFilter( )
        throws DocumentException
    {
        CdsFilterInterface cdsFilter = null;

        try
        {
            String xmlString = filterProperties.getProperty( BAD_FILTER );
            Document filterDocument = DocumentHelper.parseText( xmlString );
            cdsFilter = filterFactory.create( filterDocument, "templateId", "requestId" );
        }
        catch ( ValidationException e )
        {
            // TODO: Modify to use the refactored exception handler

            //            exceptionHandler.handleException( e, null, null, null, null );
            //
            //            assertEquals( exceptionHandler.getExceptionInfoList(null).size(), 1 );
            //            assertEquals( exceptionHandler.getExceptionInfoList(null).get( 0 ).getClass(), gov.va.med.cds.request.ValidationException.class );

            throw e;
        }
    }


    /*
     * Test method for 'gov.va.med.cds.filter.CdsFilter.testGetXpath()'
     */
    @Test
    @Suite( groups = { "checkintest" } )
    @SuppressWarnings( "unused" )
    public void testAccessorMethods( )
        throws Exception
    {

        CdsFilterInterface cdsFilter = getGoodCdsFilter();
        assertNotNull( cdsFilter );
        Element nationalId = cdsFilter.getNationalId();
        Element edipi = cdsFilter.getEdipi();
        List<Element> resolvedIdentifiers = cdsFilter.getResolvedIdentifiers();
        List<Element> excludedIdentifiers = cdsFilter.getExcludedIdentifiers();

    }


    @Test
    @Suite( groups = { "checkintest" } )
    public void testChdrAllergyFilter( )
        throws Exception
    {
        String xmlString = filterProperties.getProperty( CHDR_ALGY_FILTER );
        Document filterDocument = DocumentHelper.parseText( xmlString );
        filterFactory.create( filterDocument, "IntoleranceConditionRead40010", "54F16B9E-34CC-9ED5-4215-105D0CB8516A" );
    }
}
