/********************************************************************
 * Copyright © 2004 EDS. All rights reserved
 ********************************************************************/
package gov.va.med.esr.common.builder.entity;

// Java Classes

// Library Classes

// Framework Classes

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.insurance.InsurancePlan;
import gov.va.med.esr.common.model.insurance.InsurancePolicy;
import gov.va.med.esr.common.model.insurance.InsuranceSubscriber;
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.InsuranceReportSource;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.party.Phone;

// Messaging Classes

/**
 * Builds a rated disability from a message and a person if elements in the IN1
 * segments are present
 * 
 * @author Carlos Ruiz
 * @version 1.0
 */
public abstract class InsurancePolicyBuilder extends EntityBuilder
{
    private static final long serialVersionUID = -1370346746640850300L;
    private Builder addressBuilder;

    private Builder phoneBuilder;

    private Builder planBuilder;

    private Builder subscriberBuilder;

    private Builder insuranceReportSourceBuilder;

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

    public Builder getAddressBuilder()
    {
        return this.addressBuilder;
    }

    public void setAddressBuilder(Builder addressBuilder)
    {
        this.addressBuilder = addressBuilder;
    }

    public Builder getPhoneBuilder()
    {
        return this.phoneBuilder;
    }

    public void setPhoneBuilder(Builder phoneBuilder)
    {
        this.phoneBuilder = phoneBuilder;
    }

    public Builder getPlanBuilder()
    {
        return this.planBuilder;
    }

    public void setPlanBuilder(Builder planBuilder)
    {
        this.planBuilder = planBuilder;
    }

    public Builder getSubscriberBuilder()
    {
        return this.subscriberBuilder;
    }

    public void setSubscriberBuilder(Builder subscriberBuilder)
    {
        this.subscriberBuilder = subscriberBuilder;
    }

    /**
     * @return Returns the insuranceReportSourceBuilder.
     */
    public Builder getInsuranceReportSourceBuilder()
    {
        return insuranceReportSourceBuilder;
    }

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

    private Address buildAddress(Address input, AddressMetaData metaData)
            throws BuilderException
    {
        if (metaData == null)
        {
            return null;
        }
        metaData.setEntity(input);
        return (Address) this.addressBuilder.build(metaData);

    }

    private Phone buildPhone(Phone input, PhoneMetaData metaData)
            throws BuilderException
    {
        if (metaData == null)
        {
            return null;
        }
        metaData.setEntity(input);
        return (Phone) this.phoneBuilder.build(metaData);

    }

    private InsurancePlan buildInsurancePlan(InsurancePlan input,
            InsurancePlanMetaData metaData) throws BuilderException
    {
        if (metaData == null)
        {
            return null;
        } else
        {
            metaData.setEntity(input);
            return (InsurancePlan) this.planBuilder.build(metaData);
        }
    }

    private InsuranceSubscriber buildSubsciber(InsuranceSubscriber input,
            InsuranceSubscriberMetaData metaData) throws BuilderException
    {
        if (metaData == null)
        {
            return null;
        } else
        {
            metaData.setEntity(input);
            return (InsuranceSubscriber) this.subscriberBuilder.build(metaData);
        }
    }

    private boolean shouldKeep(InsurancePolicy obj)
    {
        return ((obj.getSubscriber() != null));
    }

    private void transfer(InsurancePolicy input,
            InsurancePolicyMetaData metaData) throws BuilderException
    {
        input.setAddress(this.buildAddress(input.getAddress(), metaData
                .getAddress()));
        input.setBusinessPhone(this.buildPhone(input.getBusinessPhone(),
                metaData.getBusinessPhone()));

        input.setSubscriber(this.buildSubsciber(input.getSubscriber(), metaData
                .getSubscriber()));
        
        ///No data received for report Source
        //input.setReportSource();
        
        input.setInsurancePlan(this.buildInsurancePlan(
                input.getInsurancePlan(), metaData.getPlan())); 
        
        input.setReportSite(super.build(input.getReportSite(),
                metaData.getReportSite()));        
    }

    public static class PrivateInsuranceBuilder extends InsurancePolicyBuilder
    {
        /**
		 * An instance of serialVersionUID
		 */
		private static final long serialVersionUID = -6508537414864674678L;

		public PrivateInsurance build(PrivateInsuranceMetaData metaData)
                throws BuilderException
        {
            PrivateInsurance input = metaData.getEntity();
            PrivateInsurance output = (input == null) ? new PrivateInsurance()
                    : input;

            this.transfer(output, metaData);

            return this.shouldKeep(output) ? output : null;
        }

        private boolean shouldKeep(PrivateInsurance obj)
        {
            return (super.shouldKeep((InsurancePolicy) obj) && (obj
                    .getPolicyNumber() != null));
        }

        private void transfer(PrivateInsurance input,
                PrivateInsuranceMetaData metaData) throws BuilderException
        {
            super.transfer((InsurancePolicy) input, metaData);

            input.setCompanyName(super.build(input.getCompanyName(), metaData
                    .getCompanyName()));
            input.setGroupName(super.build(input.getGroupName(), metaData
                    .getGroupName()));
            input.setGroupNumber(super.build(input.getGroupNumber(), metaData
                    .getGroupNumber()));
            input.setPolicyEffectiveDate(super.build(input
                    .getPolicyEffectiveDate(), metaData.getEffectiveDate()));
            input.setPolicyExpirationDate(super.build(input
                    .getPolicyExpirationDate(), metaData.getExpirationDate()));
            input.setPolicyNumber(super.build(input.getPolicyNumber(), metaData
                    .getPolicyNumber()));
        }
    }

    public static class MedicareBuilder extends InsurancePolicyBuilder
    {
        /**
		 * An instance of serialVersionUID
		 */
		private static final long serialVersionUID = -2457859721723463485L;

		public Medicare build(MedicareMetaData metaData)
                throws BuilderException
        {
            Medicare input = metaData.getEntity();
            Medicare output = (input == null) ? new Medicare() : input;

            this.transfer(output, metaData);

            return this.shouldKeep(output) ? output : null;
        }

        private boolean shouldKeep(Medicare obj)
        {
            return (super.shouldKeep((InsurancePolicy) obj) && (obj
                    .getMedicareClaimNumber() != null));
        }

        private void transfer(Medicare input, MedicareMetaData metaData)
                throws BuilderException
        {
            super.transfer((InsurancePolicy) input, metaData);

            input.setEnrolledInPartA(super.build(input.isEnrolledInPartA(),
                    metaData.getEnrolledInPartA()));
            input.setEnrolledInPartB(super.build(input.isEnrolledInPartB(),
                    metaData.getEnrolledInPartB()));
            input.setMedicareClaimNumber(super.build(input
                    .getMedicareClaimNumber(), metaData
                    .getMedicareClaimNumber()));
            input
                    .setPartAEffectiveDate(super.build(input
                            .getPartAEffectiveDate(), metaData
                            .getPartAEffectiveDate()));
            input
                    .setPartBEffectiveDate(super.build(input
                            .getPartBEffectiveDate(), metaData
                            .getPartBEffectiveDate()));
        }
    }
}