/********************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.ui.demographic.action;

// Java Classes

// Library Classes

// Framework Classes

import java.util.Iterator;

import gov.va.med.fw.conversion.ConversionServiceException;
import gov.va.med.fw.util.StringUtils;

import gov.va.med.esr.common.infra.ImpreciseDate;
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.AddressType;
import gov.va.med.esr.common.model.lookup.InsurancePlanType;
import gov.va.med.esr.common.model.lookup.InsuranceReportSource;
import gov.va.med.esr.common.model.lookup.InsuredRelationship;
import gov.va.med.esr.common.model.lookup.PhoneType;
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;
import gov.va.med.esr.common.model.person.Person;

import gov.va.med.esr.ui.common.service.LookupCacheService;
import gov.va.med.esr.ui.common.util.DateUtils;
import gov.va.med.esr.ui.common.action.AddressConversionService;
import gov.va.med.esr.service.UnknownLookupTypeException;

/**
 * A UI specific implementation of the conversion service.
 *
 * @author Priya R.
 * @version 1.0
 */
public class InsuranceConversionService extends AddressConversionService
{
    /**
     * Default constructor.
     */
    public InsuranceConversionService()
    {
    }

    /**
     * Converts between a Person object that contains the addresses information and the DemographicAddressesForm.
     *
     * @param source the source object
     * @param target the target object
     *
     * @throws gov.va.med.fw.conversion.ConversionServiceException if any errors were encountered during the conversion.
     */
    protected void convertBean(Object source, Object target) throws ConversionServiceException
    {
        if (source instanceof Person && target instanceof InsuranceMedicareForm)
        {
            convertPersonToForm((Person)source, (InsuranceMedicareForm)target);
        }
        else
            if (source instanceof InsuranceMedicareForm && target instanceof Person)
            {
                convertFormToPerson((InsuranceMedicareForm)source, (Person)target);
            }
            else
                if (source instanceof InsurancePolicy && target instanceof InsuranceInfoForm)
                {
                    convertPolicyToForm((InsurancePolicy)source, (InsuranceInfoForm)target);
                }
                else
                    if (source instanceof InsuranceInfoForm && target instanceof InsurancePolicy)
                    {
                        convertFormToPolicy((InsuranceInfoForm)source, (InsurancePolicy)target);
                    }
                    else
                    {
                        throw new ConversionServiceException("Conversion is not supported from " +
                            source.getClass().getName() + " to " + target.getClass().getName());
                    }
    }

    /**
     * Converts the insurance data from the Person object to the form.
     *
     * @param policy The insurance policy
     * @param form The form
     *
     * @throws ConversionServiceException If there were any problems converting the person to the form.
     */
    protected void convertPolicyToForm(InsurancePolicy policy, InsuranceInfoForm form) throws ConversionServiceException
    {
        try
        { 
            Person person=policy.getPerson();
            form.setGroupName(policy.getGroupName());
            form.setGroupNumber(policy.getGroupNumber());
            if(person.getDeathRecord() !=null && person.getDeathRecord().getDeathDate()!=null){
                String dod=DateUtils.format(person.getDeathRecord().getDeathDate(), null);
                form.setDateOfDeath(dod);
            }
            if(person.getBirthRecord() !=null && person.getBirthRecord().getBirthDate()!=null){
                  String dob=DateUtils.format(person.getBirthRecord().getBirthDate(), null);
                  form.setDateOfBirth(dob);
            }
            if (policy instanceof PrivateInsurance)
            {
                PrivateInsurance pIns = (PrivateInsurance)policy;
                form.setMedicareInd(false);
                form.setInsCompanyName(pIns.getCompanyName());
                form.setPolicyNumber(pIns.getPolicyNumber());
                if (pIns.getPolicyEffectiveDate() != null)
                    form.setEffDate(DateUtils.format(pIns.getPolicyEffectiveDate(), null));
                if (pIns.getPolicyExpirationDate() != null)
                    form.setExpDate(DateUtils.formatForEdit(pIns.getPolicyExpirationDate(), null));

                //type of plan
                InsurancePlan plan = policy.getInsurancePlan();
                if (plan != null)
                {
                    form.setTypeOfIns(plan.getPlanType().getCode());

                    if (plan.getPrecertificationRequired() != null)
                    {
                        if (Boolean.TRUE.equals(plan.getPrecertificationRequired()))
                            form.setPrecertReq(InsuranceInfoForm.Y);
                        else
                            form.setPrecertReq(InsuranceInfoForm.N);
                    }

                }

                //subscriber
                InsuranceSubscriber subscriber = policy.getSubscriber();
                if (subscriber != null)
                {
                    form.setNameOfInsured(subscriber.getName());
                    if (subscriber.getRelationship() != null)
                    {
                        form.setRelationshipToVeteran(subscriber.getRelationship().getCode());
                    }
                }
            }

            if (policy instanceof Medicare)
            {
                Medicare mpolicy = (Medicare)policy;

                form.setMedicareInd(true);
                form.setInsCompanyName("Medicare");
                form.setNameOnMedicareCard(mpolicy.getNameOnMedicareCard());
                form.setMedicareClaimNbr(mpolicy.getMedicareClaimNumber());

                //Check for A and B first
                if (Boolean.TRUE.equals(mpolicy.getEnrolledInPartA()) &&
                    Boolean.TRUE.equals(mpolicy.getEnrolledInPartB()))
                {

                    form.setIsEnrolledInPartA(InsuranceInfoForm.Y);
                    form.setIsEnrolledInPartB(InsuranceInfoForm.Y);
                    form.setTypeOfMedicare(InsuranceInfoForm.PartAB);
                }//A only
                else
                    if (Boolean.TRUE.equals(mpolicy.getEnrolledInPartA()))
                    {
                        form.setIsEnrolledInPartA(InsuranceInfoForm.Y);
                        form.setTypeOfMedicare(InsuranceInfoForm.PartA);
                        form.setIsEnrolledInPartB(InsuranceInfoForm.N);
                    }//B Only (not possible with the current requirements)
                    else
                        if (Boolean.TRUE.equals(mpolicy.getEnrolledInPartB()))
                        {
                            form.setIsEnrolledInPartA(InsuranceInfoForm.N);
                            form.setIsEnrolledInPartB(InsuranceInfoForm.Y);
                            form.setTypeOfMedicare(InsuranceInfoForm.PartB);
                        }
                        else //Another data error (it should A or A and B)
                        {
                            form.setIsEnrolledInPartA(InsuranceInfoForm.N);
                            form.setIsEnrolledInPartB(InsuranceInfoForm.N);
                            form.setTypeOfMedicare(null);
                        }

                //use default format for dates
                if (mpolicy!=null && mpolicy.getPartAEffectiveDate()!= null)
                    form.setPartAEffectiveDate(DateUtils.format(mpolicy.getPartAEffectiveDate(), null));
                if (mpolicy!=null && mpolicy.getPartBEffectiveDate()!= null)
                    form.setPartBEffectiveDate(DateUtils.format(mpolicy.getPartBEffectiveDate(), null));
                
              //  form.setPartAEffectiveDate(DateUtils.format(mpolicy.getPartAEffectiveDate(), null));
               // form.setPartBEffectiveDate(DateUtils.format(mpolicy.getPartBEffectiveDate(), null));
            }

            // Get the address methods
            Address address = policy.getAddress();

            // Convert the standard address fields
            convertAddressToForm(address, form);

            Phone preCertificationPhone = policy.getPreCertificationPhone();
            form.setPreCertificationPhone(preCertificationPhone == null ? null : preCertificationPhone.getFormattedPhone());
            Phone phoneNbr = policy.getBusinessPhone();
            form.setPhone(phoneNbr == null ? null : phoneNbr.getFormattedPhone());
            Phone faxNbr = policy.getFax();
            form.setFax(faxNbr == null ? null : faxNbr.getFormattedPhone());

            if (policy.getReportSource() != null)
                form.setSourceOfUpdate(policy.getReportSource().getCode());

        }
        catch (Exception ex)
        {
            throw new ConversionServiceException("Unable to convert policy to InsuranceInfoForm.", ex);
        }
    }

    /**
     * Converts the form data to the Person object.
     *
     * @param form The form
     * @param policy The Insurance policy
     *
     * @throws ConversionServiceException If there were any problems converting the form to the person.
     */
    protected void convertFormToPolicy(InsuranceInfoForm form, InsurancePolicy policy) throws ConversionServiceException
    {
        LookupCacheService lookupCacheService = getLookupCacheService();

        try
        {
            policy.setGroupName(StringUtils.isEmpty(form.getGroupName()) ? null : form.getGroupName());
            policy.setGroupNumber(StringUtils.isEmpty(form.getGroupNumber()) ? null : form.getGroupNumber());

            //set the report site to be HEC
            policy.setReportSite((VAFacility)lookupCacheService.getByCodeFromCache(
                VAFacility.class, VAFacility.CODE_HEC.getName()));

            //set report source
            policy.setReportSource((InsuranceReportSource)lookupCacheService.getByCodeFromCache(
                InsuranceReportSource.class, form.getSourceOfUpdate()));


            if (policy instanceof PrivateInsurance)
            {
                PrivateInsurance pIns = (PrivateInsurance)policy;

                pIns.setCompanyName(form.getInsCompanyName());
                pIns.setPolicyNumber(form.getPolicyNumber());              
                pIns.setPolicyEffectiveDate(DateUtils.getImpreciseDate(form.getEffDate(), false, true));
                
                // DOD
                // Time portion can be displayed (if it came from messaging), but can not be saved by the user.
                // So create an imprecise date with the time omitted.
                String formExpDate = form.getExpDate();            
                ImpreciseDate dateWithTime = DateUtils.getImpreciseDate(formExpDate, true, true);
                if(dateWithTime!=null)
                {
                    String impreciseString = dateWithTime.toStandardFormat();
                    if (impreciseString.length() > 8) {
                         if(!dateWithTime.equals(pIns.getPolicyExpirationDate())) {
                           	impreciseString = impreciseString.substring(0, 8);
                           	ImpreciseDate dateWithoutTime = new ImpreciseDate(impreciseString);
                           	pIns.setPolicyExpirationDate(dateWithoutTime);
                         }
                   	}
                    else{
                        pIns.setPolicyExpirationDate(dateWithTime); 
                    }
                }else {
                    pIns.setPolicyExpirationDate(dateWithTime); 
                }
           

                //type of plan
                if (StringUtils.isEmpty(form.getTypeOfIns()))
                {
                    policy.setInsurancePlan(null);
                }
                else
                {
                    InsurancePlan plan = policy.getInsurancePlan();
                    if (plan == null)
                    {
                        plan = new InsurancePlan();
                        if (StringUtils.isNotEmpty(form.getPrecertReq()))
                        {
                            if (StringUtils.equals(form.getPrecertReq(), InsuranceInfoForm.Y))
                                plan.setPrecertificationRequired(Boolean.TRUE);
                            else
                                plan.setPrecertificationRequired(Boolean.FALSE);
                        }
                        policy.setInsurancePlan(plan);
                    }
                    plan.setPlanType((InsurancePlanType)lookupCacheService.getByCodeFromCache(
                        InsurancePlanType.class, form.getTypeOfIns()));
                }

                // Subscriber
                if (StringUtils.isEmpty(form.getNameOfInsured()) && StringUtils.isEmpty(form.getRelationshipToVeteran()))
                {
                    policy.setSubscriber(null);
                }
                else
                {
                    InsuranceSubscriber subscriber = getSubscriber(policy);
                    subscriber.setName(StringUtils.isEmpty(form.getNameOfInsured()) ? null : form.getNameOfInsured());
                    setRelationshipToVeteran(subscriber, form.getRelationshipToVeteran());
                }
            }

            if (policy instanceof Medicare)
            {
                Medicare mpolicy = (Medicare)policy;

                mpolicy.setNameOnMedicareCard(form.getNameOnMedicareCard());
                mpolicy.setMedicareClaimNumber(form.getMedicareClaimNbr());

                if (StringUtils.isNotEmpty(form.getTypeOfMedicare()))
                {
                    if (StringUtils.equals(form.getTypeOfMedicare(), InsuranceInfoForm.PartA))
                    {
                        mpolicy.setEnrolledInPartA(Boolean.TRUE);
                        mpolicy.setEnrolledInPartB(Boolean.FALSE);
                    }
                    else
                        if (StringUtils.equals(form.getTypeOfMedicare(), InsuranceInfoForm.PartB))
                        {
                            mpolicy.setEnrolledInPartB(Boolean.TRUE);
                            mpolicy.setEnrolledInPartA(Boolean.FALSE);
                        }
                        else
                            if (StringUtils.equals(form.getTypeOfMedicare(), InsuranceInfoForm.PartAB))
                            {
                                mpolicy.setEnrolledInPartA(Boolean.TRUE);
                                mpolicy.setEnrolledInPartB(Boolean.TRUE);
                            }
                }
                else
                {
                    mpolicy.setEnrolledInPartA(Boolean.FALSE);
                    mpolicy.setEnrolledInPartB(Boolean.FALSE);
                }

                if (mpolicy!=null && mpolicy.getPartAEffectiveDate()!= null)
                    form.setPartAEffectiveDate(DateUtils.format(mpolicy.getPartAEffectiveDate(), null));
                if (mpolicy!=null && mpolicy.getPartBEffectiveDate()!= null)
                    form.setPartBEffectiveDate(DateUtils.format(mpolicy.getPartBEffectiveDate(), null));
                
              //  mpolicy.setPartAEffectiveDate(DateUtils.getDate(form.getPartAEffectiveDate()));
              //  mpolicy.setPartBEffectiveDate(DateUtils.getDate(form.getPartBEffectiveDate()));
            }

            if (form.isAnyAddressFieldFilled())
            {
                // Get the address methods
                Address address = policy.getAddress();
                if (address == null)
                {
                    address = new Address();
                    AddressType type = (AddressType)lookupCacheService.getByCodeFromCache(
                        AddressType.class, AddressType.CODE_BUSINESS_ADDRESS.getName());
                    address.setType(type);
                    policy.setAddress(address);
                }

                // Convert the standard address fields
                convertFormToAddress(form, address);
            }
            else
            {
                // If no address fields are filled, remove the address object
                policy.setAddress(null);
            }

            if (StringUtils.isNotEmpty(form.getPreCertificationPhone()))
            {
                Phone preCertificationPhone = policy.getPreCertificationPhone();
                if (preCertificationPhone == null)
                {
                    preCertificationPhone = new Phone();
                    preCertificationPhone.setType((PhoneType)lookupCacheService.getByCodeFromCache(
                        PhoneType.class, PhoneType.CODE_PRE_CERTIFICATION_PHONE.getName()));
                    policy.setPreCertificationPhone(preCertificationPhone);
                }
                preCertificationPhone.setPhoneNumber(Phone.getFormattedPhone(form.getPreCertificationPhone()));
            }
            else
            {
                policy.setPreCertificationPhone(null);
            }

            if (StringUtils.isNotEmpty(form.getPhone()))
            {
                Phone phoneNbr = policy.getBusinessPhone();
                if (phoneNbr == null)
                {
                    phoneNbr = new Phone();
                    phoneNbr.setType((PhoneType)lookupCacheService.getByCodeFromCache(
                        PhoneType.class, PhoneType.CODE_BUSINESS.getName()));

                    policy.setBusinessPhone(phoneNbr);
                }
                phoneNbr.setPhoneNumber(Phone.getFormattedPhone(form.getPhone()));
            }
            else
            {
                policy.setBusinessPhone(null);
            }

            if (StringUtils.isNotEmpty(form.getFax()))
            {
                Phone faxNbr = policy.getFax();
                if (faxNbr == null)
                {
                    faxNbr = new Phone();
                    faxNbr.setType((PhoneType)lookupCacheService.getByCodeFromCache(
                        PhoneType.class, PhoneType.CODE_FAX.getName()));

                    policy.setFax(faxNbr);
                }
                faxNbr.setPhoneNumber(Phone.getFormattedPhone(form.getFax()));
            }
            else
            {
                policy.setFax(null);
            }
        }
        catch (Exception ex)
        {
            throw new ConversionServiceException("Unable to convert InsuranceInfoForm to Policy.", ex);
        }
    }

    //Medicare conversion only
    protected void convertPersonToForm(Person person, InsuranceMedicareForm form) throws ConversionServiceException
    {
        Medicare partA = null;
        Medicare partB = null;

        //Get Medicare policies
        if(person !=null && person.getBirthRecord() !=null && person.getBirthRecord().getBirthDate() !=null){ // ccr10388
        	String dob=DateUtils.format(person.getBirthRecord().getBirthDate(), null);////ccr9799,9800;
        	form.setDateOfBirth(dob);
        }
        if(person !=null && person.getDeathRecord() !=null && person.getDeathRecord().getDeathDate() !=null){  // ccr10388
        	String dod=DateUtils.format(person.getDeathRecord().getDeathDate(), null);////ccr10116
        	form.setDateOfDeath(dod);
        }
        Iterator iter = person.getInsurances().iterator();
        while (iter.hasNext())
        {
            InsurancePolicy insPolicy = (InsurancePolicy)iter.next();

            //Ignore the policies from other sites
            if (insPolicy instanceof Medicare &&
                (insPolicy.getReportSite() == null ||
                    VAFacility.CODE_HEC.getName().equals(
                        insPolicy.getReportSite().getStationNumber())))
            {
                Medicare medicare = (Medicare)insPolicy;

                if (medicare.isEnrolledInPartB() != null &&
                    Boolean.TRUE.equals(medicare.isEnrolledInPartB()))
                {
                    partB = medicare;
                }
                else
                    if (medicare.isEnrolledInPartA() != null &&
                        Boolean.TRUE.equals(medicare.isEnrolledInPartA()))
                    {
                        partA = medicare;
                    }
                    else
                    {
                        //Erronious medicare policy
                        throw new ConversionServiceException("Medicare Insurance found without Part A or B indicators");
                    }
            }
        }
        //type of medicare
        form.setTypeOfMedicare(partB == null ? InsuranceMedicareForm.PartA : InsuranceMedicareForm.PartAB);

        //Convert Part A
        if (partA != null)
        {
            form.setInsuranceId(partA.getEntityKey()!=null?partA.getEntityKey().getKeyValueAsString():"");
            form.setGroupName(partA.getGroupName());
            form.setGroupNumber(partA.getGroupNumber());
            form.setNameOnMedicareCard(partA.getNameOnMedicareCard());
            form.setMedicareClaimNbr(partA.getMedicareClaimNumber());
            form.setPartAEffectiveDate(DateUtils.format(partA.getPartAEffectiveDate(), null));
            Phone phoneNbr = partA.getBusinessPhone();
            form.setPhone(phoneNbr == null ? null : phoneNbr.getFormattedPhone());
            Phone faxNbr = partA.getFax();
            form.setFax(faxNbr == null ? null : faxNbr.getFormattedPhone());
            InsuranceReportSource reportSource = partA.getReportSource();
            form.setSourceOfUpdate(reportSource == null ? null : reportSource.getCode());

            // Get the address methods
            Address address = partA.getAddress();

            // Convert the standard address fields
            convertAddressToForm(address, form);
        }

        //Convert Part B
        if (partB != null)
        {
            form.setPartBInsuranceId(partB.getEntityKey()!=null?partB.getEntityKey().getKeyValueAsString():"");
            form.setPartBGroupName(partB.getGroupName());
            form.setPartBGroupNumber(partB.getGroupNumber());
            form.setPartBNameOnMedicareCard(partB.getNameOnMedicareCard());
            form.setPartBMedicareClaimNbr(partB.getMedicareClaimNumber());
            form.setPartBEffectiveDate(DateUtils.format(partB.getPartBEffectiveDate(), null));
            Phone phoneNbr = partB.getBusinessPhone();
            form.setPartBPhone(phoneNbr == null ? null : phoneNbr.getFormattedPhone());
            Phone faxNbr = partB.getFax();
            form.setPartBFax(faxNbr == null ? null : faxNbr.getFormattedPhone());
            InsuranceReportSource reportSource = partB.getReportSource();
            form.setPartBSourceOfUpdate(reportSource == null ? null : reportSource.getCode());

            // Get the address and convert
            Address address = partB.getAddress();
            convertSecondAddressToForm(address, form);
        }


    }

    protected void convertFormToPerson(InsuranceMedicareForm form, Person person) throws ConversionServiceException
    {
        LookupCacheService lookupCacheService = getLookupCacheService();
        try
        {
            Medicare partA = null;
            Medicare partB = null;

            //TODO code is duplicated move to a function
            //Get Medicare policies
            Iterator iter = person.getInsurances().iterator();

            while (iter.hasNext())
            {
                InsurancePolicy insPolicy = (InsurancePolicy)iter.next();

                //Ignore the policies from other sites
                if (insPolicy instanceof Medicare &&
                    (insPolicy.getReportSite() == null ||
                        VAFacility.CODE_HEC.getName().equals(
                            insPolicy.getReportSite().getStationNumber())))
                {
                    Medicare medicare = (Medicare)insPolicy;
                    if (medicare.isEnrolledInPartB() != null &&
                        Boolean.TRUE.equals(medicare.isEnrolledInPartB()))
                    {
                        partB = medicare;
                    }
                    else
                        if (medicare.isEnrolledInPartA() != null &&
                            Boolean.TRUE.equals(medicare.isEnrolledInPartA()))
                        {
                            partA = medicare;
                        }
                        else
                        {
                            //Erronious medicare policy
                            throw new ConversionServiceException("Medicare Insurance found with Part A or B indicators");
                        }
                }
            }

            //Convert Part A Id is not used as there can be only one medicare plan
            if (partA == null)
            {
                partA = new Medicare();
                person.addInsurance(partA);
            }
            else
            {
                //Match the Identifier values
                if (partA.getEntityKey()!=null && !StringUtils.equals(form.getInsuranceId(),
                    partA.getEntityKey().getKeyValueAsString()))
                {
                    //Non Matching Keys
                    log.error("Medicare partA key in the database is different from the one being edited");
                        //Commented out to resolve Fortify High Finding Log Forging
                    	// +
                        //"db Key " + partA.getEntityKey().getKeyValueAsString() 
                        //+ " ui Key " + form.getInsuranceId());
                    //As system will throw optimistic lock exception, no exception is raised
                }
            }

            //Update Part A
            partA.setCompanyName(form.getInsCompanyName());
            partA.setGroupName(form.getGroupName());
            partA.setGroupNumber(form.getGroupNumber());

            //set the report site to be HEC
            partA.setReportSite((VAFacility)lookupCacheService.getByCodeFromCache(
                VAFacility.class, VAFacility.CODE_HEC.getName()));

            //set report source
            partA.setReportSource((InsuranceReportSource)lookupCacheService.getByCodeFromCache(
                InsuranceReportSource.class, form.getSourceOfUpdate()));

            partA.setNameOnMedicareCard(form.getNameOnMedicareCard());
            partA.setMedicareClaimNumber(form.getMedicareClaimNbr());
            partA.setEnrolledInPartA(Boolean.TRUE);
            partA.setEnrolledInPartB(Boolean.FALSE);
            partA.setPartAEffectiveDate(DateUtils.getImpreciseDate(form.getPartAEffectiveDate(), false, true));
           // partA.setPartAEffectiveDate(DateUtils.getDate(form.getPartAEffectiveDate()));
            partA.setPartBEffectiveDate(null);

            Phone phoneNbr = partA.getBusinessPhone();
            if (StringUtils.isNotEmpty(form.getPhone()))
            {
                if (phoneNbr == null)
                {
                    phoneNbr = new Phone();
                    phoneNbr.setType((PhoneType)lookupCacheService.getByCodeFromCache(
                        PhoneType.class, PhoneType.CODE_BUSINESS.getName()));

                    partA.setBusinessPhone(phoneNbr);
                }
                phoneNbr.setPhoneNumber(Phone.getFormattedPhone(form.getPhone()));
            }
            else
            {
                partA.setBusinessPhone(null);
            }

            Phone faxNbr = partA.getFax();
            if (StringUtils.isNotEmpty(form.getFax()))
            {
                if (faxNbr == null)
                {
                    faxNbr = new Phone();
                    faxNbr.setType((PhoneType)lookupCacheService.getByCodeFromCache(
                        PhoneType.class, PhoneType.CODE_FAX.getName()));

                    partA.setFax(faxNbr);
                }
                faxNbr.setPhoneNumber(Phone.getFormattedPhone(form.getFax()));
            }
            else
            {
                partA.setFax(null);
            }

            if (form.isAnyAddressFieldFilled())
            {
                // Get the address methods
                Address address = partA.getAddress();
                if (address == null)
                {
                    address = new Address();
                    partA.setAddress(address);
                }
                // Convert the standard address fields
                convertFormToAddress(form, address);
            }
            else
            {
                // If no address fields are filled, remove the address object
                partA.setAddress(null);
            }

            // Default the relationship
            InsuranceSubscriber subscriber = getSubscriber(partA);
            setRelationshipToVeteran(subscriber, null);

            // Part B
            if (InsuranceMedicareForm.PartAB.equals(form.getTypeOfMedicare()))
            {
                // Convert Part B
                if (partB == null)
                {
                    partB = new Medicare();
                    person.addInsurance(partB);
                }
                else
                {
                    //Match the Identifier values
                    if (partB.getEntityKey()!=null && !StringUtils.equals(form.getPartBInsuranceId(),
                        partB.getEntityKey().getKeyValueAsString()))
                    {
                        //Non Matching Keys
                        log.error("Medicare partB key in the database is different from the one being edited");// +
                            //"db Key " + partB.getEntityKey().getKeyValueAsString() + " ui Key " + form.getPartBInsuranceId());
                        //As system will throw optimistic lock exception, no excetion is raised
                    }

                }

                partB.setCompanyName(form.getInsCompanyName());
                partB.setGroupName(form.getPartBGroupName());
                partB.setGroupNumber(form.getPartBGroupNumber());

                //set the report site to be HEC
                partB.setReportSite((VAFacility)lookupCacheService.getByCodeFromCache(
                    VAFacility.class, VAFacility.CODE_HEC.getName()));

                //set report source
                partB.setReportSource((InsuranceReportSource)lookupCacheService.getByCodeFromCache(
                    InsuranceReportSource.class, form.getPartBSourceOfUpdate()));

                partB.setNameOnMedicareCard(form.getPartBNameOnMedicareCard());
                partB.setMedicareClaimNumber(form.getPartBMedicareClaimNbr());
                //TODO part A indicator is set to true as rules looks into this one
                //to verify the existance of Part A
                partB.setEnrolledInPartA(Boolean.TRUE);
                partB.setEnrolledInPartB(Boolean.TRUE);
                partB.setPartAEffectiveDate(null);
                /*Defect294787-Medicare-part A and B -copy A for B -update –data will be shown - REEG_00012084*/
                partB.setPartBEffectiveDate(DateUtils.getImpreciseDate(form.getPartBEffectiveDate(), false, true));
               // partB.setPartBEffectiveDate(DateUtils.getDate(form.getPartBEffectiveDate()));

                phoneNbr = partB.getBusinessPhone();
                if (StringUtils.isNotEmpty(form.getPartBPhone()))
                {
                    if (phoneNbr == null)
                    {
                        phoneNbr = new Phone();
                        phoneNbr.setType((PhoneType)lookupCacheService.getByCodeFromCache(
                            PhoneType.class, PhoneType.CODE_BUSINESS.getName()));

                        partB.setBusinessPhone(phoneNbr);
                    }
                    phoneNbr.setPhoneNumber(Phone.getFormattedPhone(form.getPartBPhone()));
                }
                else
                {
                    partB.setBusinessPhone(null);
                }


                faxNbr = partB.getFax();
                if (StringUtils.isNotEmpty(form.getPartBFax()))
                {
                    if (faxNbr == null)
                    {
                        faxNbr = new Phone();
                        faxNbr.setType((PhoneType)lookupCacheService.getByCodeFromCache(
                            PhoneType.class, PhoneType.CODE_FAX.getName()));

                        partB.setFax(faxNbr);
                    }
                    faxNbr.setPhoneNumber(Phone.getFormattedPhone(form.getPartBFax()));
                }
                else
                {
                    partB.setFax(null);
                }

                if (form.isAnyAddress2FieldFilled())
                {
                    // Get the address methods
                    Address address = partB.getAddress();
                    if (address == null)
                    {
                        address = new Address();
                        partB.setAddress(address);
                    }
                    // Convert the standard address fields
                    convertFormToSecondAddress(form, address);
                }
                else
                {
                    // If no address fields are filled remove the object
                    partB.setAddress(null);
                }

                // Default the relationship
                subscriber = getSubscriber(partB);
                setRelationshipToVeteran(subscriber, null);
            }
            else
            {
                //TODO we are supporting the deletion of part B alone here
                //if Part B exists delete
                if (partB != null)
                {
                    person.removeInsurance(partB);
                }
            }

        }
        catch (Exception ex)
        {
            throw new ConversionServiceException("Conversion Failed");
        }
    }

    protected void convertSecondAddressToForm(Address address, InsuranceMedicareForm form)
    {
        if (address != null)
        {
            // Convert the standard fields
            form.setAddressLine12(address.getLine1());
            form.setAddressLine22(address.getLine2());
            form.setAddressLine32(address.getLine3());
            if (address.getCountry() != null)
            {
                form.setCountry2(address.getCountry());
            }

            form.setCity2(address.getCity());
            form.setState2(address.getState());
            form.setCounty2(address.getCounty());
            form.setPrevZip2(address.getZipCode());
            form.setZipCode2(address.getZipCode());
            form.setZipPlus42(address.getZipPlus4());
        }
    }

    /**
     * Sets the relationship to veteran.  If the relationship is blank, it will be defaulted to "patient".
     *
     * @param subscriber The subscriber
     * @param relationshipCode The relationship code,.
     *
     * @throws UnknownLookupTypeException
     * @throws ClassNotFoundException
     */
    protected void setRelationshipToVeteran(InsuranceSubscriber subscriber, String relationshipCode)
        throws UnknownLookupTypeException, ClassNotFoundException
    {
        if (StringUtils.isBlank(relationshipCode))
        {
            relationshipCode = InsuredRelationship.CODE_VETERAN.getName();
        }
        subscriber.setRelationship((InsuredRelationship)getLookupCacheService().getByCodeFromCache(
            InsuredRelationship.class, relationshipCode));
    }

    /**
     * Gets the insurance subscriber and creates a new one if one has not yet been created.
     *
     * @param policy The insurance policy.
     *
     * @return The subscriber
     */
    protected InsuranceSubscriber getSubscriber(InsurancePolicy policy)
    {
        InsuranceSubscriber subscriber = policy.getSubscriber();
        if (subscriber == null)
        {
            subscriber = new InsuranceSubscriber();
            policy.setSubscriber(subscriber);
        }
        return subscriber;
    }

    /**
     * Converts the address form data onto the address object.
     *
     * @param form The form
     * @param address The address
     */
    protected void convertFormToSecondAddress(InsuranceMedicareForm form, Address address)
    {
        // Convert the standard fields
        address.setCountry(StringUtils.isBlank(form.getCountry2()) ? null : form.getCountry2());
        address.setLine1(StringUtils.isBlank(form.getAddressLine12()) ? null : form.getAddressLine12());
        address.setLine2(StringUtils.isBlank(form.getAddressLine22()) ? null : form.getAddressLine22());
        address.setLine3(StringUtils.isBlank(form.getAddressLine32()) ? null : form.getAddressLine32());
        address.setCity(StringUtils.isBlank(form.getCity2()) ? null : form.getCity2());

        // Convert US and non-US specific fields and null out the fields that don't apply
        if (form.isUSAddress())
        {
            address.setCounty(StringUtils.isBlank(form.getCounty2()) ? null : form.getCounty2());
            address.setState(StringUtils.isBlank(form.getState2()) ? null : form.getState2());
            address.setZipCode(StringUtils.isBlank(form.getZipCode2()) ? null : form.getZipCode2());
            address.setZipPlus4(StringUtils.isBlank(form.getZipPlus42()) ? null : form.getZipPlus42());
            address.setProvince(null);
            address.setPostalCode(null);
        }
        else
        {
            address.setCounty(null);
            address.setState(null);
            address.setZipCode(null);
            address.setZipPlus4(null);
            address.setProvince(StringUtils.isBlank(form.getProvince2()) ? null : form.getProvince2());
            address.setPostalCode(StringUtils.isBlank(form.getPostalCode2()) ? null : form.getPostalCode2());
        }
    }
}