package gov.va.med.esr.service;

// Java classes
import gov.va.med.esr.common.batchprocess.SSASSNVerificationData;
import gov.va.med.esr.common.model.comms.CommsLogEntry;
import gov.va.med.esr.common.model.comms.HandBookMailQueue;
import gov.va.med.esr.common.model.financials.IncomeTest;
import gov.va.med.esr.common.model.lookup.ConfidentialAddressCategoryType;
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.ConfidentialAddressCategory;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.SSNVerification;
import gov.va.med.esr.common.model.person.id.PersonEntityKey;
import gov.va.med.esr.service.external.demographics.DemographicsChangeSummary;
import gov.va.med.esr.service.impl.ChangeEvent;
import gov.va.med.esr.service.impl.HistoricalInfo;
import gov.va.med.fw.model.EntityKey;
import gov.va.med.fw.service.ServiceException;
import gov.va.med.fw.service.trigger.TriggerEvent;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * Interface for the demographic services.
 *
 * @author DNS   LEV
 * @author Andrew Pach
 * @author DNS   PATNAR
 * @version 3.0
 */
public interface DemographicService extends Serializable
{

    /**
     * Updates demographic information. This method is meant to be called from UI.
     *
     * @param incoming person with the data updated by UI.
     *
     * @return The person object after updating(database).
     * @throws ServiceException thrown when there is application error or rule validation errors.
     */
    public Person updateDemographicInformation(Person incoming) throws ServiceException;

    /**
     * Updates demographic information. This method is meant to be called from the Messaging.
     *
     * @param sendingFacility the sending VA facility.
     * @param incoming person with the data updated by Messaging.
     *
     * @return The person object after updating(database).
     * @throws ServiceException thrown when there is application error or rule validation errors.
     */
    public Person processDemographicInformation(VAFacility sendingFacility, Person incoming) throws ServiceException;

    /**
     * @param incoming the incoming person
     *
     * @return the updated person
     * @throws ServiceException if any problems were encountered.
     */
    public Person updateContactInformation(Person incoming) throws ServiceException;


    /**
	 * DO NOT USE for generic demographics cases
	 * This is utility only for creating address_h entry during correspondence generation to track
	 * address at time of mail request, explicit flush is invoked.
     * @param onFileAddress - unmodified address from getLetterAddress
     * @return void
     * @throws ServiceException
     *
     */
    public void saveAddress(Address onFileAddress) throws ServiceException;

    /**
     * Get Address History timestamps
     *
     * @param personID the person Id
     *
     * @return the set of change times
     * @throws ServiceException if any problems were encountered
     */
    public Set getAddressHistoryChangeTimes(EntityKey personID) throws ServiceException;

    /**
     * Get current and previous address by change time
     *
     * @param event the change event
     *
     * @return the history information
     * @throws ServiceException if any problems were encountered
     */
    public HistoricalInfo getAddressHistoryByChangeTime(ChangeEvent event)
        throws ServiceException;

    /**
     * Get Address History timestamps
     *
     * @param personID the person Id
     *
     * @return the set of change times
     * @throws ServiceException if any problems were encountered
     */
    public Set getInsuranceHistoryChangeTimes(EntityKey personID) throws ServiceException;

    /**
     * Get current and previous address by change time
     *
     * @param event the change event
     *
     * @return the history information
     * @throws ServiceException if any problems were encountered
     */
    public HistoricalInfo getInsuranceHistoryByChangeTime(ChangeEvent event)
        throws ServiceException;
    /**
     * Get Demographics History timestamps
     *
     * @param personID the person Id
     *
     * @return the list of change times
     * @throws ServiceException if any problems were encountered
     */
    public Set getDemographicHistoryChangeTimes(EntityKey personID) throws ServiceException;

    /**
     * Get current and previous person demographics by change time
     *
     * @param event the change event
     *
     * @return the history information
     * @throws ServiceException if any problems were encountered
     */
    public HistoricalInfo getDemographicHistoryByChangeTime(ChangeEvent event)
        throws ServiceException;

    /**
     * Get Social Security History timestamps
     *
     * @param personID the person Id
     *
     * @return The set of change times
     * @throws ServiceException if any problems were encountered
     */
    public Set getIdentityTraitsChangeTimes(EntityKey personID) throws ServiceException;
    
    public Set getSubmittedIdentityTraitsChangeTimes(EntityKey personID) throws ServiceException;

    /**
     * Get current and previous Social Security by change time
     *
     * @param event the change event
     *
     * @return the history information
     * @throws ServiceException if any problems were encountered
     */
    public HistoricalInfo getIdentityTraitsHistoryByChangeTime(ChangeEvent event)
        throws ServiceException;

    public HistoricalInfo getSubmittedIdentityTraitsHistoryByChangeTime(ChangeEvent event)
    	throws ServiceException;
    
    /**
     * Entry point for non-ESR initiated demographics changes
     *
     * @param changeSummary the demographics change summary
     *
     * @throws ServiceException if any problems were encountered.
     */
    public void processExternalDemographicsChange(DemographicsChangeSummary changeSummary) throws ServiceException;

    
    
    /**
     *  
     * @param incomeTestStatus
     * @param lastEditedDate
     * @throws ServiceException
     */
    public void updateIncomeTestLastEditedDate(IncomeTest incomeTest, Date lastEditedDate) throws ServiceException;
    

    /**
     * Get the addresses of a person
     *
     * @param key the entity key
     *
     * @return a List of addresses for that person, null if one can not be found
     * @throws ServiceException if any problems were encountered.
     */
    List getPersonAddresses(PersonEntityKey key) throws ServiceException;

    /**
     * Get the address to be used for letter mailing
     *
     * @param person the person whose letter address should be retrieved for
     *
     * @return an address object for mailing, null if one can not be found
     * @throws ServiceException if any problems were encountered.
     */
    Address getLetterAddress(Person person) throws ServiceException;

    /**
     * Get the updated address since the last time the letter was sent out. It compares the address (String literal)
     * used in the letter sent and the latest letter address. If they are identical, return null. Otherwise return the
     * latest letter address.
     *
     * @param log the comms log entry
     *
     * @return a latest address for mailing, null if one can not be found
     * @throws ServiceException if any problems were encountered.
     */
    Address getUpdatedLetterAddress(CommsLogEntry log) throws ServiceException;

    /**
     * Overaloded method to support undeliverable handbook
     */
    public Address getUpdatedLetterAddress(HandBookMailQueue mailQueue) throws ServiceException;

    /**
     * Get the updated address that will be used assuming the address that was used to send out the letter
     * is no longer valid.
     *
     * @param log The CommsLogEntry
     * @return The updated address or null if no new address would be used.
     * @throws ServiceException if any problems were encountered.
     */
    Address getUndeliverableMailUpdatedLetterAddress(CommsLogEntry log) throws ServiceException;

    /**
     * Processes the data from SSN Verification response from SSA
     *
     * @param ssnVerificationData the SSN verification data
     *
     * @throws ServiceException if any problems were encountered.
     */
    public Person updateSSNVerificationResponse(
        SSASSNVerificationData ssnVerificationData) throws ServiceException;

    /**
     * @param ssnVerification the SSN verification information
     * @param newSSNVerificationDetails newlyadded detail objects.
     * @param bulkUpdateQueryString - query string to be used for bulk update
     * @param spouseDependentsUpdateParams - params to be set in the query string for bulk update
     *
     * @return the updated SSN verification information
     * @throws ServiceException if any problems were encountered.
     */
    public SSNVerification updateRequestSSNVerificationData(SSNVerification ssnVerification,
                                                            List newSSNVerificationDetails,
                                                            String bulkUpdateQueryString, 
                                                            Object[] spouseDependentsUpdateParams)
        throws ServiceException;

    /**
     * Update and apply rules for identity traits information.
     * 
     * @param incoming the incoming person
     * @return the updated person
     * @throws ServiceException if any problems were encountered.
     */
    public Person updateIdentityTraits(Person incoming) throws ServiceException;    
    
    /**
     * Process a new DeathRecord for a Person.  This is called by the DateOfDeath 
     * batch process.
     * 
     * @param Person The person with a new DeathRecord  
     * @throws ServiceException
     */
    public Person processDeathRecordFromIdm(Person incoming) throws ServiceException;

    
    /**
     * Process for updating a Person with a Date of Death from 
     * Idm. Rules may be specific to Idm context so
     * beware using this method for other purposes.
     * 
     * @param person person
     * @param dateOfDeath
     * @return
     * @throws ServiceException
     */
    public Person processDateOfDeathFromIdm(Person person, Date dateOfDeath)  throws ServiceException;  
    
    public void sendDodUpdate(TriggerEvent triggerEvent) throws ServiceException;
    
    /**
     * Process for retrieving a specific ConfidentialAddressCategoryType by code.
     * 
     * @param code
     * @return ConfidentialAddressCategoryType
     * @throws ServiceException
     */
    public ConfidentialAddressCategoryType getConfidentialAddressCategoryTypesByCode(String code) throws ServiceException;
    
    /**
     * Get the list of ConfidentialAddressCategoryType's
     * @param person
     * @return
     */
    public List getConfAddrCategories(Person person);
    

}
