/**
 * 
 */


package gov.va.med.cds.persistence.hibernate;


import gov.va.med.cds.common.person.correlation.PersonIdentifier;
import gov.va.med.cds.common.person.correlation.PersonIdentifierInterface;
import gov.va.med.cds.exception.ErrorCodeEnum;
import gov.va.med.cds.filter.EntryFilterInterface;
import gov.va.med.cds.persistence.PersistenceException;
import gov.va.med.cds.persistence.QueryStrategyInterface;
import gov.va.med.cds.persistence.QueryWorkInterface;
import gov.va.med.cds.persistence.ReadException;
import gov.va.med.cds.template.generated.JaxBMarshallerUnmarshallerInterface;

import org.dom4j.Document;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;


/**
 * @author DNS   egberb
 *
 */
public class FailingSiteSpecificHibernateReadPersistenceManager
    extends
        DefaultHibernateReadPersistenceManager
{
    @Autowired
    protected String cdsAppName;


    /* (non-Javadoc)
     * @see gov.va.med.cds.persistence.ReadPersistenceManagerInterface#isApplicable(gov.va.med.cds.filter.EntryFilterInterface, java.util.List)
     */
    @Override
    public boolean isApplicable( EntryFilterInterface entryFilter, List<PersonIdentifierInterface> personIdentifiers )
        throws PersistenceException
    {
        return ( super.isApplicable( entryFilter, personIdentifiers ) && containsSiteIdentifier( personIdentifiers ) );
    }


    /*
     * (non-Javadoc)
     * @see gov.va.med.cds.persistence.hibernate.DefaultHibernateReadPersistenceManager#createQueryWork(gov.va.med.cds.persistence.QueryStrategyInterface, gov.va.med.cds.filter.EntryFilterInterface, java.util.List, java.lang.Class)
     */
    @Override
    protected List<QueryWorkInterface> createQueryWork( QueryStrategyInterface queryStrategy, EntryFilterInterface entryFilter,
                    List<PersonIdentifierInterface> personIdentifiers, Class<?> pointInTimeUserType, String siteId, JaxBMarshallerUnmarshallerInterface marshallerUnmarshaller )
        throws PersistenceException
    {
        return queryStrategy.createQueryWork( getSessionFactory( entryFilter.getTemplateId() ), entryFilter, findSitePatients( personIdentifiers ),
                        pointInTimeUserType, siteId, marshallerUnmarshaller );

    }


    @Override
    public Document performReadOnClinicalData( EntryFilterInterface entryFilter, List<PersonIdentifierInterface> personIdentifiers,
                    String applicationName )
        throws PersistenceException
    {
        Document resultDocument = null;
        PersonIdentifier[] pids = personIdentifiers.toArray( new PersonIdentifier[personIdentifiers.size()] );
        if ( pids.length > 0 )
        {
            throw new PersistenceException( ErrorCodeEnum.READ_REQUEST_DATA_SOURCE_FAILURE, this.siteIdentifier, pids[0].getIdentity(),
                            entryFilter.getDomainEntryPoint(), this.managerIdentifier,
                            "gov.va.med.cds.persistence.hibernate.FailingSiteSpecificHibernateReadPersistenceManager" );
        }

        return resultDocument;
    }


    /**
     * Iterates over the list until it comes across the person identifier with the assigning facility 
     * that matches the site.
     * @param personIdentifiers This list of person identifiers to look through.
     * @return The person identifier with an assigning facility that matches the 
     * site identifier of the 
     */
    private List<String> findSitePatients( List<PersonIdentifierInterface> personIdentifiers )
    {
        List<String> sitePatients = new ArrayList<String>();

        if ( personIdentifiers == null || personIdentifiers.size() == 0 )
        {
            throw new ReadException( ErrorCodeEnum.READ_PERSISTENCE_MGR_NULL_PERSON_IDENTIFIERS_LIST, this.managerIdentifier );
        }

        for ( PersonIdentifierInterface personIdentifier : personIdentifiers )
        {
            if ( this.siteIdentifier.equals( personIdentifier.getAssigningFacility() ) )
            {
                sitePatients.add( personIdentifier.getIdentity() );
            }
        }

        if ( sitePatients.size() == 0 )
        {
            throw new ReadException( ErrorCodeEnum.READ_PERSISTENCE_MGR_NO_PERSON_WITH_SITE_ID, this.siteIdentifier );
        }

        return sitePatients;
    }


    /**
     * Determines whether the list of 
     * @param personIdentifiers
     * @return
     */
    private boolean containsSiteIdentifier( List<PersonIdentifierInterface> personIdentifiers )
    {
        for ( PersonIdentifierInterface personIdentifier : personIdentifiers )
        {
            if ( this.siteIdentifier.equals( personIdentifier.getAssigningFacility() ) )
            {
                return true;
            }
        }
        return false;
    }


    public String getSiteIdentifier( )
    {
        return this.siteIdentifier;
    }

}
