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

// Java Classes

// Library Classes

// Framework Classes
import gov.va.med.esr.common.model.financials.DependentFinancials;
import gov.va.med.esr.common.model.financials.FinancialInformation;
import gov.va.med.esr.common.model.financials.FinancialStatement;
import gov.va.med.esr.common.model.financials.SpouseFinancials;
import gov.va.med.esr.common.model.lookup.Country;
import gov.va.med.esr.common.model.lookup.EmploymentStatus;
import gov.va.med.esr.common.model.lookup.Gender;
import gov.va.med.esr.common.model.lookup.NameType;
import gov.va.med.esr.common.model.lookup.PseudoSSNReason;
import gov.va.med.esr.common.model.lookup.Relationship;
import gov.va.med.esr.common.model.lookup.SSAVerificationStatus;
import gov.va.med.esr.common.model.lookup.SSNChangeSource;
import gov.va.med.esr.common.model.lookup.SSNType;
import gov.va.med.esr.common.model.party.Address;
import gov.va.med.esr.common.model.person.Dependent;
import gov.va.med.esr.common.model.person.Employment;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.Relation;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.common.model.person.Spouse;
import gov.va.med.esr.common.ui.form.DependentFinancialInfoBean;
import gov.va.med.esr.common.ui.form.RelationFinancialInfoBean;
import gov.va.med.esr.common.ui.form.SpouseFinancialInfoBean;
import gov.va.med.esr.common.ui.conversion.CommonFinancialsDependentConversionService;
import gov.va.med.esr.service.UnknownLookupTypeException;
import gov.va.med.esr.ui.common.service.LookupCacheService;
import gov.va.med.esr.ui.common.util.DateUtils;
import gov.va.med.esr.ui.conversion.UIConversionServiceImpl;
import gov.va.med.fw.conversion.ConversionServiceException;
import gov.va.med.fw.util.StringUtils;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import gov.va.med.esr.ui.common.action.AddressConversionService;
import gov.va.med.esr.ui.common.action.AddressForm;
/**
 * A UI specific implementation of the conversion service.
 * 
 * @author Priya R.
 * @version 1.0
 */
// public class FinancialsDependentConversionService extends UIConversionServiceImpl {
public class FinancialsDependentConversionService extends AddressConversionService {

    private CommonFinancialsDependentConversionService commonDependentConversionService;
    
    private final static Map relationGender = new HashMap();
    static {
        relationGender.put(Relationship.CODE_SON.getCode(), Gender.MALE.getName());
        relationGender.put(Relationship.CODE_STEPSON.getCode(), Gender.MALE.getName());
        relationGender.put(Relationship.CODE_DAUGHTER.getCode(), Gender.FEMALE.getName());
        relationGender.put(Relationship.CODE_STEPDAUGHTER.getCode(), Gender.FEMALE.getName());        
    }

    /**
     * Default constructor.
     */
    public FinancialsDependentConversionService() {}

    /**
     * Converts between a Person object that contains the financial information
     * and the FinancialDetailsForm.
     * 
     * @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 {
        FinancialsDependentForm form = null;
    
        if (source instanceof FinancialInformation) {
            // person = (Person)source;
            if (target instanceof FinancialsDependentForm) {
                form = (FinancialsDependentForm) target;
                if (source instanceof SpouseFinancials) {
	            	boolean isAddAPerson = form.isAddAPerson();
	                SpouseFinancials finInfo = (SpouseFinancials) source;
	                SpouseFinancialInfoBean sInfoBean = new SpouseFinancialInfoBean(); 
	                sInfoBean.setAddAPerson(isAddAPerson);
	                getCommonDependentConversionService().convertSpouseFinancialsToBean(finInfo, sInfoBean);
	                form.setSpouseInfo(sInfoBean);
	                form.setSpouseInd(true);
	                
	                System.out.println("FinancialsDependentConversionService source spouseFinancial target DependentForm isAddAPerson="+isAddAPerson);
	                if (isAddAPerson){
	                	Spouse spouse = finInfo.getReportedOn();
	                	if (spouse != null ){
	                		Employment employment = spouse.getEmployment();
	                		if (employment!=null){
	                			Address address = employment.getEmployerAddress();
	                			if (address!=null)
	                				convertAddressToForm(address, form);
	                		}
	                	}
                    }
                }else if (source instanceof DependentFinancials) {
                    DependentFinancials finInfo = (DependentFinancials) source;
                    DependentFinancialInfoBean dInfoBean = new DependentFinancialInfoBean();
                    getCommonDependentConversionService().convertDependentFinancialsToBean(finInfo, dInfoBean);
                    form.setDependentInfo(dInfoBean);
                    form.setSpouseInd(false);
                }
            } else {
                throw new ConversionServiceException("Target object is of type "
                        + target.getClass().getName() + " and must be of type FinancialsDependentForm.");
            }
        } else {
            if (source instanceof FinancialsDependentForm) {
                try {
                    form = (FinancialsDependentForm) source;
                    if (target instanceof SpouseFinancials) {
                        SpouseFinancials finInfo = (SpouseFinancials) target;
                        
                        // add a person
                        boolean isAddAPerson = form.isAddAPerson();
                        SpouseFinancialInfoBean sinfoBean = form.getSpouseInfo();
                        if (sinfoBean == null)
                        	sinfoBean = new SpouseFinancialInfoBean();
                        sinfoBean.setAddAPerson(isAddAPerson);
                        
                        // convertBeanToSpouseFinancials(form.getSpouseInfo(), finInfo);
                        convertBeanToSpouseFinancials(sinfoBean, finInfo);
                        
                        System.out.println("FinancialsDependentConversionService source DependentForm target spouseFinancial isAddAPerson="+isAddAPerson);
                        if (isAddAPerson){
                        	Spouse spouse = finInfo.getReportedOn();
                        	Employment employment = spouse.getEmployment();
                        	if (employment == null ){
                        		employment = new Employment();
                        		spouse.setEmployment(employment);
                        	}
                        	if (form.isAnyAddressFieldFilled()){	
                        		Address address = employment.getEmployerAddress();
                        		if(address == null){
                        			address = new Address();
                        			employment.setEmployerAddress(address);
                        		}
                        		convertFormToAddress(form,address);	
                        	}
                        	else
                        		employment.setEmployerAddress(null);
                        }   
                    } else if (target instanceof DependentFinancials) {
                        DependentFinancials finInfo = (DependentFinancials) target;
                        convertBeanToDependentFinancials(form.getDependentInfo(), finInfo);
                    } else {
                        throw new ConversionServiceException("Target object is of type "
                                + target.getClass().getName() + " and must be of type FinancialInformation.");
                    }
                } catch (Exception ex) {
                    throw new ConversionServiceException(
                            "Unable to convert FinancialsDependentForm to Person.", ex);
                }
            
            } else {
                throw new ConversionServiceException("Source object is of type "
                        + target.getClass().getName()
                        + " and must be of type Person or FinancialsDependentForm.");
            }
        }
    }
     public void convertBeanToSpouseFinancials(SpouseFinancialInfoBean bean, SpouseFinancials spFins)
            throws Exception {

        FinancialStatement statement = null;
        spFins.setLivedWithPatient(getBoolean(bean.getLivedWithVeteran()));
        //spFins.setValidDependent(getBoolean(bean.getValidDependent()));

        // contributed to spouse support indicator. Since we are allowing to unselect radio button the value will always be set.
        statement = spFins.getFinancialStatement();
        if (statement != null)
        {
            statement.setContributedToSpouseInd(getBoolean(bean.getContributedToSpouseInd()));    
        }        
        
        // spousal support amt
        if (StringUtils.isNotEmpty(bean.getContributedToSupport())) {            
            if (statement != null)
                statement.setContributionToSpouse(new BigDecimal(bean.getContributedToSupport()));
        } else {            
            if (statement != null)
                statement.setContributionToSpouse(null);
        }

        Spouse spouse = spFins.getReportedOn();
        if (spouse == null) {
            spouse = new Spouse();
            spFins.setReportedOn(spouse);
        }
        convertBeanToRelation(bean, spouse);

    }

    public void convertBeanToDependentFinancials(DependentFinancialInfoBean bean, DependentFinancials depFins)
            throws Exception {
        depFins.setValidDependent(getBoolean(bean.getValidDependent()));
        depFins.setLivedWithPatient(getBoolean(bean.getLivedWithVeteran()));
        depFins.setIncapableOfSelfSupport(getBoolean(bean.getIncapableOfSelfSupport()));
        depFins.setHasIncome(getBoolean(bean.getHasIncome()));
        depFins.setContributedToSupport(getBoolean(bean.getContributedToSupport()));
        depFins.setAttendedSchool(getBoolean(bean.getAttendedSchool()));
        depFins.setIncomeAvailableToPatient(getBoolean(bean.getIncomeAvailableToPatient()));

       
        
        // amount contributed
        if (StringUtils.isNotEmpty(bean.getAmtContributed())) {
            depFins.setAmountContributedToSupport(new BigDecimal(bean.getAmtContributed()));
        } else {
            depFins.setAmountContributedToSupport(null);
        }

        Dependent dependent = depFins.getReportedOn();
        if (dependent == null) {
            dependent = new Dependent();
            depFins.setReportedOn(dependent);
        }
        convertBeanToRelation(bean, dependent);
    }

    private void convertBeanToRelation(RelationFinancialInfoBean bean, Relation relation) throws Exception {
        LookupCacheService lookupCacheService = getLookupCacheService();

        setNames(bean, relation, lookupCacheService);
        setDob(bean, relation);
        setSsnInfo(bean, relation, lookupCacheService);
        setPseudoSsnInfo(bean, relation, lookupCacheService);
        setEffectiveDate(bean, relation);
        setInActiveDate(bean, relation);

        String genderCode = bean.getGenderCode();
        String relationshipCode = bean.getRelationshipCode();

        if (relation instanceof Spouse) {
            relationshipCode = Relationship.CODE_SPOUSE.getName();
            
            SpouseFinancialInfoBean sBean = (SpouseFinancialInfoBean) bean;
            Spouse spouse = (Spouse)relation;
            spouse.setMaidenName(StringUtils.isBlank(sBean.getMaidenName()) ? null : sBean.getMaidenName());
           
            EmploymentStatus employmentStatus = (EmploymentStatus)lookupCacheService.getByCodeFromCache(
                   EmploymentStatus.class, sBean.getEmploymentStatus());
                    
            EmploymentStatus onFileEmploymentStatus = (EmploymentStatus)lookupCacheService.getByCodeFromCache(
                    EmploymentStatus.class, sBean.getOnFileEmploymentStatus());
            
            if(employmentStatus==null && onFileEmploymentStatus !=null){  // CCR 9722 can't delete the exting employment status.
                employmentStatus=onFileEmploymentStatus; 
            }
            Employment employment = spouse.getEmployment();
            
            if (employment == null) {
                // No previous record exists - create new one
                employment = new Employment();
                spouse.setEmployment(employment);
            }
            
            employment.setEmploymentStatus(employmentStatus);
            // CCR 10673
            employment.setRetirementDate(DateUtils.getImpreciseDate(sBean.getRetirementDate()));         
        }
        else if (relation instanceof Dependent) {
            genderCode = relationshipCode != null ? (String) relationGender.get(relationshipCode) : null;
        }
        setGender(relation, genderCode);
        setRelationship(relation, relationshipCode, lookupCacheService);
    }

    private void setNames(RelationFinancialInfoBean bean, Relation relation,
            LookupCacheService lookupCacheService) throws UnknownLookupTypeException, ClassNotFoundException {
        if (bean.isAnyNameFieldFilled())
        {
            Name name = relation.getName();

            if (name == null) {
                name = new Name();
                name.setType((NameType) lookupCacheService.getByCodeFromCache(NameType.class, NameType.LEGAL_NAME
                        .getName()));
                relation.setName(name);
            }
            name.setPrefix(StringUtils.isBlank(bean.getPrefix()) ? null : bean.getPrefix());
            name.setFamilyName(StringUtils.isBlank(bean.getLastName()) ? null : bean.getLastName());
            name.setGivenName(StringUtils.isBlank(bean.getFirstName()) ? null : bean.getFirstName());
            name.setMiddleName(StringUtils.isBlank(bean.getMiddleName()) ? null : bean.getMiddleName());
            name.setSuffix(StringUtils.isBlank(bean.getSuffix()) ? null : bean.getSuffix());
        }
        else
        {
            relation.setName(null);
        }
    }

    private void setDob(RelationFinancialInfoBean bean, Relation relation) {
        if (StringUtils.isNotEmpty(bean.getDateOfBirth()))
            relation.setDob(DateUtils.getImpreciseDate(bean.getDateOfBirth()));
        else
            relation.setDob(null);
    }

    private void setSsnInfo(RelationFinancialInfoBean bean, Relation relation,
            LookupCacheService lookupCacheService)
            throws UnknownLookupTypeException, ClassNotFoundException {
        String beanSsn = bean.getSsn();
        if (StringUtils.isNotEmpty(beanSsn)) {
            SSN ssn = relation.getOfficialSsn();
            if (ssn == null) {
                ssn = new SSN();
                ssn.setType((SSNType) lookupCacheService.getByCodeFromCache(
                        SSNType.class, SSNType.CODE_ACTIVE.getName()));
                relation.addSsn(ssn);
            }
            ssn.setSsnText(beanSsn.replaceAll("-", ""));
            ssn.setSourceOfChange((SSNChangeSource) lookupCacheService
                    .getByCodeFromCache(SSNChangeSource.class, bean
                            .getSsnSourceOfChange()));
            ssn
                    .setSsaVerificationStatus((SSAVerificationStatus) lookupCacheService
                            .getByCodeFromCache(SSAVerificationStatus.class,
                                    bean.getSsaVerificationStatus()));
        } else {
            SSN ssn = relation.getOfficialSsn();
            if (ssn != null)
                relation.removeSsn(ssn);
        }
    }

    private void setGender(Relation relation, String genderCode)
            throws UnknownLookupTypeException, ClassNotFoundException {
        if (StringUtils.isNotEmpty(genderCode)) {
            relation.setGender((Gender) getLookupCacheService()
                    .getByCodeFromCache(Gender.class, genderCode));
        } else {
            relation.setGender(null);
        }
    }

    private void setInActiveDate(RelationFinancialInfoBean bean, Relation relation) {
        relation.setEndDate(DateUtils.getDate(bean.getInactiveDate()));
    }

    
    private void setEffectiveDate(RelationFinancialInfoBean bean, Relation relation) {
        if (StringUtils.isNotEmpty(bean.getEffectiveDate()))
            relation.setStartDate(DateUtils.getImpreciseDate(bean.getEffectiveDate()));
        else
            relation.setStartDate(null);
    }

    private void setRelationship(Relation relation, String relationshipCode,
            LookupCacheService lookupCacheService) throws UnknownLookupTypeException, ClassNotFoundException {
        if (StringUtils.isNotEmpty(relationshipCode)) {
            relation.setRelationship((Relationship) lookupCacheService.getByCodeFromCache(Relationship.class,
                    relationshipCode));
        }
        else {
            relation.setRelationship(null);
        }
    }

    private void setPseudoSsnInfo(RelationFinancialInfoBean bean, Relation relation, LookupCacheService lookupCacheService) throws UnknownLookupTypeException, ClassNotFoundException {
        if (StringUtils.isNotEmpty(bean.getPseudoSsnReason())) {
            SSN pssn = relation.getPseudoSsn();
            if (pssn == null) {
                pssn = new SSN();
                pssn.setType((SSNType) lookupCacheService.getByCodeFromCache(SSNType.class,
                        SSNType.CODE_PSEUDO.getName()));
                relation.addSsn(pssn);
            }
            if (StringUtils.isNotEmpty(bean.getPseudoSsn()))
                pssn.setSsnText(bean.getPseudoSsn().replaceAll("-", ""));
            pssn.setPseudoSSNReason((PseudoSSNReason) lookupCacheService.getByCodeFromCache(
                    PseudoSSNReason.class, bean.getPseudoSsnReason()));
        } else {
            SSN pssn = relation.getPseudoSsn();
            if (pssn != null)
                relation.removeSsn(pssn);
        }
    }

    public CommonFinancialsDependentConversionService getCommonDependentConversionService() {
        return commonDependentConversionService;
    }

    public void setCommonDependentConversionService(
            CommonFinancialsDependentConversionService commonDependentConversionService) {
        this.commonDependentConversionService = commonDependentConversionService;
    }
}
