package gov.va.med.esr.service;

import gov.va.med.esr.common.infra.ImpreciseDate;
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.PhoneType;
import gov.va.med.esr.common.model.lookup.SSNType;
import gov.va.med.esr.common.model.lookup.SelfIdentifiedGenderIdentity;
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.BirthRecord;
import gov.va.med.esr.common.model.person.DeathRecord;
import gov.va.med.esr.common.model.person.Name;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.common.model.person.id.VPIDEntityKey;
import gov.va.med.fw.model.AbstractEntity;
import gov.va.med.fw.util.StringUtils;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.ToStringBuilder;

public class IdmServiceVO extends AbstractEntity {

	private static final long serialVersionUID = -963101290677483931L;

	public static final String UPDATE_STATUS_ACCEPTED = "ACCEPTED";

	public static final String UPDATE_STATUS_PENDING = "PENDING";

	public static final String UPDATE_STATUS_REJECTED = "REJECTED";

	public static final int POTENTIAL_MATCH = 1;

	public static final int EXACT_MATCH = 2;

	public static final String HOME_PHONE_TYPE_CODE = PhoneType.CODE_HOME.getCode();

	private Set names = new HashSet();

	private BirthRecord birthRecord;

	private DeathRecord deathRecord;

	private Gender gender;

	private SelfIdentifiedGenderIdentity sigi;

	private SSN ssn;

	private VPIDEntityKey vpid;

	private String mothersMaidenName;

	private String IDState = null;

	Set addresses = null;

	private Set phones = null;

	private VAFacility preferredFacilty;

	//private String placeOfBirthCity;

	//private String placeOfBirthState;

	private boolean addAPerson;

	private boolean deathEvent;

	private String patientType;

	private boolean isVeteran;

	private boolean isServiceConnected;

	private int idmMatchType;

	/**
	 * @see gov.va.med.fw.model.AbstractEntity#buildToString(org.apache.commons.lang.builder.ToStringBuilder)
	 */
	protected void buildToString(ToStringBuilder builder) {
		builder.append("names", names);
		builder.append("birthRecord", birthRecord);
		builder.append("deathRecord", deathRecord);
		builder.append("gender", gender);
		builder.append("ssn", ssn);
		builder.append("vpid", vpid);
		builder.append("preferredFacility", preferredFacilty);
		//builder.append("placeOfBirthCity", placeOfBirthCity);
		//builder.append("placeOfBirthState", placeOfBirthState);
		builder.append("addresses", addresses);
		builder.append("patientType", patientType);
		builder.append("isVeteran", isVeteran);
		builder.append("isServiceConnected", isServiceConnected);
		builder.append("idmMatchType", idmMatchType);
	}

	/**
	 * @return Returns the gender.
	 */
	public Gender getGender() {
		return gender;
	}

	/**
	 * @param gender The gender to set.
	 */
	public void setGender(Gender gender) {
		this.gender = gender;
	}

	public SelfIdentifiedGenderIdentity getSigi() {
		return sigi;
	}

	public void setSigi(SelfIdentifiedGenderIdentity sigi) {
		this.sigi = sigi;
	}

	/**
	 * @return Returns the names.
	 */
	public Set getNames() {
		return names;
	}

	public Name getLegalName() {
		return names != null ? Name.getNameOfType(names, NameType.LEGAL_NAME
				.getName()) : null;
	}

	public void addName(Name name) {
		names.add(name);
	}

	/**
	 * @param names The names to set.
	 */
	public void setNames(Set names) {
		this.names = names;
	}

	public SSN getSsn() {
		return ssn;
	}

	public String getSsnText() {
		return ssn != null ? ssn.getFormattedSsnText() : null;
	}

	public void setSsn(SSN ssn) {
		this.ssn = ssn;
	}

	/**
	 * @return Returns the birthRecord.
	 */
	public BirthRecord getBirthRecord() {
		return birthRecord;
	}

	/**
	 * @param birthRecord The birthRecord to set.
	 */
	public void setBirthRecord(BirthRecord birthRecord) {
		this.birthRecord = birthRecord;
	}

	/**
	 * @return Returns the deathRecord.
	 */
	public DeathRecord getDeathRecord() {
		return deathRecord;
	}

	/**
	 * @param deathRecord The deathRecord to set.
	 */
	public void setDeathRecord(DeathRecord deathRecord) {
		this.deathRecord = deathRecord;
	}

	/**
	 * @return Returns the deathevent indicator.
	 */
	public boolean getDeathEvent() {
		return deathEvent;
	}

	/**
	 * @param deathRecord The deathRecord to set.
	 */
	public void setDeathEvent(boolean deathEvent) {
		this.deathEvent = deathEvent;
	}

	/**
	 * @return Returns the vpid.
	 */
	public VPIDEntityKey getVpid() {
		return vpid;
	}

	/**
	 * @param vpid The vpid to set.
	 */
	public void setVpid(VPIDEntityKey vpid) {
		this.vpid = vpid;
	}

	public boolean isServiceConnected() {
		return isServiceConnected;
	}

	public void setServiceConnected(boolean isServiceConnected) {
		this.isServiceConnected = isServiceConnected;
	}

	public boolean isVeteran() {
		return isVeteran;
	}

	public void setVeteran(boolean isVeteran) {
		this.isVeteran = isVeteran;
	}

	public String getPatientType() {
		return patientType;
	}

	public void setPatientType(String patientType) {
		this.patientType = patientType;
	}

	public Set getAddresses() {
		return addresses;
	}

	public void setAddresses(Set addresses) {
		this.addresses = addresses;
	}

	public void addAddress(Address address) {
		Validate.notNull(address, "Null address specified.");
		if (addresses == null) {
			addresses = new HashSet();
		}
		addresses.add(address);
	}

	public Address getAddressByType(String addressTypeName) {
		if (addresses != null && addresses.size() > 0) {
			return Address.getAddressOfType(addresses, addressTypeName);
		}
		return null;
	}

	public void addPhone(Phone phone) {
		Validate.notNull(phone, "Null phone specified.");
		if (phones == null) {
			phones = new HashSet();
		}
		phones.add(phone);
	}

	public Phone getPhoneByType(String phoneTypeName) {
		if (phones != null && phones.size() > 0) {
			return Phone.getPhoneOfType(phones, phoneTypeName);
		}
		return null;
	}

	/* CCR 11402
	 * ESR UI allows multiple home phones. Get the latest home phone only
	 */
	public Phone getHomePhone()
	{
		Phone homePhone = null;
		if (phones != null && phones.size() > 0)
		{
			for (Iterator iter = phones.iterator(); iter.hasNext();) {
	            Phone phone = (Phone) iter.next();
	            if (phone.getType().getCode().equals(HOME_PHONE_TYPE_CODE)) {
	            	if (homePhone == null || (phone.getChangeDate() != null && homePhone.getChangeDate() != null && phone.getChangeDate().after(homePhone.getChangeDate())))
	            	{
	            		homePhone =phone;
	            	}
	            }
	        }
		}
		return homePhone;
	}

	public boolean containsOnlySSN() {
		String ssn = getSsn() != null ? getSsn().getSsnText() : null;
		String firstName = getLegalName() != null ? getLegalName()
				.getGivenName() : null;
		String lastName = getLegalName() != null ? getLegalName()
				.getFamilyName() : null;
		ImpreciseDate dob = getBirthRecord() != null ? getBirthRecord()
				.getBirthDate() : null;
		Gender gender = getGender();

		boolean result = false;
		if (vpid == null && StringUtils.isNotBlank(ssn)
				&& StringUtils.isBlank(firstName)
				&& StringUtils.isBlank(lastName) && dob == null
				&& gender == null)
			result = true;
		return result;
	}

	public boolean hasOfficialSSN() {
		SSNType myType = getSsn() != null ? getSsn().getType() : null;
		return myType != null
				&& SSNType.CODE_ACTIVE.getCode().equals(myType.getCode());
	}

	public boolean containsOnlyFullName() {
		String ssn = getSsn() != null ? getSsn().getSsnText() : null;
		String firstName = getLegalName() != null ? getLegalName()
				.getGivenName() : null;
		String lastName = getLegalName() != null ? getLegalName()
				.getFamilyName() : null;
		ImpreciseDate dob = getBirthRecord() != null ? getBirthRecord()
				.getBirthDate() : null;
		Gender gender = getGender();

		boolean result = false;
		if (vpid == null && StringUtils.isBlank(ssn)
				&& StringUtils.isNotBlank(firstName)
				&& StringUtils.isNotBlank(lastName) && dob == null
				&& gender == null)
			result = true;
		return result;
	}

	public boolean containsAtLeastFullName() {
		String firstName = getLegalName() != null ? getLegalName()
				.getGivenName() : null;
		String lastName = getLegalName() != null ? getLegalName()
				.getFamilyName() : null;

		boolean result = false;
		if (StringUtils.isNotBlank(firstName)
				&& StringUtils.isNotBlank(lastName))
			result = true;
		return result;
	}

	public boolean containsOnlyLastNameAndDOB() {
		String ssn = getSsn() != null ? getSsn().getSsnText() : null;
		String firstName = getLegalName() != null ? getLegalName()
				.getGivenName() : null;
		String lastName = getLegalName() != null ? getLegalName()
				.getFamilyName() : null;
		ImpreciseDate dob = getBirthRecord() != null ? getBirthRecord()
				.getBirthDate() : null;
		Gender gender = getGender();

		boolean result = false;
		if (vpid == null && StringUtils.isBlank(ssn)
				&& StringUtils.isBlank(firstName)
				&& StringUtils.isNotBlank(lastName) && dob != null
				&& gender == null)
			result = true;
		return result;
	}

	public boolean containsAtLeastLastNameAndDOB() {
		String lastName = getLegalName() != null ? getLegalName()
				.getFamilyName() : null;
		ImpreciseDate dob = getBirthRecord() != null ? getBirthRecord()
				.getBirthDate() : null;

		boolean result = false;
		if (StringUtils.isNotBlank(lastName) && dob != null)
			result = true;
		return result;
	}

	public boolean containsSsnDOBGender() {
		String ssn = getSsn() != null ? getSsn().getSsnText() : null;
		String lastName = getLegalName() != null ? getLegalName()
				.getFamilyName() : null;
		ImpreciseDate dob = getBirthRecord() != null ? getBirthRecord()
				.getBirthDate() : null;
		Gender gender = getGender();

		boolean result = false;
		if (vpid == null && StringUtils.isBlank(lastName)
				&& StringUtils.isNotBlank(ssn) && dob != null && gender != null)
			result = true;
		return result;
	}

	/**
	 * @return Returns the mothersMaidenName.
	 */
	public String getMothersMaidenName() {
		return mothersMaidenName;
	}

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

	public boolean equals(Object o) {
		super.getLogger(); // this just initializes logger and allows us to turn on logging for this class
		return super.equals(o);
	}

	public String getIDState() {
		return IDState;
	}

	public void setIDState(String state) {
		IDState = state;
	}

	/**
	public MultipleBirthIndicator getMultiBirth() {
		return multiBirth;
	}

	public void setMultiBirth(MultipleBirthIndicator multiBirth) {
		this.multiBirth = multiBirth;
	}

	public String getPlaceOfBirthCity() {
		return placeOfBirthCity;
	}

	public void setPlaceOfBirthCity(String placeOfBirthCity) {
		this.placeOfBirthCity = placeOfBirthCity;
	}

	public String getPlaceOfBirthState() {
		return placeOfBirthState;
	}

	public void setPlaceOfBirthState(String placeOfBirthState) {
		this.placeOfBirthState = placeOfBirthState;
	}
**/
	public VAFacility getPreferredFacilty() {
		return preferredFacilty;
	}

	public void setPreferredFacilty(VAFacility preferredFacilty) {
		this.preferredFacilty = preferredFacilty;
	}

	public boolean isAddAPerson() {
		return addAPerson;
	}

	public void setAddAPerson(boolean addAPerson) {
		this.addAPerson = addAPerson;
	}

	public int getIdmMatchType() {
		return idmMatchType;
	}

	public void setIdmMatchType(int idmMatchType) {
		this.idmMatchType = idmMatchType;
	}

	public Set getPhones() {
		return phones;
	}

	public void setPhones(Set phones) {
		this.phones = phones;
	}

}
