/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.messaging.parser;

// Framework Classes
import java.util.List;

import gov.va.med.fw.hl7.InvalidMessageException;
import gov.va.med.fw.hl7.Message;
import gov.va.med.fw.hl7.constants.SegmentConstants;
import gov.va.med.fw.hl7.segment.*;
import gov.va.med.fw.util.builder.Builder;
import gov.va.med.fw.util.builder.BuilderException;

// Common Classes
import gov.va.med.esr.common.model.ee.*;
import gov.va.med.esr.common.model.person.*;

// Messaging Classes
import gov.va.med.esr.common.builder.datatype.metadata.*;
import gov.va.med.esr.common.builder.entity.*;
import gov.va.med.esr.common.builder.entity.metaData.*;

/**
 * @author Martin Francisco
 */
public class Z11Parser extends EntityBuilder
{
    /**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = 7295355420919189955L;

	private Builder personBuilder;

    private Builder deathRecordBuilder;

    private Builder incompetenceRulingBuilder;

    private Builder ineligibilityFactorBuilder;

    private Builder monetaryBenefitAwardBuilder;

    private Builder serviceConnectionAwardBuilder;
    
    private Builder vaPensionBuilder;

    /**
     * Default constructor.
     */
    public Z11Parser()
    {
        super();
    }

    public Builder getDeathRecordBuilder()
    {
        return this.deathRecordBuilder;
    }

    public void setDeathRecordBuilder(Builder deathRecordBuilder)
    {
        this.deathRecordBuilder = deathRecordBuilder;
    }

    public Builder getIncompetenceRulingBuilder()
    {
        return this.incompetenceRulingBuilder;
    }

    public void setIncompetenceRulingBuilder(Builder incompetenceRulingBuilder)
    {
        this.incompetenceRulingBuilder = incompetenceRulingBuilder;
    }

    public Builder getIneligibilityFactorBuilder()
    {
        return this.ineligibilityFactorBuilder;
    }

    public void setIneligibilityFactorBuilder(Builder ineligibilityFactorBuilder)
    {
        this.ineligibilityFactorBuilder = ineligibilityFactorBuilder;
    }

    public Builder getMonetaryBenefitAwardBuilder()
    {
        return this.monetaryBenefitAwardBuilder;
    }

    public void setMonetaryBenefitAwardBuilder(
            Builder monetaryBenefitAwardBuilder)
    {
        this.monetaryBenefitAwardBuilder = monetaryBenefitAwardBuilder;
    }

    public Builder getServiceConnectionAwardBuilder()
    {
        return this.serviceConnectionAwardBuilder;
    }

    public void setServiceConnectionAwardBuilder(
            Builder serviceConnectionAwardBuilder)
    {
        this.serviceConnectionAwardBuilder = serviceConnectionAwardBuilder;
    }

    /**
     * @return Returns the personBuilder.
     */
    public Builder getPersonBuilder()
    {
        return personBuilder;
    }

    /**
     * @param personBuilder
     *            The personBuilder to set.
     */
    public void setPersonBuilder(Builder personBuilder)
    {
        this.personBuilder = personBuilder;
    }
    

    public Builder getVaPensionBuilder() {
		return vaPensionBuilder;
	}

	public void setVaPensionBuilder(Builder vaPensionBuilder) {
		this.vaPensionBuilder = vaPensionBuilder;
	}

	public Person build(Object[] args) throws BuilderException
    {
        return this.build((Person) args[0], (Message) args[1]);
    }

    public Person build(Person input, Message message) throws BuilderException
    {
        try
        {
            Person person = buildPerson(input, message);

            person.setDeathRecord(this.buildDeathRecord(
                    person.getDeathRecord(), message));
            person.setIncompetenceRuling(this.buildIncompetenceRuling(person
                    .getIncompetenceRuling(), message));
            person.setIneligibilityFactor(this.buildIneligibilityFactor(person
                    .getIneligibilityFactor(), message));
            person.setMonetaryBenefitAward(this.buildMonetaryBenefitAward(
                    person.getMonetaryBenefitAward(), message));
            person.setServiceConnectionAward(this.buildServiceConnectionAward(
                    person.getServiceConnectionAward(), message));
            
            //this.buildReceivedEligibilities(person, message);
            this.buildSensitiveRecord(person, message);
            
            //CR 5987 Add Dental Indicator and data element(s) into HECMS.
            buildClassIIDental(person, message);

            return person;
        } catch (InvalidMessageException e)
        {
            throw new BuilderException(e);
        }
    }

    private Person buildPerson(Person input, Message message)
            throws BuilderException, InvalidMessageException
    {
        //Pass null for zem, zen, zmh, zio. They are not present in incoming
        // ORUZ11 from MVR
        PersonMetaData metaData = new PersonMetaDataFromPID((PID) message
                .getSegment(SegmentConstants.PID), (ZPD) message
                .getSegment(SegmentConstants.ZPD), null, null, (ZEL) message
                .getSegment(SegmentConstants.ZEL), (MSH) message
                .getSegment(SegmentConstants.MSH), null, null);
        metaData.setEntity(input);

        return this.buildPerson(metaData);
    }

    private Person buildPerson(PersonMetaData metaData) throws BuilderException
    {
        return (Person) this.personBuilder.build(metaData);
    }

    private DeathRecord buildDeathRecord(DeathRecord input, Message message)
            throws BuilderException, InvalidMessageException
    {
        DeathRecordMetaData metaData = new DeathRecordMetaDataFromZPD(
                (ZPD) message.getSegment(SegmentConstants.ZPD), (MSH) message
                        .getSegment(SegmentConstants.MSH), false);
        metaData.setEntity(input);

        return this.buildDeathRecord(metaData);
    }

    private DeathRecord buildDeathRecord(DeathRecordMetaData metaData)
            throws BuilderException
    {
        return (DeathRecord) this.deathRecordBuilder.build(metaData);
    }

    private IncompetenceRuling buildIncompetenceRuling(
            IncompetenceRuling input, Message message) throws BuilderException,
            InvalidMessageException
    {
        IncompetenceRulingMetaData metaData = new IncompetenceRulingMetaDataFromZPD(
                (ZPD) message.getSegment(SegmentConstants.ZPD));
        metaData.setEntity(input);

        return this.buildIncompetenceRuling(metaData);
    }

    private IncompetenceRuling buildIncompetenceRuling(
            IncompetenceRulingMetaData metaData) throws BuilderException
    {
        return (IncompetenceRuling) this.incompetenceRulingBuilder
                .build(metaData);
    }

    private IneligibilityFactor buildIneligibilityFactor(
            IneligibilityFactor input, Message message)
            throws BuilderException, InvalidMessageException
    {
        IneligibilityFactorMetaData metaData = new IneligibilityFactorMetaDataFromZIE(
                (ZIE) message.getSegment(SegmentConstants.ZIE), null);
        metaData.setEntity(input);

        return this.buildIneligibilityFactor(metaData);
    }

    private IneligibilityFactor buildIneligibilityFactor(
            IneligibilityFactorMetaData metaData) throws BuilderException
    {
        return (IneligibilityFactor) this.ineligibilityFactorBuilder
                .build(metaData);
    }

    private MonetaryBenefitAward buildMonetaryBenefitAward(
            MonetaryBenefitAward input, Message message)
            throws BuilderException, InvalidMessageException
    {
        MonetaryBenefitAwardMetaData metaData = new MonetaryBenefitAwardMetaDataFromZEL(
                (ZEL) message.getSegment(SegmentConstants.ZEL));
        metaData.setEntity(input);

        MonetaryBenefitAward awd = this.buildMonetaryBenefitAward(metaData);
        
        //CR 4510- VBA Pension Data Sharing
        VAPensionMetaData pensionMetaData = new VAPensionMetaDataFromOBX(message.getSegments(SegmentConstants.OBX));
        pensionMetaData.setEntity(awd);
        awd = (MonetaryBenefitAward) this.vaPensionBuilder.build(pensionMetaData);
        
        return awd;
    }

    private MonetaryBenefitAward buildMonetaryBenefitAward(
            MonetaryBenefitAwardMetaData metaData) throws BuilderException
    {
        return (MonetaryBenefitAward) this.monetaryBenefitAwardBuilder
                .build(metaData);
    }

    private ServiceConnectionAward buildServiceConnectionAward(
            ServiceConnectionAward input, Message message)
            throws BuilderException, InvalidMessageException
    {
        ServiceConnectionAwardMetaData metaData = new ServiceConnectionAwardMetaDataFromZSP(
                (ZSP) message.getSegment(SegmentConstants.ZSP), message
                        .getSegments(SegmentConstants.ZRD));
        metaData.setEntity(input);

        return this.buildServiceConnectionAward(metaData);
    }

    private ServiceConnectionAward buildServiceConnectionAward(
            ServiceConnectionAwardMetaData metaData) throws BuilderException
    {
        return (ServiceConnectionAward) this.serviceConnectionAwardBuilder
                .build(metaData);
    }

    private void buildSensitiveRecord(Person person, Message message)
            throws BuilderException, InvalidMessageException
    {
        OBX obx = null;

        List obxs = message.getSegments(SegmentConstants.OBX);
        for (int index = 0; index < ((obxs == null) ? 0 : obxs.size()); index++)
        {
            OBX current = (OBX) obxs.get(index);
            CE id = CE.create(current.getObservationID(), current
                    .getComponentDelimiter());
            if ((id != null) && "38.1".equals(super.getValue(id.getID()))
                    && "SECURITY LOG".equals(super.getValue(id.getText())))
            {
                obx = current;
            }
        }

        if ((person != null) && (obx != null))
        {
            CE sensitiveRecord = CE.create(obx.getObservationValue(), obx
                    .getComponentDelimiter());

            if (sensitiveRecord != null)
            {
                person.setSensitiveRecord(super.build(person
                        .isSensitiveRecord(), super.getValue(sensitiveRecord
                        .getID())));
            }
        }
    }
    
    private void buildClassIIDental(Person person, Message message)
	throws BuilderException, InvalidMessageException
	{
		ZSP zsp =(ZSP) message.getSegment(SegmentConstants.ZSP);
		if (zsp != null)
		{
			person.setEligibleForClassIIDental(
					this.build(person.getEligibleForClassIIDental(), zsp.getClassIIDentalIndicator()));
			person.setClassIIDentalApplicationDueBefore(
					this.build(person.getClassIIDentalApplicationDueBefore(), zsp.getClassIIDentalApplicationDueBeforeDate()));
		}
	}

}