/********************************************************************
 * Copyright © 2004 EDS. All rights reserved
 ********************************************************************/
//Package
package gov.va.med.esr.messaging.builder.message;

// Java classes
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import gov.va.med.fw.hl7.Message;
import gov.va.med.fw.hl7.segment.MSH;
import gov.va.med.fw.hl7.segment.QRD;
import gov.va.med.fw.model.AbstractEntity;
import gov.va.med.fw.util.builder.BuilderException;

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.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;

/**
 * Class to build a QRYZ11 message.
 * 
 * @author Alex Yoon
 * @version 1.0
 */
public class QRYZ11Builder extends AbstractMessageBuilder
{

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

   /**
     * Default constructor
     */
    public QRYZ11Builder()
    {
        super();
    }


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

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

        try
        {
            segments.add(buildMSHSegment());
            segments.add(buildQRDSegment(person));
            segments.add(super.buildQRFSegment(person,
                    HL7Constants.WHERE_SUBJECT_FILTER_IVM, getName(person),
                    getBirthDate(person)));

            message = new Message(segments, HL7Constants.QRYZ11, 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() throws BuilderException
    {
        MSH segment = null;

        try
        {
            MSHMetaData metaData = new MSHMetaData((AbstractEntity) null);
            Date creationDatetime = Calendar.getInstance().getTime();

            String id = getMessagingService().generateControlIdentifier();

            metaData
                    .setApplicationACKType(HL7Constants.APPLICATION_ACK_TYPE_AL);
            metaData.setControlID(id);
            metaData.setCreationDatetime(creationDatetime);
            metaData.setMessageType(HL7Constants.QRYZ11);
            metaData
                    .setReceivingApplication(HL7Constants.HEADER_RECEIVING_APPLICATION_MVR);
            metaData.setReceivingFacility(VAFacility.CODE_MVR.getName()
                    + HL7Constants.HEADER_RECEIVING_FACILITY_MVR);

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

        return segment;
    }

    /**
     * Method to build the QRD segment.
     * 
     * @param person
     *            The person who is source for QRD segment content.
     * @return The QRD segment.
     * @throws BuilderException
     */
    private QRD buildQRDSegment(Person person) throws BuilderException
    {
        QRD segment = null;

        String ssn = person.getOfficialSsn() == null ? null : person
                .getOfficialSsn().getFormattedSsnText();
        //Income Year is current year minus 1
        String incomeYear = String.valueOf(Calendar.getInstance().get(
                Calendar.YEAR) - 1);

        segment = super.buildQRDSegment(person, null, ssn, Calendar.getInstance()
                .getTime(), HL7Constants.WHAT_SUBJECT_FILTER_ELG, incomeYear);

        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;
    }
}