/**
 * 
 */


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


import gov.va.med.cds.audit.AbstractAuditLog;
import gov.va.med.cds.audit.ClientMapping;
import gov.va.med.cds.audit.FilterIdWrapper;
import gov.va.med.cds.audit.TemplateIdWrapper;
import gov.va.med.cds.audit.persistence.AuditLogPersistenceManagerInterface;
import gov.va.med.cds.util.LogMessageUtil;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.util.StringUtils;


/**
 * @author vhaislegberb
 *
 */
public class HibernateAuditLogPersistenceManager
    implements
        AuditLogPersistenceManagerInterface
{
    private static final Log logger = LogFactory.getLog( HibernateAuditLogPersistenceManager.class );
    private HibernateTemplate hibernateTemplate;
    private HibernateTemplate hibernateTemplateHa;
    private String appName;
    private List<String> haTemplateIdList;
    private Map<String, String> requestIdClientNameMap;


    public String getAppName( )
    {
        return appName;
    }


    @Autowired
    @Qualifier( "cdsAppName" )
    public void setAppName( String appName )
    {
        this.appName = appName;
    }


    /* (non-Javadoc)
     * @see gov.va.med.cds.audit.persistence.AuditLogPersistenceManagerInterface#storeAuditLog(gov.va.med.cds.audit.ReadAuditLog)
     */
    @SuppressWarnings( "unchecked" )
    public void storeAuditLog( AbstractAuditLog auditLog )
    {

        try
        {
            persistTemplateIdWrapper( auditLog );
            persistFilterIdWrapper( auditLog );

            // find client mapping
            long tId = auditLog.getTemplateIdWrapper().getId();
            long fId = auditLog.getFilterIdWrapper().getId();

            String clientName = auditLog.getClientId();
            if ( !StringUtils.hasLength( clientName ) )//existing clients requests with no client name
            {
                String requestId = auditLog.getRequestId();

                for ( String key : requestIdClientNameMap.keySet() )
                {
                    if ( requestId.toUpperCase().contains( key.toUpperCase() ) )
                    {
                        clientName = requestIdClientNameMap.get( key );
                        break;
                    }
                }

                if ( !StringUtils.hasLength( clientName ) )
                {
                    if ( auditLog.getFilterIdWrapper().getFilterId().startsWith( "CHDR" ) )
                    {
                        clientName = "Clinical Health Data Repository";
                    }
                }
                auditLog.setClientId( clientName );
            }

            List<ClientMapping> hibernateResult = null;
            if ( StringUtils.hasLength( clientName ) )// for both existing and ftp client
            {
                hibernateResult = ( List<ClientMapping> )hibernateTemplate.findByNamedQueryAndNamedParam(
                                "cds.clientmapping.filter.template.clientname", new String[] { "templateId", "filterId", "clientName" },
                                new Object[] { tId, fId, clientName } );
                
                if (hibernateResult.size() == 0)
                {
                	hibernateResult = ( List<ClientMapping> )hibernateTemplate.findByNamedQueryAndNamedParam( "cds.clientmapping.filter.template",
                            new String[] { "templateId", "filterId" }, new Long[] { tId, fId } );
                }
            }
            else
            {
                hibernateResult = ( List<ClientMapping> )hibernateTemplate.findByNamedQueryAndNamedParam( "cds.clientmapping.filter.template",
                                new String[] { "templateId", "filterId" }, new Long[] { tId, fId } );
            }

            if ( hibernateResult.size() > 0 )
            {
                auditLog.setClientMapping( hibernateResult.get( 0 ) );
                if ( auditLog.getFacility() == null )
                {
                    auditLog.setFacility( auditLog.getClientMapping().getShortName() );
                }
            }
            else
            // rare scenario
            {
                auditLog.setClientMapping( null );
            }

            if ( haTemplateIdList.contains( auditLog.getTemplateIdWrapper().getTemplateId() ) )
            {
                hibernateTemplateHa.save( auditLog );
                hibernateTemplateHa.flush();
            }
            else
            {

                hibernateTemplate.save( auditLog );
                hibernateTemplate.flush();
            }
        }
        catch ( RuntimeException ex )
        {
            logger.error( LogMessageUtil.buildMessage( null, null, appName, "Error Auditing READ request message. " ), ex );
        }
    }


    @SuppressWarnings( "unchecked" )
    private void persistTemplateIdWrapper( AbstractAuditLog auditLog )
    {
        List<TemplateIdWrapper> hibernateTemplateIds = ( List<TemplateIdWrapper> )hibernateTemplate.findByNamedQueryAndNamedParam( "template.name",
                        new String[] { "templateName", "templateName" }, new String[] { auditLog.getTemplateIdWrapper().getTemplateId(),
                                        auditLog.getTemplateIdWrapper().getTemplateId() } );

        if ( hibernateTemplateIds.size() < 1 )
        {
            hibernateTemplate.save( auditLog.getTemplateIdWrapper() );
        }
        else
        {
            auditLog.setTemplateIdWrapper( hibernateTemplateIds.get( 0 ) );
        }
    }


    @SuppressWarnings( "unchecked" )
    private void persistFilterIdWrapper( AbstractAuditLog auditLog )
    {
        List<FilterIdWrapper> hibernateFilterIds = ( List<FilterIdWrapper> )hibernateTemplate.findByNamedQueryAndNamedParam( "filter.name",
                        new String[] { "filterName", "filterName" }, new String[] { auditLog.getFilterIdWrapper().getFilterId(),
                                        auditLog.getFilterIdWrapper().getFilterId() } );
        if ( hibernateFilterIds.size() < 1 )
        {
            hibernateTemplate.save( auditLog.getFilterIdWrapper() );
        }
        else
        {
            auditLog.setFilterIdWrapper( hibernateFilterIds.get( 0 ) );
        }
    }


    public void setHibernateTemplate( HibernateTemplate hibernateTemplate )
    {
        this.hibernateTemplate = hibernateTemplate;
    }


    public void setHaTemplateIdList( List<String> haTemplateIdList )
    {
        this.haTemplateIdList = haTemplateIdList;
    }


    public HibernateTemplate getHibernateTemplateHa( )
    {
        return hibernateTemplateHa;
    }


    public void setHibernateTemplateHa( HibernateTemplate hibernateTemplateHa )
    {
        this.hibernateTemplateHa = hibernateTemplateHa;
    }


    public void setRequestIdClientNameMap( Map<String, String> requestIdClientNameMap )
    {
        this.requestIdClientNameMap = requestIdClientNameMap;
    }

}