package gov.va.med.esr.messaging.builder.message;

import gov.va.med.esr.common.model.lookup.NameType;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.messaging.SiteIdentity;
import gov.va.med.esr.common.model.person.BirthRecord;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.messaging.constants.HL7Constants;
import gov.va.med.fw.hl7.Message;
import gov.va.med.fw.hl7.segment.MSH;
import gov.va.med.fw.hl7.segment.QPD;
import gov.va.med.fw.model.AbstractEntity;
import gov.va.med.fw.util.builder.BuilderException;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class QRYZ21Builder extends AbstractMessageBuilder {



    /**
    * An instance of serialVersionUID 
    */
   private static final long serialVersionUID = -478577045295329834L;

   /**
     * Default constructor
     */
    public QRYZ21Builder()
    {
        super();
    }
    
    public Message build(Object[] args) throws BuilderException
    {
        return this.build((Person) args[0], (SiteIdentity) args[1]);
    }


    /**
     * Method to build the QRYZ21 from person.
     * 
     * @param person
     *            The person who is source for message content.
     * @return The QRYZ11 message.
     * @throws BuilderException
     */
    public Message build(Person person, SiteIdentity siteIdentity) throws BuilderException
    {
        if (person == null || siteIdentity == null)
        {
            throw new BuilderException(
                    "Invalid input parameters to build an object");
        }

        Message message = null;
        List segments = new ArrayList();

        try
        {
            segments.add(buildMSHSegment(siteIdentity));
            segments.add(buildQPDSegment(person));
            segments.add(super.buildRCPSegment((AbstractEntity) null));

            message = new Message(segments, HL7Constants.QRYZ21, true);
            
        } catch (Exception e)
        {
            throw new BuilderException(
                    "Failed to build QRYZ11 message due to an exception ", e);
        }

        return message;
    }

    /**
     * Method to build MSH segment.
     * 
     * @return The MSH segment.
     * @throws BuilderException
     */
    private MSH buildMSHSegment(SiteIdentity site) throws BuilderException
    {
        MSH segment = null;

        try
        {
        	if (site == null)
            {
                throw new BuilderException(
                        "Invalid input parameter to build a segment");
            }
        	
            MSHMetaData metaData = new MSHMetaData((AbstractEntity) null);
            Date creationDatetime = Calendar.getInstance().getTime();

            String id = getMessagingService().generateControlIdentifier();
            String receiving_facility = site.getVaFacility().getStationNumber();
            String receiving_application = "VAMC " + receiving_facility;
            

            metaData
                    .setApplicationACKType(HL7Constants.APPLICATION_ACK_TYPE_NE);
            metaData.setControlID(id);
            metaData.setCreationDatetime(creationDatetime);
            metaData.setMessageType(HL7Constants.QRYZ21);
            metaData.setReceivingApplication(receiving_application);
            metaData.setReceivingFacility(receiving_facility);            

            //Get segment through its builder
            segment = (MSH) (getMshBuilder().build(metaData));
            segment.setVersionID( HL7Constants.NEW_VERSION_ID );
        } catch (Exception e)
        {
            throw new BuilderException(
                    "Failed to build MSH Segment due to an exception ", e);
        }

        return segment;
    }

    /**
     * Method to build the QPD segment.
     * 
     * @param person
     *            The person who is source for QPD segment content.
     * @return The QPD segment.
     * @throws BuilderException
     */
    private QPD buildQPDSegment(Person person) throws BuilderException
    {
        QPD segment = null;
        
        segment = super.buildQPDSegment(person, null, HL7Constants.QUERY_Z21);

        return segment;
    }

    /**
     * Method to find legal name and return formatted name.
     * 
     * @param person
     *            The person object.
     * @return String formatted name.
     */
    private String getName(Person person)
    {
        String name = null;

        Set names = person.getNames();
        Name legalName = null;

        if (names != null)
        {
            Iterator iterNames = names.iterator();
            while (iterNames.hasNext())
            {
                Name theName = (Name) iterNames.next();
                if ((theName != null) && (theName.getType() != null))
                {
                    if (NameType.LEGAL_NAME.getName().equals(
                            theName.getType().getCode()))
                    {
                        legalName = theName;
                        break;
                    }
                }
            }
        }

        if (legalName != null)
        {
            name = ElementFormatter.formatName(legalName);
        }

        return name;
    }

    /**
     * Method to get birth date and return string value.
     * 
     * @param person
     *            The person object.
     * @return String formatted date.
     */
    private String getBirthDate(Person person)
    {
        String birthDate = null;

        BirthRecord birthRecord = person.getBirthRecord();
        if (birthRecord != null)
        {
            birthDate = DateFormatter.formatDate(birthRecord.getBirthDate());
        }

        return birthDate;
    }

}
