package gov.va.med.esr.messaging.service.outbound;

import gov.va.med.esr.common.model.lookup.MessageStatus;
import gov.va.med.esr.common.model.messaging.MessageLogEntry;
import gov.va.med.esr.common.model.messaging.SiteIdentity;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.service.trigger.PersonTriggerEvent;
import gov.va.med.fw.hl7.InvalidMessageException;
import gov.va.med.fw.hl7.Message;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.builder.BuilderException;

/**
 * Concrete implementation for processing Solicitated outbound messages
 * e.g ORFZ10, ORFZ11. 
 * 
 * @author Rajiv Patnaik Created on Dec 22, 2005
 * @version 1.0
 * 
 * Copyright © 2005 VHA. All rights reserved
 */
public class SolicitedOutboundMessageService extends
        AbstractOutboundProcessService implements OutboundMessageService
{

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.service.outbound.OutboundMessageService#processMessage(gov.va.med.esr.common.model.person.Person,
     *      gov.va.med.esr.common.model.messaging.SiteIdentity)
     */
    public void processMessage(Person person, SiteIdentity siteIdentity)
            throws ServiceException
    {
        this.processMessage(person, siteIdentity, null, null);

    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.service.outbound.OutboundMessageService#processMessage(gov.va.med.esr.common.model.person.Person,
     *      gov.va.med.esr.common.model.messaging.SiteIdentity,
     *      gov.va.med.esr.common.model.messaging.MessageLogEntry)
     */
    public void processMessage(Person person, SiteIdentity siteIdentity,
            MessageLogEntry log) throws ServiceException
    {
        this.processMessage(person, siteIdentity, null, log);

    }

    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.service.outbound.OutboundMessageService#processMessage(gov.va.med.esr.common.model.person.Person,
     *      gov.va.med.esr.common.model.messaging.SiteIdentity,
     *      gov.va.med.esr.service.trigger.PersonTriggerEvent)
     */
    public void processMessage(Person person, SiteIdentity siteIdentity,
            PersonTriggerEvent triggerEvent) throws ServiceException
    {
        this.processMessage(person, siteIdentity, triggerEvent, null);

    }

    /* (non-Javadoc)
     * @see gov.va.med.esr.messaging.service.outbound.OutboundMessageService#processMessage(gov.va.med.esr.common.model.person.Person, gov.va.med.esr.common.model.messaging.SiteIdentity, gov.va.med.esr.service.trigger.PersonTriggerEvent, gov.va.med.esr.common.model.messaging.MessageLogEntry)
     */
    public void processMessage(Person person, SiteIdentity siteIdentity,
            PersonTriggerEvent triggerEvent, MessageLogEntry incomingLogEntry)
            throws ServiceException
    {
    	this.processMessage(person, siteIdentity, triggerEvent, null, false);
    }
    
    /*
     * (non-Javadoc)
     * 
     * @see gov.va.med.esr.messaging.service.outbound.OutboundMessageService#processMessage(gov.va.med.esr.common.model.person.Person,
     *      gov.va.med.esr.common.model.messaging.SiteIdentity,
     *      gov.va.med.esr.service.trigger.PersonTriggerEvent,
     *      gov.va.med.esr.common.model.messaging.MessageLogEntry)
     */
    public void processMessage(Person person, SiteIdentity siteIdentity,
            PersonTriggerEvent triggerEvent, MessageLogEntry incomingLogEntry,boolean isRetransmitFromUI)
            throws ServiceException
    {
        try
        {
            Message message = buildMessage(person, siteIdentity, triggerEvent);

            MessageLogEntry logEntry;

            //If normal outbound message.
            if (incomingLogEntry == null)
            {
                logEntry = super.createMessageLog(message, message
                        .getMessageID(), message.getMessageID(), person,
                        siteIdentity.getVaFacility(), super
                                .buildTransmissionDate(message),MessageStatus.COMPLETE);
            } else
            {
                // CR 6445
                // If retransmission. There will be only one message as there is
                // only one LogEntry.
                   logEntry = super.createMessageLog(message, message
                           .getMessageID(), message.getMessageID(), person,
                           siteIdentity.getVaFacility(), super
                                   .buildTransmissionDate(message),
                           incomingLogEntry.getRetransmissionCount() + 1,
                           incomingLogEntry, MessageStatus.RETRANSMIT);
            }
            
            super.logMessage(logEntry);

            super.publishMessage(message);
 
            super.logger.info("Built Solicitated Outbound Message Id " + message.getMessageID()
                    + " and message type " + this.getMessageTypeCode()
                    + " for facility " + siteIdentity.getVaFacility().getCode());
            
            if (super.logger.isDebugEnabled()) 
            {
                super.logger.debug("Batch Message: " + message.getMessageData());
            }
        } catch (BuilderException e)
        {
            throw new ServiceException("Failed to build outbound "
                    + this.getMessageTypeCode()
                    + " message due to an exception in processMessage", e);
        } catch (InvalidMessageException e)
        {
            //ASSERT: Should not happen if the message is already parsed.
            throw new RuntimeException(
                    "Failed to obtain data from the message", e);
        }

    }

    private Message buildMessage(Person person, SiteIdentity siteIdentity,
            PersonTriggerEvent triggerEvent) throws ServiceException
    {
        Message message = null;

        try
        {
            message = super.buildMessage(new Object[] { person, siteIdentity,
                    null, triggerEvent });

        } catch (BuilderException e)
        {
            throw new ServiceException("Failed to build outbound "
                    + this.getMessageTypeCode()
                    + " message due to an exception", e);
        }

        return message;
    }

}