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

//Framework Classes
import gov.va.med.fw.hl7.Segment;
import gov.va.med.fw.hl7.segment.IN1;
import gov.va.med.fw.hl7.builder.HL7MetaData;
import gov.va.med.fw.hl7.constants.SegmentConstants;
import gov.va.med.fw.model.EntityKey;
import gov.va.med.fw.util.builder.BuilderException;

//ESR Classes
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.insurance.InsurancePolicy;
import gov.va.med.esr.common.model.insurance.Medicare;
import gov.va.med.esr.common.model.insurance.PrivateInsurance;
import gov.va.med.esr.common.model.lookup.InsuredRelationship;
import gov.va.med.esr.common.model.person.*;

/**
 * Class to build the IN1 segment.
 * 
 * @author Alex Yoon
 * @version 1.0
 */
public class IN1Builder extends AbstractSegmentBuilder
{

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


   public IN1Builder()
    {
        super();
    }
    
    /**
     * Method to build the IN1 segment.
     * 
     * @param metaData
     *            The parameter object used to build the a IN1 segment.
     * @return The IN1 segment.
     */
    public Object build(HL7MetaData metaData, EntityKey entityKey)
            throws BuilderException
    {
        if ((metaData == null) || (metaData.getEntity() == null)
                || !(metaData.getEntity() instanceof Person))
        {
            throw new BuilderException(
                    "Invalid input parameter to build a segment");
        }

        IN1 segment = new IN1();
        Person person = (Person) metaData.getEntity();
        
        InsurancePolicy insurancePolicyToBuild = person.getInsuranceByEntityKey(entityKey);
        
        setDefaultValues(segment);        
        //Seq 1
        segment.setSetID("1");

        if (insurancePolicyToBuild != null)
        {
            try
            {
                //Seq 4
                segment.setInsuranceCompanyName(insurancePolicyToBuild
                        .getCompanyName());
                //Seq 5
                if (insurancePolicyToBuild.getAddress() != null)
                {
                    segment
                            .setInsuranceCompanyAddress(ElementFormatter
                                    .formatAddress(insurancePolicyToBuild
                                            .getAddress()));
                }
                //Seq 7
                segment.setInsuranceCompanyPhoneNumber(insurancePolicyToBuild
                        .getBusinessPhone() == null ? null
                        : insurancePolicyToBuild.getBusinessPhone()
                                .getPhoneNumber());
                //Seq 8
                segment.setGroupNumber(insurancePolicyToBuild.getGroupNumber());
                //Seq 9
                segment.setGroupName(insurancePolicyToBuild.getGroupName());
                //Sequence 12, 13, 36
                setMedicareAndPrivateInsuranceData(segment,
                        insurancePolicyToBuild);

                if (insurancePolicyToBuild.getInsurancePlan() != null)
                {
                    //Sequence 15
                        segment.setPlanType(super.build(insurancePolicyToBuild
                                .getInsurancePlan().getPlanType()));

                    //Sequence 28
                    segment.setPreadmitCertification(super.buildBooleanForVA001(insurancePolicyToBuild
                            .getInsurancePlan().getPrecertificationRequired()));
                }
                if (insurancePolicyToBuild.getSubscriber() != null)
                {
                    //Sequence 16
                    segment.setInsuredName(insurancePolicyToBuild
                            .getSubscriber().getName());

                    //Sequence 17
                    InsuredRelationship relationship = insurancePolicyToBuild
                            .getSubscriber().getRelationship();
                    segment.setInsuredRelationToPatient(super.build(relationship));
                }

            } catch (Exception e)
            {
                throw new BuilderException(
                        "Failed to build IN1 Segment due to an exception ", e);
            }

        }

        return segment;
    }
 
    protected void setDefaultValues(Segment segment)
    {
    	IN1 in1 = (IN1) segment;
    	in1.setInsuranceCompanyName(SegmentConstants.DEFAULT_VALUE);    	
    	in1.setInsuranceCompanyAddress(SegmentConstants.DEFAULT_VALUE);    	
    	in1.setInsuranceCompanyPhoneNumber(SegmentConstants.DEFAULT_VALUE);    	
    	in1.setGroupNumber(SegmentConstants.DEFAULT_VALUE);
        in1.setGroupName(SegmentConstants.DEFAULT_VALUE);
        in1.setPlanEffectiveDate(SegmentConstants.DEFAULT_VALUE);
        in1.setPlanExpirationDate(SegmentConstants.DEFAULT_VALUE);
        in1.setPolicyNumber(SegmentConstants.DEFAULT_VALUE);        
        in1.setPlanType(SegmentConstants.DEFAULT_VALUE);
        in1.setPreadmitCertification(SegmentConstants.DEFAULT_VALUE);
        in1.setInsuredName(SegmentConstants.DEFAULT_VALUE);
        in1.setInsuredRelationToPatient(SegmentConstants.DEFAULT_VALUE);
    }


    /**
     * Set PlanEffectiveDate, PlanExpirationDate, PolicyNumber
     * 
     * For Priv Ins, getPolicyEffectiveDate(). For Medicare -getPlanAEffDate or
     * PlanBEffectiveDate
     * 
     * @param segment
     * @param insurance
     */
    private void setMedicareAndPrivateInsuranceData(IN1 segment,
            InsurancePolicy insurance)
    {
        String planEffectiveDate = null;
        String planExpirationDate = null;
        String policyNumber = null;

        //For Priv Ins, getPolicyEffectiveDate(), for Medicare -
        // getPlanAEffDate or PlanBEffectiveDate
        if (insurance instanceof PrivateInsurance)
        {
            ImpreciseDate policyEffectiveDate = ((PrivateInsurance) insurance)
                    .getPolicyEffectiveDate();
            ImpreciseDate policyExpirationDate = ((PrivateInsurance) insurance)
                    .getPolicyExpirationDate();

            planEffectiveDate = DateFormatter.formatDate(policyEffectiveDate);
            planExpirationDate = DateFormatter.formatDate(policyExpirationDate);
            policyNumber = ((PrivateInsurance) insurance).getPolicyNumber();

        } else if (insurance instanceof Medicare)
        {
            Medicare medicare = (Medicare) insurance;
            String groupName = medicare.getGroupName();
            String groupNumber = medicare.getGroupNumber();
            if ((groupName != null && groupName.equalsIgnoreCase(IN1.MEDICARE_PART_A))
                    || (groupNumber != null && groupNumber
                            .equalsIgnoreCase(IN1.MEDICARE_PART_A)))
            {
                planEffectiveDate = DateFormatter.formatDate(medicare
                        .getPartAEffectiveDate());

            } else if ((groupName != null && groupName
                    .equalsIgnoreCase(IN1.MEDICARE_PART_B))
                    || (groupNumber != null && groupNumber
                            .equalsIgnoreCase(IN1.MEDICARE_PART_B)))
            {
                planEffectiveDate = DateFormatter.formatDate(medicare
                        .getPartBEffectiveDate());
            }

            policyNumber = medicare.getMedicareClaimNumber();
        }

        segment.setPlanEffectiveDate(planEffectiveDate);
        segment.setPlanExpirationDate(planExpirationDate);
        segment.setPolicyNumber(policyNumber);
    }
}