package gov.va.med.esr.common.rule.parameter;

import gov.va.med.esr.common.batchprocess.SSASSNVerificationData;
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.infra.ImpreciseDateUtils;
import gov.va.med.esr.common.model.lookup.Gender;
import gov.va.med.esr.common.model.lookup.SSAMessage;
import gov.va.med.esr.common.model.lookup.SSAVerificationStatus;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.Relation;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.common.persistent.person.SSNVerificationDetailDAO;
import gov.va.med.esr.common.rule.SSNVerificationResponseInput;
import gov.va.med.esr.common.rule.data.SSNVerificationResponseInputData;
import gov.va.med.fw.persistent.DAOOperations;
import gov.va.med.fw.rule.RuleDataAware;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.util.StringUtils;

/**
 * 
 * @author Rajiv Patnaik Created on Mar 20, 2006
 * @version 1.0
 * 
 * Copyright © 2006 VHA. All rights reserved
 */
public class SSNVerificationResponseInputParameter extends BaseParameter
        implements SSNVerificationResponseInput
{
    /**
    * An instance of serialVersionUID 
    */
   private static final long serialVersionUID = -4097456271790178726L;

   private String ssnVerificationDetailDAOName;

    private String genericDAOName;
    
    // These constants are used to compare the identity traits
    // As per current ICD the supported lengths are as follows.
    private static final int LAST_NAME_LENGTH=13;    
    private static final int FIRST_NAME_LENGTH=10;
    private static final int MIDDLE_NAME_LENGTH=7;
    private static final int WHOLE_LENGTH= -1 ;
    

    public SSNVerificationResponseInputParameter()
    {
        super();
    }

    /**
     * @return Returns the ssnVerificationDetailDAOName.
     * @throws ServiceException
     */
    public SSNVerificationDetailDAO getSsnVerificationDetailDAO()
            throws ServiceException
    {
        return (SSNVerificationDetailDAO) this
                .getComponent(this.ssnVerificationDetailDAOName);
    }

    /**
     * @param ssnVerificationDetailDAOName
     *            The ssnVerificationDetailDAOName to set.
     */
    public void setSsnVerificationDetailDAOName(
            String ssnVerificationDetailDAOName)
    {
        this.ssnVerificationDetailDAOName = ssnVerificationDetailDAOName;
    }

    /**
     * @return Returns the ssnVerificationDetailDAOName.
     * @throws ServiceException
     */
    public DAOOperations getGenericDAO() throws ServiceException
    {
        return (DAOOperations) this.getComponent(this.genericDAOName);
    }

    /**
     * @param ssnVerificationDetailDAOName
     *            The ssnVerificationDetailDAOName to set.
     */
    public void setGenericDAOName(String genericDAOName)
    {
        this.genericDAOName = genericDAOName;
    }

    public boolean isSSNVerificationForSpouseOrDependent()
            throws ServiceException
    {
        //If SSNVerificationDetail has a ssn id, it is either a spouse or
        // dependent
        return ((SSASSNVerificationData) this.getIncomingData())
                .isSsnVerificationForSpouseOrDependent();
    }

    public String getVerificationCode()
    {
        String verificationCode = ((SSASSNVerificationData)this.getIncomingData()).getVerificationCode(); 
        return  StringUtils.isEmpty(verificationCode) ? null : verificationCode;
    }

    public boolean isHECIdMatched() throws ServiceException
    {
        return ((SSASSNVerificationData) this.getIncomingData())
                .isHECInternalIdMatched();
    }

    public void setVerificationStatus(String statusCode)
            throws ServiceException
    {
        if (this.getSSNVerificationInputData() != null)
        {
            SSAVerificationStatus verificationStatus = getLookupService()
                    .getSSAVerificationStatusByCode(statusCode);
            SSASSNVerificationData resultSSNVerificationData = this
                    .getSSNVerificationInputData().getResultSSNVerificationData();
            resultSSNVerificationData
                    .setSsaVerificationStatus(verificationStatus);
        }
    }

    public void setSSAMessage(String ssaMessageCode) throws ServiceException
    {
        if (this.getSSNVerificationInputData() != null)
        {
            SSAMessage ssaMessage = getLookupService().getSSAMessageByCode(
                    ssaMessageCode);
            SSASSNVerificationData resultSSNVerificationData = this.getSSNVerificationInputData().getResultSSNVerificationData();
            resultSSNVerificationData.setSsaMessage(ssaMessage);
        }
    }
    
    //CCR 11666
    public void addToSSNVerificationQueue() throws ServiceException
    {
    	if(!this.isSSNVerificationForSpouseOrDependent())
    		this.getHelperService().addToSSNVerificationQueue(this.getResultPerson());
    }

    public Person getPersonForSpouseOrDependent() throws ServiceException
    {
        return this.getResultPerson();
    }

    public void updateSSNVerificationResult() throws ServiceException
    {
        if (this.getSSNVerificationInputData() != null)
        {
            SSASSNVerificationData resultSSNVerification = (SSASSNVerificationData) this
                    .getSSNVerificationInputData()
                    .getResultSSNVerificationData();

            if (isSSNVerificationForSpouseOrDependent())
            {
                resultSSNVerification
                        .setSsnVerificationForSpouseOrDependent(isSSNVerificationForSpouseOrDependent());
                resultSSNVerification.setSsnId(((SSASSNVerificationData)this.getIncomingData()).getSsnId());
            }
        }
    }

    private SSNVerificationResponseInputData getSSNVerificationInputData()
    {
        RuleDataAware ruleDataAware = this.getRuleDataAware();
        if (ruleDataAware instanceof SSNVerificationResponseInputData)
        {
            return (SSNVerificationResponseInputData) ruleDataAware;
        }
        return null;
    }
    
    private Relation getRelation()
    {
        return getSSNVerificationInputData()!=null ? getSSNVerificationInputData().getRelation() : null;
    }
    /**
     * 
     */
    public boolean isIdentityTraitsChanged ()
    {
        boolean identityChanged=false;
        SSASSNVerificationData incomingSSNVerifData =(SSASSNVerificationData)this.getIncomingData();        
        if(incomingSSNVerifData.isSsnVerificationForSpouseOrDependent())
        {
            identityChanged=isSpouseOrDependentIdentityTraitsChanged(incomingSSNVerifData,getRelation()); 
        }
        else
        {
            Person person=getPristinePerson();
            identityChanged=isVeteranIdentityTraitsChanged(incomingSSNVerifData,person);            
            
        }       
        return identityChanged;
    }
    
    /**
     * 
     * @param sSNVerifData
     * @param person
     * @return
     */
    private boolean isVeteranIdentityTraitsChanged(SSASSNVerificationData sSNVerifData,Person person)
    {       
        ImpreciseDate dob=person.getBirthRecord()!=null?person.getBirthRecord().getBirthDate():null;
        return isIdentityTraitsChanged(person.getLegalName(),dob,person.getGender(),
                person.getOfficialSsn(),sSNVerifData);        
    }
    
    /**
     * 
     * @param sSNVerifData
     * @param person
     * @return
     */
    private boolean isSpouseOrDependentIdentityTraitsChanged(SSASSNVerificationData sSNVerifData,Relation relation)
    {        
               
        return relation!=null? isIdentityTraitsChanged(relation.getName(),relation.getDob(),relation.getGender(),
                relation.getOfficialSsn(),sSNVerifData):false;        
        
    }  
    
    /**
     * 
     * @param name
     * @param dob
     * @param gender
     * @param ssn
     * @param sSNVerifData
     * @return
     */
    private boolean isIdentityTraitsChanged(Name name, ImpreciseDate dob,Gender gender, SSN ssn, SSASSNVerificationData sSNVerifData)
    {
        boolean identityChanged=false;
        if(!equalsIgnoreCaseIgnoreBlanks(sSNVerifData.getFirstName(), name.getGivenName(), FIRST_NAME_LENGTH) || 
                !equalsIgnoreCaseIgnoreBlanks(sSNVerifData.getLastName(), name.getFamilyName(), LAST_NAME_LENGTH)||
                !equalsIgnoreCaseIgnoreBlanks(sSNVerifData.getMiddleInitial(), name.getMiddleName(), MIDDLE_NAME_LENGTH)||
                 !ImpreciseDateUtils.impreciseDatesEqualWithoutTime(sSNVerifData.getDateOfBirth(),dob)||
                 !equalsIgnoreCaseIgnoreBlanks(sSNVerifData.getGender(), gender != null?gender.getCode(): null, WHOLE_LENGTH )||
                 !equalsIgnoreCaseIgnoreBlanks(sSNVerifData.getSsn(), ssn.getSsnText(), WHOLE_LENGTH))             
        {
            identityChanged=true;
        }    
        return identityChanged;        
    }
    
    /**
     * 
     * @param str1
     * @param str2
     * @param compareLength
     * @return
     */
    public static boolean equalsIgnoreCaseIgnoreBlanks(String str1, String str2, int compareLength)
    {
        if(StringUtils.isBlank(str1) && StringUtils.isBlank(str2)  )
            return true;
        String org1 = compareLength != -1 ?  StringUtils.substring(str1, 0 , compareLength) : str1;
        String org2 = compareLength != -1 ?  StringUtils.substring(str2, 0 , compareLength) : str2;
        return StringUtils.equalsIgnoreCase(org1 ,org2);
    }
    
   
}
