

package gov.va.med.tfs.mapping;


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

import gov.va.med.cds.testharness.AbstractBaseTest;
import gov.va.med.tfs.client.webservice.DomainEntryPoint;
import gov.va.med.tfs.client.webservice.EntryFilter;
import gov.va.med.tfs.junit.runners.Suite;
import gov.va.med.tfs.mapping.tfstocds.FilterMetaDataMapper;
import gov.va.med.tfs.mapping.tfstocds.TemplateMetaDataMapper;

import org.junit.Test;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;


public class TemplateFilterMappingTest
    extends
        AbstractBaseTest
{

    private ResourceLoader resourceLoader = new DefaultResourceLoader();


    //@Test
    @Suite( groups = { "checkintest" } )
    public void mapTemplateMetaDataTest( )
        throws Exception
    {

        // Serialize from a file
        //    	gov.va.med.tfs.client.webservice.TemplateMetaData delegateTemplateMetaData = createTestTemplateMetaData();
        //        ObjectOutput out = new ObjectOutputStream(new FileOutputStream("TemplateMetaData.ser"));
        //        out.writeObject(delegateTemplateMetaData);
        //        out.close();

        Resource resource = resourceLoader.getResource( "classpath:gov/va/med/tfs/mapping/TemplateMetaData.ser" );

        gov.va.med.tfs.client.webservice.TemplateMetaData tfsTemplateMetaData = null;
        gov.va.med.cds.clinicaldata.TemplateMetaData cdsTemplateMetaData = null;

        try
        {
            // Deserialize from a file
            ObjectInputStream in = new ObjectInputStream( new FileInputStream( resource.getFile() ) );
            tfsTemplateMetaData = ( gov.va.med.tfs.client.webservice.TemplateMetaData )in.readObject();
            in.close();

            cdsTemplateMetaData = TemplateMetaDataMapper.getInstance().map( tfsTemplateMetaData );

        }
        catch ( Exception e )
        {
            System.err.println( "mapTemplateMetaDataTest Exception: " + e.getMessage() );
            assertTrue( false );
        }

        assertNotNull( tfsTemplateMetaData );
        assertNotNull( cdsTemplateMetaData );

        assertEquals( ( tfsTemplateMetaData.getDateActivated() != null ? tfsTemplateMetaData.getDateActivated().toGregorianCalendar().getTime()
                        : null ), cdsTemplateMetaData.getDateActivated() );
        assertEquals( ( tfsTemplateMetaData.getDateAdded() != null ? tfsTemplateMetaData.getDateAdded().toGregorianCalendar().getTime() : null ),
                        cdsTemplateMetaData.getDateAdded() );
        assertEquals( ( tfsTemplateMetaData.getDateDeactivated() != null ? tfsTemplateMetaData.getDateDeactivated().toGregorianCalendar().getTime()
                        : null ), cdsTemplateMetaData.getDateDeactivated() );
        assertEquals( ( tfsTemplateMetaData.getDateDeprecated() != null ? tfsTemplateMetaData.getDateDeprecated().toGregorianCalendar().getTime()
                        : null ), cdsTemplateMetaData.getDateDeprecated() );
        assertEquals( ( tfsTemplateMetaData.getDateUpdated() != null ? tfsTemplateMetaData.getDateUpdated().toGregorianCalendar().getTime() : null ),
                        cdsTemplateMetaData.getDateUpdated() );

        assertEquals( ( tfsTemplateMetaData.getDomainEntryPoints() != null ? tfsTemplateMetaData.getDomainEntryPoints().size() : 0 ),
                        cdsTemplateMetaData.getDomainEntryPoints().size() );
        Set<gov.va.med.cds.clinicaldata.DomainEntryPoint> clientDomainEntryPoints = cdsTemplateMetaData.getDomainEntryPoints();
        for ( gov.va.med.cds.clinicaldata.DomainEntryPoint clientDomainEntryPoint : clientDomainEntryPoints )
        {
            if ( clientDomainEntryPoint != null )
            {
                assertTrue( compareDomainEntryPoint( clientDomainEntryPoint, tfsTemplateMetaData.getDomainEntryPoints() ) );
            }
        }

        assertEquals( tfsTemplateMetaData.getOperation(), cdsTemplateMetaData.getOperation().name() );

        assertEquals( ( tfsTemplateMetaData.getReadCdsVdms() != null ? tfsTemplateMetaData.getReadCdsVdms().size() : 0 ), cdsTemplateMetaData
                        .getReadCdsVdms().size() );
        HashSet<String> clientReadCdsVdms = cdsTemplateMetaData.getReadCdsVdms();
        for ( String clientReadCdsVdm : clientReadCdsVdms )
        {
            if ( clientReadCdsVdm != null )
            {
                assertTrue( compareReadCdsVdm( clientReadCdsVdm, tfsTemplateMetaData.getReadCdsVdms() ) );
            }
        }

        assertEquals( tfsTemplateMetaData.getStatus(), cdsTemplateMetaData.getStatus() );

        assertEquals( tfsTemplateMetaData.getTemplateDescription(), cdsTemplateMetaData.getTemplateDescription() );

        assertEquals( tfsTemplateMetaData.getTemplateId(), cdsTemplateMetaData.getTemplateId() );

        assertArrayEquals( tfsTemplateMetaData.getTemplateJar(), cdsTemplateMetaData.getTemplateJar() );

        assertEquals( tfsTemplateMetaData.getTemplateName(), cdsTemplateMetaData.getTemplateName() );

        assertEquals( tfsTemplateMetaData.isTestOnly(), cdsTemplateMetaData.getTestOnly() );

        assertEquals( ( tfsTemplateMetaData.getVhimVersions() != null ? tfsTemplateMetaData.getVhimVersions().size() : 0 ),
                        ( cdsTemplateMetaData.getVhimVersions() != null ? cdsTemplateMetaData.getVhimVersions().length : 0 ) );
        String[] clientVhimVersions = cdsTemplateMetaData.getVhimVersions();
        for ( String clientVhimVersion : clientVhimVersions )
        {
            assertTrue( compareVhimVersion( clientVhimVersion, tfsTemplateMetaData.getVhimVersions() ) );
        }

        assertEquals( tfsTemplateMetaData.getWriteCdsVdm(), cdsTemplateMetaData.getWriteCdsVdm() );

        /*        TemplateMetaData templateMetaData = tfsClientService.getTemplateMetaData("LabRead40010");
                
                assertNotNull( templateMetaData );
                
                String[] vhimVersions = templateMetaData.getVhimVersions();
                
                for ( String vhimVersion : vhimVersions )
                {
                    System.out.println( "vhim version: " + vhimVersion );
                }*/

        System.out.println( "exit: -x-x- mapTemplateMetaDataTest" );
    }


    //@Test
    @Suite( groups = { "checkintest" } )
    public void mapFilterMetaDataTest( )
        throws Exception
    {

        // Serialize from a file
        //    	gov.va.med.tfs.client.webservice.FilterMetaData delegateFilterMetaData = createTestFilterMetaData();
        //        ObjectOutput out = new ObjectOutputStream(new FileOutputStream("FilterMetaData.ser"));
        //        out.writeObject(delegateFilterMetaData);
        //        out.close();

        Resource resource = resourceLoader.getResource( "classpath:gov/va/med/tfs/mapping/FilterMetaData.ser" );

        gov.va.med.tfs.client.webservice.FilterMetaData tfsFilterMetaData = null;
        gov.va.med.cds.clinicaldata.FilterMetaData cdsFilterMetaData = null;

        try
        {
            // Deserialize from a file
            ObjectInputStream in = new ObjectInputStream( new FileInputStream( resource.getFile() ) );
            tfsFilterMetaData = ( gov.va.med.tfs.client.webservice.FilterMetaData )in.readObject();
            in.close();

            cdsFilterMetaData = FilterMetaDataMapper.getInstance().map( tfsFilterMetaData );

        }
        catch ( Exception e )
        {
            System.err.println( "mapFilterMetaDataTest Exception: " + e.getMessage() );
            assertTrue( false );
        }

        assertNotNull( tfsFilterMetaData );
        assertNotNull( cdsFilterMetaData );

        assertEquals( tfsFilterMetaData.getFilterId(), cdsFilterMetaData.getFilterId() );

        //removed from cds as duplicate to FilterSchemaXml
        //assertEquals( tfsFilterMetaData.getFilterString(), cdsFilterMetaData.getFilterString() );

        assertEquals( ( tfsFilterMetaData.getEntryFilters() != null ? tfsFilterMetaData.getEntryFilters().size() : 0 ), cdsFilterMetaData
                        .getEntryFilters().size() );

        Set<gov.va.med.cds.clinicaldata.EntryFilter> clientEntryFilters = cdsFilterMetaData.getEntryFilters();

        for ( gov.va.med.cds.clinicaldata.EntryFilter clientEntryFilter : clientEntryFilters )
        {
            if ( clientEntryFilter != null )
            {
                assertTrue( compareEntryFilter( clientEntryFilter, tfsFilterMetaData.getEntryFilters() ) );
            }
        }

        assertEquals( ( tfsFilterMetaData.getVhimVersions() != null ? tfsFilterMetaData.getVhimVersions().size() : 0 ), cdsFilterMetaData
                        .getVhimVersions().size() );
        Set<String> clientVhimVersions = cdsFilterMetaData.getVhimVersions();
        for ( String clientVhimVersion : clientVhimVersions )
        {
            assertTrue( compareVhimVersion( clientVhimVersion, tfsFilterMetaData.getVhimVersions() ) );
        }

        assertEquals( tfsFilterMetaData.getFilterSchemaXml(), cdsFilterMetaData.getFilterSchemaXml() );

        assertEquals( tfsFilterMetaData.getFilterDescription(), cdsFilterMetaData.getFilterDescription() );

        assertEquals( tfsFilterMetaData.isContainsCorrelation(), cdsFilterMetaData.isContainsCorrelation() );

        assertEquals( ( tfsFilterMetaData.getDateAdded() != null ? tfsFilterMetaData.getDateAdded().toGregorianCalendar().getTime() : null ),
                        cdsFilterMetaData.getDateAdded() );

        assertEquals( ( tfsFilterMetaData.getDateDeprecated() != null ? tfsFilterMetaData.getDateDeprecated().toGregorianCalendar().getTime() : null ),
                        cdsFilterMetaData.getDateDeprecated() );

        assertEquals( ( tfsFilterMetaData.getDateActivated() != null ? tfsFilterMetaData.getDateActivated().toGregorianCalendar().getTime() : null ),
                        cdsFilterMetaData.getDateActivated() );

        assertEquals( ( tfsFilterMetaData.getDateDeactivated() != null ? tfsFilterMetaData.getDateDeactivated().toGregorianCalendar().getTime()
                        : null ), cdsFilterMetaData.getDateDeactivated() );

        assertEquals( ( tfsFilterMetaData.getDateUpdated() != null ? tfsFilterMetaData.getDateUpdated().toGregorianCalendar().getTime() : null ),
                        cdsFilterMetaData.getDateUpdated() );

        assertEquals( tfsFilterMetaData.getStatus(), cdsFilterMetaData.getStatus() );

        System.out.println( "exit: -x-x- mapFilterMetaDataTest" );

    }


    private boolean compareVhimVersion( String aClientVhimVersion, List<String> aDelegateVhimVersions )
    {
        for ( String delegateVhimVersion : aDelegateVhimVersions )
        {
            if ( aClientVhimVersion == null )
            {
                if ( delegateVhimVersion == null )
                {
                    return true;
                }
            }
            else if ( aClientVhimVersion.equals( delegateVhimVersion ) )
            {
                return true;
            }
        }
        return false;
    }


    private boolean compareReadCdsVdm( String aClientReadCdsVdm, List<String> aDelegateReadCdsVdms )
    {
        for ( String domainReadCdsVdm : aDelegateReadCdsVdms )
        {
            if ( aClientReadCdsVdm.equals( domainReadCdsVdm ) )
            {
                return true;
            }
        }
        return false;
    }


    private boolean compareDomainEntryPoint( gov.va.med.cds.clinicaldata.DomainEntryPoint clientDomainEntryPoint,
                    List<DomainEntryPoint> aDomainEntryPoints )
    {

        for ( DomainEntryPoint domainEntryPoint : aDomainEntryPoints )
        {
            if ( clientDomainEntryPoint.getName().equals( domainEntryPoint.getName() )
                            && clientDomainEntryPoint.getDomain().equals( domainEntryPoint.getDomain() ) )
            {
                return true;
            }
        }
        return false;
    }


    private boolean compareEntryFilter( gov.va.med.cds.clinicaldata.EntryFilter aClientEntryFilter, List<EntryFilter> aDelegateEntryFilters )
    {

        for ( gov.va.med.tfs.client.webservice.EntryFilter delegateEntryFilter : aDelegateEntryFilters )
        {
            if ( aClientEntryFilter.getXpath() == null )
            {
                if ( delegateEntryFilter.getXpath() == null
                                && compareDomainEntryPoint( aClientEntryFilter.getDomainEntryPoint(), delegateEntryFilter.getDomainEntryPoint() ) )
                {
                    return true;
                }
            }
            else if ( aClientEntryFilter.getXpath().equals( delegateEntryFilter.getXpath() )
                            && compareDomainEntryPoint( aClientEntryFilter.getDomainEntryPoint(), delegateEntryFilter.getDomainEntryPoint() ) )
            {
                return true;
            }
        }

        return false;
    }


    private boolean compareDomainEntryPoint( gov.va.med.cds.clinicaldata.DomainEntryPoint aClientDomainEntryPoint,
                    DomainEntryPoint aDelegateDomainEntryPoint )
    {
        if ( aClientDomainEntryPoint.getDomain().equals( aDelegateDomainEntryPoint.getDomain() )
                        && aClientDomainEntryPoint.getName().equals( aDelegateDomainEntryPoint.getName() ) )
        {
            return true;
        }

        return false;
    }


    private gov.va.med.tfs.client.webservice.TemplateMetaData createTestTemplateMetaData( )
        throws DatatypeConfigurationException
    {
        gov.va.med.tfs.client.webservice.TemplateMetaData tmd = new gov.va.med.tfs.client.webservice.TemplateMetaData();

        DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();

        XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar();

        tmd.setDateActivated( xmlGregorianCalendar );
        tmd.setDateAdded( xmlGregorianCalendar );
        tmd.setDateDeactivated( xmlGregorianCalendar );
        tmd.setDateDeprecated( xmlGregorianCalendar );
        tmd.setDateUpdated( xmlGregorianCalendar );
        //tmd.setDomainEntryPoints( new gov.va.med.tfs.client.webservice.DomainEntryPoint[] {} );
        tmd.setOperation( "Create" );
        tmd.setStatus( "Active" );
        tmd.setTemplateDescription( "A bogus template." );
        tmd.setTemplateId( "BogusTemplate1" );
        tmd.setTemplateJar( new byte[] {} );
        tmd.setTemplateName( "BogusTemplate1" );
        tmd.setTestOnly( false );
        //tmd.setVhimVersions( new String[] { "Vhim_4_00" } );

        return tmd;
    }


    private gov.va.med.tfs.client.webservice.FilterMetaData createTestFilterMetaData( )
        throws DatatypeConfigurationException
    {
        gov.va.med.tfs.client.webservice.FilterMetaData fmd = new gov.va.med.tfs.client.webservice.FilterMetaData();

        DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();

        XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar();

        fmd.setContainsCorrelation( true );
        fmd.setDateActivated( xmlGregorianCalendar );
        fmd.setDateAdded( xmlGregorianCalendar );
        fmd.setDateDeactivated( xmlGregorianCalendar );
        fmd.setDateDeprecated( xmlGregorianCalendar );
        fmd.setDateUpdated( xmlGregorianCalendar );
        //        fmd.setEntryFilters( new gov.va.med.tfs.client.webservice.EntryFilter[] { new gov.va.med.tfs.client.webservice.EntryFilter(
        //                        new gov.va.med.tfs.client.webservice.DomainEntryPoint( "QuestionnaireResult", "QuestionnaireResult" ),
        //                        "//questionnaireResult/documentIdentifier" ) } );
        fmd.setFilterDescription( "A bogus filter." );
        fmd.setFilterId( "BogusFilter1" );
        fmd.setFilterSchemaXml( "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\" attributeFormDefault=\"unqualified\"><xs:element name=\"ENTER_NAME_OF_ROOT_ELEMENT_HERE\"><xs:annotation><xs:documentation>Comment describing your root element</xs:documentation></xs:annotation></xs:element></xs:schema>" );
        fmd.setFilterString( "BogusFilter1" );
        fmd.setStatus( "Active" );
        //fmd.setVhimVersions( new String[] { "Vhim_4_00" } );

        return fmd;
    }

}
