package gov.va.med.esr.messaging.service.inbound;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;

import gov.va.med.fw.hl7.InvalidMessageException;
import gov.va.med.fw.hl7.Message;
import gov.va.med.fw.hl7.constants.SegmentConstants;
import gov.va.med.fw.hl7.segment.QRD;
import gov.va.med.fw.hl7.segment.QRF;
import gov.va.med.fw.service.ServiceException;

import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.service.PersonSearchQueryInfo;
import gov.va.med.person.exceptions.NoRecordFoundException;

/**
 * 
 * @author Rajiv Patnaik Created on Dec 22, 2005
 * @version 1.0
 * 
 * Copyright © 2005 VHA. All rights reserved
 */
public class PersonFinderFromVistaQuery extends AbstractPersonFinderFromVista {
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see gov.va.med.esr.messaging.service.inbound.PersonFinder#find(gov.va.med.fw.hl7.Message)
	 */
	public Person find(Message message) throws ServiceException {
		try {
			String dfn = ((QRD) message.getSegment(SegmentConstants.QRD))
					.getQueryID();
			String stationNumber = getSendingFacilityStationNumber(message);
			
			return this.getPerson(dfn, stationNumber);
		} catch (ServiceException se) {

			// ESR_CodeCR6852. If the DFN/Station Number lookup fails
			// to return a record, lookup the person by SSN+DOB+GENDER.

			// if the service exception is caused by a PSIM
			// NoRecordFoundException
			if (ExceptionUtils.getRootCause(se) instanceof NoRecordFoundException) {
				try {
					String whoSubjectFilter = ((QRD) message
							.getSegment(SegmentConstants.QRD))
							.getWhoSubjectFilter();
					String ssnText = StringUtils.substring(whoSubjectFilter, 0, 9);
								
					QRF qrf = (QRF) message.getSegment(SegmentConstants.QRF);
					String dobText = qrf.getWhatUserQualifier();
					String genderText = qrf.getOtherQuerySubjectFilter();

					PersonSearchQueryInfo criteria = new PersonSearchQueryInfo();
					
					criteria.setUnformattedSsn(ssnText);
					criteria.setDateOfBirth(dobText);
					criteria.setGender(genderText);
					
					if(logger.isWarnEnabled()) {
						logger.warn("Find for person with dfn+station#"
								+ " failed, finding with " //ssn=" + ssnText
								+ "Date of Birth=" + dobText + ", gender="
								+ genderText);
					}
					
					try {
						List results = this.getPersonService().search(criteria, true, true, false, 1);
						
						if(results.size() == 0)
						   throw new ServiceException(PERSON_NOT_FOUND_ERR);

						return (Person) results.iterator().next();
					} catch (Exception e) {
						throw new ServiceException(PERSON_NOT_FOUND_ERR, e);
					}
				} catch (InvalidMessageException e) {
					// ASSERT: Should not happen if the message is already
					// parsed.
					throw new RuntimeException(
							"Failed to obtain the QRD or QRF segment", e);
				}
			} else 
				throw se;
		}
		catch (InvalidMessageException e) {
			// ASSERT: Should not happen if the message is already parsed.
			throw new RuntimeException(
					"Failed to obtain the dfn from the PID segment", e);
		}
	}

}
