/*
 * Created on Feb 1, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package gov.va.med.esr.common.builder.comms;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import gov.va.med.esr.common.model.comms.MailingStatusLink;
import gov.va.med.esr.common.model.lookup.AddressType;
import gov.va.med.esr.common.model.lookup.AssociationType;
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.party.Address;
import gov.va.med.esr.common.model.party.Phone;
import gov.va.med.esr.common.model.person.Association;
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.SSN;
import gov.va.med.esr.common.util.LetterFormatHelper;
import gov.va.med.esr.service.LookupService;
import gov.va.med.esr.service.PersonHelperService;
import gov.va.med.fw.service.ServiceException;

/**
 * @author DNS   TSAIG
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public abstract class GeneralTransmission implements ITransmission {

	//-------------------------------------------------------------------
	// Static variable(s)
	//--------------------------------------------------------------------
	// default value for all String type
	protected static final String EMPTY_STRING = "";
	protected static final String TODAY_DATE_FORMAT_STRING = "MM/dd/yyyy";
	protected static SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");

	private boolean isVeteranSet = false; //veteran related info
	private boolean isWorkloadSet = false; //workload related info
	private boolean isLogSet = false; //Comms log related info
	//if transmission restored from xml, do not populate any values from database
	protected boolean historicalCopy = false;
	
	//--------------------------------------------------------------------
	// Constructor(s)
	//--------------------------------------------------------------------
	public GeneralTransmission()
	{
	}

	//NEED this one when workflow is done
//	public GeneralTransmission(Person veteran, int incomeYear, WorkflowCase workflowCase)

	public GeneralTransmission(Person veteran, String incomeYear, BigDecimal workflowCaseId)
	{
	    this.vet = veteran;
//	    this.incomeYear = this.incomeYear = (incomeYear == 0) ? null: incomeYear + EMPTY_STRING;
	    this.incomeYear = incomeYear;
	    this.workflowCaseId = workflowCaseId;
	    
	    cal = new GregorianCalendar();
	    todayDt = cal.getTime();
	}

/*
 * private method to turn null string to empty string
 */
	protected static String getString(String str)
	{
	    return LetterFormatHelper.getString(str);
	}
	
	//--------------------------------------------------------------------
	// Properties
	//--------------------------------------------------------------------
    public void setHelperService(PersonHelperService service) {
        this.helperService = service;
    }

	/// <summary>
	/// properties for IncomeYear, PASSED IN 
	/// Income Year's default will be (currentYear - 1)
	/// Historic letter, this value is come from XML deserilization.
	/// <\summary>
	public String getIncomeYear()
	{
		if ( incomeYear == null || incomeYear.length() == 0 )
			incomeYear = (cal.get(GregorianCalendar.YEAR)-1) + "";

		return incomeYear;
	}
	
	public void setIncomeYear(String inYearStr)
	{
		incomeYear = inYearStr;
	}


	/// <summary>
	/// interface method
	/// </summary>
	/// <returns></returns>
	public boolean validate()
	{
		return true;
	}


	protected void setVeteranRelatedProperties()
	{
		if ( isVeteranSet || historicalCopy)
			return;
		
		if (vet!= null)
		{
			//1. Veteran basic info
		    Date aDate = null;
		    if (vet.getBirthRecord() != null && vet.getBirthRecord().getBirthDate() != null &&
		            vet.getBirthRecord().getBirthDate().getDate() != null)
		    {
		        aDate = vet.getBirthRecord().getBirthDate().getDate();
		        synchronized(sdf) {
		        	this.veteranDOB = sdf.format(aDate);
		        }
		    }
			//name
			Name legalName =  Name.getNameOfType(vet.getNames(), NameType.LEGAL_NAME.getName());
			
			if (legalName != null)
			{
			    this.veteranFirstName = legalName.getGivenName();
			    this.veteranLastName = legalName.getFamilyName();
			    this.veteranSuffix = legalName.getSuffix();
			    this.vetTitle = legalName.getPrefix();
			}
			if (vet.getGender() != null)
			    this.veteranGender = vet.getGender().getCode();
			
			if (vetTitle == null || vetTitle.length() == 0)
			{
				if (veteranGender != null && this.veteranGender.length() > 0)
				{
					//no title, derive from gender type
					if (this.veteranGender.equals("M"))
						vetTitle = "MR."; //male, upper case
					else
						vetTitle = "MS."; //female, upper case
				} else
				{
				    vetTitle = "MR."; //male by default, if not specified
				}
			}
			
			//TODO homeless indicator
			//??this.veteranHomelessIndicator = vet.get;
		    if (vet.getDeathRecord() != null && vet.getDeathRecord().getDeathDate() != null)
		    {
		        aDate = vet.getDeathRecord().getDeathDate().getDate();
		        synchronized(sdf) {
		        	this.veteranDateOfDeath = sdf.format(aDate);
		        }
		    }

			
			
			//2. Veteran SSN
			if (veteranSsn != null)
			    vetSsnVerified = true;
			else 
			{
			    SSN ssn = null;
			    
			    try{
			        ssn = helperService.getSSN(SSNType.CODE_ACTIVE.getName(), vet); //SSA verified SSN (02)
			    } catch (ServiceException sex)
			    {
			        //can't get the SSN, set it to null
			        this.veteranSsn = null;
			    }
			    
				if (ssn != null)
				{
					vetSsnVerified = true;
					this.veteranSsn = ssn.getSsnText();
				}					
			}
			//3. Veteran Address
		     Set addrSet = vet.getAddresses();
		     Set phoneSet = vet.getPhones();
		      
		     //run through address priority algorithm to pich a mailing address
		     Address addrToUse = gov.va.med.esr.common.util.MailingAddressHelper.selectAddressForMailing(addrSet);
		      
		    if (phoneSet != null && phoneSet.size()>0)
		    {
		        Phone phone= Phone.getPhoneOfType(phoneSet, PhoneType.CODE_HOME.getName());
		        if (phone != null)
		            this.homePhoneNumber = phone.getPhoneNumber();
		        
		        phone = Phone.getPhoneOfType(phoneSet, PhoneType.CODE_BUSINESS.getName());
		        if (phone != null)
		            this.workPhoneNumber = phone.getPhoneNumber();		        
		    }
			 
			mailingAdress =  addrToUse;			
			if (mailingAdress != null) {
			    this.veteranAddressType = mailingAdress.getType(); 
				this.veteranAddressLine1 = mailingAdress.getLine1(); 
				this.veteranAddressLine2 = mailingAdress.getLine2(); 
				this.veteranAddressLine3 = mailingAdress.getLine3();
				this.veteranCity = mailingAdress.getCity();
				this.veteranState = LetterFormatHelper.getMailingAddressState(mailingAdress);
				this.veteranZipCodeOrPostalCode = LetterFormatHelper.getMailingAddressZipOrPostal(mailingAdress);
				this.veteranCountyOrProvince = LetterFormatHelper.getMailingAddressCountyOrProvince(mailingAdress);
				this.veteranCountry = mailingAdress.getCountry();
				// country preference is postal name
				this.veteranCountryName = LetterFormatHelper.getMailingAddressCountry(mailingAdress);
			}
			// CMS use
			this.veteranPersonIdentifier = vet.getVPIDValue();
		}
		
		isVeteranSet = true;
	}


	public Person getVeteran()
	{
	    return vet;
	}
	
	public void setVeteran (Person veteran)
	{
	    vet = veteran;
	}
	/// <summary>
	/// properties for Title
	/// <\summary>
	public String getVeteranTitle()
	{
	    setVeteranRelatedProperties();
		return getString(vetTitle);
	}
	
	public void setVeteranTitle(String vetTitle)
	{
			this.vetTitle = vetTitle;
	}
	

	public String getVeteranName()
	{
	    setVeteranRelatedProperties();
		if ( veteranName == null )
		{
			StringBuffer nameString = new StringBuffer();
			nameString.append (this.veteranFirstName);
			nameString.append (" ");
			nameString.append (this.veteranMiddleName);
			nameString.append (" ");
			nameString.append (this.veteranLastName);
			veteranName = nameString.toString ();
		}
		return getString(veteranName);
	}
	
	public void setVeteranName(String vetName)
	{
		veteranName = vetName;
	}

	public String getVeteranFirstName()
	{
	    setVeteranRelatedProperties();
		return getString(veteranFirstName);
	}
	
	public void setVeteranFirstName(String firstName)
	{
		this.veteranFirstName = firstName;
	}

	/// <summary>
	/// veteran last name
	/// </summary>
	public String getVeteranLastName()
	{
	    setVeteranRelatedProperties();
		return getString(veteranLastName);
	}
	public void	setVeteranLastName(String lastName)
	{
		this.veteranLastName = lastName;
	}

	/// <summary>
	/// veteran middle name
	/// </summary>
	public String getVeteranMiddleName()
	{
	    setVeteranRelatedProperties();
		return getString(veteranMiddleName);
	}
	public void	setVeteranMiddleName(String middleName)
	{
		this.veteranMiddleName = middleName;
	}
	/// <summary>
	/// veteran suffix
	/// </summary>
	public String getVeteranSuffix()
	{
	    setVeteranRelatedProperties();
		return getString(veteranSuffix);
	}
	public void	setVeteranSuffix(String suffix)
	{
		this.veteranSuffix = suffix;
	}
	
	/// <summary>
	/// veteran gender
	/// </summary>
	public String getVeteranGender()
	{
	    setVeteranRelatedProperties();
		return getString(veteranGender);
	}
	public void	setVeteranGender(String gender)
	{
		veteranGender = gender;
	}

	public AddressType getVeteranAddressType() {
		setVeteranRelatedProperties();
		return veteranAddressType;
	}
	
	public void setVeteranAddressType(AddressType veteranAddressType) {
		this.veteranAddressType = veteranAddressType;
	}
	
	/**
	 * @return Returns the veteranAddressLine1.
	 * @throws ServiceException
	 */
	public String getVeteranAddressLine1() {
		setVeteranRelatedProperties();
		return getString(veteranAddressLine1);
	}
	/**
	 * @param veteranAddressLine1 The veteranAddressLine1 to set.
	 */
	public void setVeteranAddressLine1(String veteranAddressLine1) {
		this.veteranAddressLine1 = veteranAddressLine1;
	}


	/// <summary>
	/// properties for AddressLine2 
	/// <\summary>
	public String getVeteranAddressLine2()
	{
		setVeteranRelatedProperties();
		return getString(veteranAddressLine2);
	}

	public void	setVeteranAddressLine2(String vetAddrLine2)
	{
		veteranAddressLine2 = vetAddrLine2;
	}	
	/**
	 * @return Returns the veteranAddressLine3.
	 * @throws ServiceException
	 */
	public String getVeteranAddressLine3() {
		setVeteranRelatedProperties();
		return getString(veteranAddressLine3);
	}
	/**
	 * @param veteranAddressLine3 The veteranAddressLine3 to set.
	 */
	public void setVeteranAddressLine3(String veteranAddressLine3) {
		this.veteranAddressLine3 = veteranAddressLine3;
	}
	/**
	 * @return Returns the veteranCity.
	 * @throws ServiceException
	 */
	public String getVeteranCity() {
		setVeteranRelatedProperties();
		return getString(veteranCity);
	}
	/**
	 * @param veteranCity The veteranCity to set.
	 */
	public void setVeteranCity(String veteranCity) {
		this.veteranCity = veteranCity;
	}
	/**
	 * @return Returns the veteranState.
	 * @throws ServiceException
	 */
	public String getVeteranState()  {
		setVeteranRelatedProperties();
		return getString(veteranState);
	}
	/**
	 * @param veteranState The veteranState to set.
	 */
	public void setVeteranState(String veteranState) {
		this.veteranState = veteranState;
	}
	/**
	 * @return Returns the veteranCountry.
	 * @throws ServiceException
	 */
	public String getVeteranCountry() {
		setVeteranRelatedProperties();
		return getString(veteranCountry);
	}
	/**
	 * @param veteranCountry The veteranCountry to set.
	 */
	public void setVeteranCountry(String veteranCountry) {
		this.veteranCountry = veteranCountry;
	}
	/**
	 * @return Returns the veteranDateOfDeath.
	 * @throws ServiceException
	 */
	public String getVeteranDateOfDeath() {
		setVeteranRelatedProperties();
		return getString(veteranDateOfDeath);
	}
	/**
	 * @param veteranDateOfDeath The veteranDateOfDeath to set.
	 */
	public void setVeteranDateOfDeath(String veteranDateOfDeath) {
		this.veteranDateOfDeath = veteranDateOfDeath;
	}



	/// <summary>
	/// VeteranVISN: VA reginal network where the prrferred facility belongs to
	/// using lookup table to find right facility based on PreferredFacilityNumber
	/// </summary>
	public String getVisn()
	{
		return getString(vetVISN);
	}
	public void	setVisn(String visn)
	{
		this.vetVISN = visn;
	}

	/// <summary>
	/// veteran's home phone number
	/// </summary>
	public String getVeteranHomeTelephoneNumber()
	{
	    setVeteranRelatedProperties();
		return getString(homePhoneNumber);
	}
	public void	setVeteranHomeTelephoneNumber(String hmPhNum)
	{
		homePhoneNumber = hmPhNum;
	}
	/// <summary>
	/// veteran's work phone number
	/// </summary>
	public String getVeteranWorkTelephoneNumber()
	{
	    setVeteranRelatedProperties();
		return getString(workPhoneNumber);
	}
	public void setVeteranWorkTelephoneNumber(String workNum)
	{
		workPhoneNumber = workNum;
	}

	/// <summary>
	/// date of birth
	/// </summary>
	public String getVeteranDOB()
	{
	    setVeteranRelatedProperties();
		return getString(veteranDOB);
	}
	public void	setVeteranDOB(String dob)
	{
		veteranDOB = dob;
	}

	/*
	For Enrollment letters, SSN to use:
	The letter shall find SSN in the following order: SSA verified SSN (02) and site SSN (01).
	The letter shall use a pseudo SSN (03) automatically without user intervention if a SSN can not be found,
	The letter shall fail the rule 'isRequiredFieldsMissing()' if a pseudo SSN is still not found. The system shall not log the rule failure.
	*/
	public String getVeteranSsn()
	{
	    setVeteranRelatedProperties();
		return getString(veteranSsn);
	}
	public void	setVeteranSsn(String ssn)
	{
		veteranSsn = ssn;
	}

	/*
	 * Format SSN for easy-to-read format (e.g. 123456789 -> 123-45-6789)
	 * For unknown SSN format, jsut return it. 
	 */
	protected String FormatSSN(String ssn)
	{
		if (ssn != null && ssn.length() == 9 && ssn.indexOf("-") == -1)
		{
			StringBuffer hypenSsn = new StringBuffer();
			hypenSsn.append(ssn.substring(0,3));
			hypenSsn.append("-");
			hypenSsn.append(ssn.substring(3,5));
			hypenSsn.append("-");
			hypenSsn.append(ssn.substring(5));
			return hypenSsn.toString();
		}

		//otherwise, return the same as input
		return ssn;

	}
/*
GetOtherSSN is called when a SSA verified SSN is not available. This method is meant to
be overrided in the sub types to get the proper SSN to use.

SSN to use in comms letters:

1. IVM letters:
The letter shall only use SSA verified SSN
The letter shall fail exception 'SSN Is Verified By SSA'  on someone without SSA verified SSN 

2 Enrollment letters:
The letter shall find SSN in the following order: SSA verified SSN (02) and site SSN (01).
The letter shall use a pseudo SSN (03) automatically without user intervention if a SSN can not be found,
The letter shall fail the rule 'isRequiredFieldsMissing()' if a pseudo SSN is still not found. The system shall not log the rule failure.

3. SSN letters:
The letter shall not be triggered on someone with a verified SSN.
The letter shall not be triggered on someone with pseudo SSN only.
The letter shall search SSN with a non-empty 'SSN error message' in the following order: site SSN (01), edited SSN (04), and registry SSN (06).
The letter shall fail the rule 'isRequiredFieldsMissing()' if no SSN is found. The system shall not log the rule failure.

*/
	protected String GetVeteranOtherSSN()
	{
		return null;
	}


	/// <summary>
	/// Not used. Replaced with PrimaryVAFacilityNumber in EnrollmentTransmission.
	/// </summary>

	/// <summary>
	/// properties for TodaysDate 
	/// <\summary>
	public String getTodaysDate()
	{
		if (todaysDate == null) {
			synchronized(sdf) {
				todaysDate = sdf.format(new Date());
			}
		}

		return todaysDate;
	}
	public void setTodaysDate(String today)
	{
			todaysDate = today;	
	}
	/// <summary>
	/// this will be filled in
	/// </summary>
	//TODO: ???
	public String getMailingAddress()
	{
		return getString(mailingAddress);
	}
	public void	setMailingAddress(String mailAddr)
	{
		this.mailingAddress = mailAddr;
	}

	/// <summary>
	/// ?????
	/// </summary>
	//TODO: ???
	public String getUndelivRetAddress()
	{
		return getString(undelivRetAddress);
	}
	public void	setUndelivRetAddress(String undelAddr)
	{
		undelivRetAddress = undelAddr;
	}
	



	//TODO: All the contact and POA stuff!!
/*
	/// <summary>
	/// person who is responsible for this workload
	/// </summary>
	public String getContactPhoneNumber()
	{
		if ( contactPhoneNumber == null && PowerOfAttorney != null )
		{
			Address tmpAddress = SelectAddress (PowerOfAttorney);
			if(tmpAddress != null)
			{
				foreach(Telephone telephone in tmpAddress.Telephones)
				{
					if(telephone.TypeCd.Equals (Telephone.TYPE_WORK))
					{
						contactPhoneNumber = telephone.PhoneNum;
						break;
					}
				}
			}
		}
		return contactPhoneNumber;
	}
	public void	setContactPhoneNumber(String contPhNUm)
	{
		contactPhoneNumber = contPhNUm;
	}

	/// <summary>
	/// person who is responsible for this workload
	/// </summary>
	public String getContactName()
	{
		if ( contactName == null && PowerOfAttorney != null )
		{
			contactName = PowerOfAttorney.Name.FirstName;
			if(PowerOfAttorney.Name.MiddleName != null && PowerOfAttorney.Name.MiddleName.Length > 0)
				contactName += (" " + PowerOfAttorney.Name.MiddleName);
			contactName += (" " + PowerOfAttorney.Name.LastName);
		}
		return contactName;
	}
	public void	setContactName(String contName)
	{
		contactName = contName;
	}

	/// <summary>
	/// person who is responsible for this workload
	/// </summary>
	public String getContactAddress()
	{
		if ( contactAddress == null )
		{
			if ( PowerOfAttorney != null && PowerOfAttorney.Addresses != null )
			{
				Address tmpAddress = SelectAddress (PowerOfAttorney);
				if(tmpAddress != null)
				{
					contactAddress = tmpAddress.Line1;
					String line2 = tmpAddress.Line2;
					String line3 = tmpAddress.Line3;
					if ( line2 != null && line2.Length > 0 )
						contactAddress += ("\n" + line2);
					if ( line3 != null && line3.Length > 0 )
						contactAddress += ("\n" + line3);
				}
			}
		}
		return contactAddress;
	}
	public void	setContactAddress (String contAddr)
	{
		contactAddress = contAddr;
	}

	
	public String OriginationTypeCode
	{
		get
		{
			return originationTypeCode;
		}
		set
		{
			originationTypeCode = value;
		}
	}
*/	
	/*********************************
	 * Workload related: 
	 * - workload status/activity code
	 * - Application User Phone number *
	 *********************************/
	protected void setWorkloadRelatedProperties()
	{
		if(isWorkloadSet|| historicalCopy ||workflowCaseId == null)
			return;
		
		List workloadStatusLst = null;
/*		try{	
			workloadStatusLst = findWorkloadStatusByWorkflowCaseId(workflowCaseId);
		} catch (ServiceException se)
		{
			se.printStackTrace();
		}
*/		
		if (workloadStatusLst == null || workloadStatusLst.size() == 0)
		{
			isWorkloadSet = true;
			return;
		}
/*		
		//set workload status and activity code fields
		//order-by workload_status_update_date DESC,
		//the first one is the latest status
		WorkloadStatus workloadStatus = (WorkloadStatus)workloadStatusLst.get(0);
		this.workloadStatusCode = workloadStatus.getWorkloadStatType().getWorkloadStatTypeCode();
		
		if (workloadStatus.getWorkloadActivityLinks() != null ||
				workloadStatus.getWorkloadActivityLinks().size() > 0)
			this.workloadActivityCode =  ((gov.va.med.esr.common.model.WorkloadActivityLink)
					workloadStatus.getWorkloadActivityLinks().iterator().next()).getWorkloadActivity().getWorkloadActivityCode();
		
		//and set app user telephone number
		AppUser appuser = workloadStatus.getAppUser();
		currentRepPhoneNumber = appuser.getAppUserPhoneNumber();
		currentRepresentative = appuser.getAppUserGivenName() + " " + appuser.getAppUserFamilyName();
*/			
		isWorkloadSet = true;
	}	
	
	/*******************************
	 * Workload related properties *
	 *******************************/
	/**
	 * @return Returns the workloadActivityCode.
	 */
	public String getWorkloadActivityCode() {
		setWorkloadRelatedProperties();
		return getString(workloadActivityCode);
	}
	/**
	 * @param workloadActivityCode The workloadActivityCode to set.
	 */
	public void setWorkloadActivityCode(String workloadActivityCode) {
		this.workloadActivityCode = workloadActivityCode;
	}
	/**
	 * @return Returns the workloadStatusCode.
	 */
	public String getWorkloadStatusCode() {
		setWorkloadRelatedProperties();
		return getString(workloadStatusCode);
	}
	/**
	 * @param workloadStatusCode The workloadStatusCode to set.
	 */
	public void setWorkloadStatusCode(String workloadStatusCode) {
		this.workloadStatusCode = workloadStatusCode;
	}
	/// <summary>
	/// properties for CurrentRepPhoneNumber 
	/// <\summary>
	public String getCurrentRepresentativeTelephone()
	{
		setWorkloadRelatedProperties();
		return getString(currentRepPhoneNumber);		
	}
	
	public void setCurrentRepresentativeTelephone(String repNumber)
	{
			currentRepPhoneNumber = repNumber;
	}
	/// <summary>
	/// application user for this workload
	/// </summary>
	public String getCurrentRepresentative()
	{
	    setWorkloadRelatedProperties();
		return getString(currentRepresentative);
	}
	public void	setCurrentRepresentative(String currRep)
	{
		currentRepresentative = currRep;
	}
	
    /**
     * @return Returns the userNumber.
     */
    public String getUserNumber() {
        return getString(userNumber);
    }
    /**
     * @param userNumber The userNumber to set.
     */
    public void setUserNumber(String userNumber) {
        this.userNumber = userNumber;
    }

    /**
     * @return Returns the aacVersionNumber.
     */
    public String getAacVersionNumber() {
        return getString(aacVersionNumber);
    }
    /**
     * @param aacVersionNumber The aacVersionNumber to set.
     */
    public void setAacVersionNumber(String aacVersionNumber) {
        this.aacVersionNumber = aacVersionNumber;
    }
    /**
     * @return Returns the barcodeData.
     */
    public String getBarcodeData() {
        return getString(barcodeData);
    }
    /**
     * @param barcodeData The barcodeData to set.
     */
    public void setBarcodeData(String barcodeData) {
        this.barcodeData = barcodeData;
    }
    /**
     * @return Returns the caseNumber.
     */
    public String getCaseNumber() {
        return getString(caseNumber);
    }
    /**
     * @param caseNumber The caseNumber to set.
     */
    public void setCaseNumber(String caseNumber) {
        this.caseNumber = caseNumber;
    }
    /**
     * @return Returns the formNumber.
     */
    public String getFormNumber() {
        return getString(formNumber);
    }
    /**
     * @param formNumber The formNumber to set.
     */
    public void setFormNumber(String formNumber) {
        this.formNumber = formNumber;
    }
    /**
     * @return Returns the stationNumber.
     */
    public String getStationNumber() {
        return getString(stationNumber);
    }
    /**
     * @param stationNumber The stationNumber to set.
     */
    public void setStationNumber(String stationNumber) {
        this.stationNumber = stationNumber;
    }

    /**
     * @return Returns the workflowCaseId.
     */
    public BigDecimal getworkflowCaseId() {
        return workflowCaseId;
    }
    /**
     * @param workflowCaseId The workflowCaseId to set.
     */
    public void setworkflowCaseId(BigDecimal workflowCaseId) {
        this.workflowCaseId = workflowCaseId;
    }
    
    /// <summary>
	/// provide cached information for local use only
	/// </summary>
/*	
	protected Address LocalPoaAddress
	{
		get
		{
			if ( localPoaAddress == null && PowerOfAttorney != null && !historicalCopy )
				localPoaAddress = GetPersonAddress (PowerOfAttorney);
			return localPoaAddress;
		}
	}
*/
	//--------------------------------------------------------------------
	// Public method(s)
	//--------------------------------------------------------------------
/*
	private static boolean isActiveMailingAddress (Address addr, VHAImpreciseDate date)
	{
		//SELECT  address_role_type_code, address_line_1, address_line_2, address_line_3, address_city_text, state_code, address_postal_code_text, address.ADDRESS_IDENTIFIER, zip_code, address.country_code from ADDRESS WHERE ADDRESS.VETERAN_IDENTIFIER = :PersonID AND 
		//( (invalid_reas_code IS NULL) OR (address_invalid_date IS NULL) OR (address_invalid_date > SYSDATE-1) ) 
		//AND ( (address_start_date IS NULL) OR (address_start_date < SYSDATE ) ) AND ( (address_end_date IS NULL) OR (address_end_date > SYSDATE-1) )
		if (addr == null)
			return false;
		return ( ((addr.StartDt == null) || (addr.StartDt != null) && (addr.StartDt.CompareTo(date) <=0)) &&
				 ((addr.EndDt == null) || (addr.EndDt != null) && (addr.EndDt.CompareTo(date) >=0)) &&
				 (addr.UndeliverableDt == null) &&
				 (addr.UndeliverableReasonCd == null) );
	}
*/


	/// <summary>
	/// CreateInstanceByXml Accepts a String containing an EDB xml 
	/// document and uses it to materialize an Transmission object instance.
	/// </summary>
	/// 
	/// <returns>object, can be either EnrollTransmission or SSNTransmission</returns>
	/// <param name="xmlDoc"></param>

	//TODO: implement this!!
	public static Object CreateInstanceByXml ( String xmlDoc)
	{
/*	    
		GeneralTransmission transmission = null;
		XmlNodeReader reader = null;
		
		try
		{
			XmlSerializer serializer = new XmlSerializer(transmissionType);
			XmlDocument doc = new XmlDocument();
			doc.LoadXml(xmlDoc); 
			reader = new XmlNodeReader(doc);
			transmission = (GeneralTransmission)serializer.Deserialize(reader);
		}
		finally
		{
			if (reader != null)
				reader.Close();
			reader = null;
		}

		transmission.historicalCopyCopy(true);
		return transmission;
*/
	    return null;
		}

	/// <summary>
	/// externalizeAsXml to transform the bject state into EDB XML String
	/// </summary>
	/// 
	/// <returns>String</returns>
	public String externalizeAsXml()
	{
/*	    
		StringWriter strWriter = new StringWriter();
		XmlTextWriter writer = new XmlTextWriter (strWriter);

		Type transmisstionType = GetType ();
		writer.Formatting = Formatting.None; //save some spaces (15-25%) wo/idented
		writer.WriteStartDocument(true);
		writer.WriteDocType (transmisstionType.FullName, null, null, null);

		XmlSerializer serializer = new XmlSerializer(transmisstionType);
		try
		{
			serializer.Serialize(writer, this);
		} 
		catch (Exception ex)
		{
			throw ex.InnerException;
		}

		writer.Close();
		strWriter.Close();

		return strWriter.toString();
*/
	    return null;
 		
	}

	/// <summary>
	/// Set the data elements used for this letter. The Hashtable is used by
	/// isRequiredFieldsMissing(). Sub classes may want to override it for 
	/// processing special data elements (e.g. anything within MergeSpecial in Formatter)
	/// </summary>
	/// 
	/// <returns>String</returns>
	public void SetTemplateDataElements(Hashtable dataElemTable)
	{
		if (dataElemTable != null)
		{
			dataElemTable.remove("Attachments"); //remove special tag: Attachments
			dataElemTable.remove("BarcodeData"); 
		}
		dataElementTable = dataElemTable; 
	}
	
	public void setCommsLog(List logs)
	{
	    this.logs = logs;
	}
	
/*	public void setWorkflowCase(WorkflowCase wkfCase)
	{
	    this.wkfCase = wkfCase;
	}*/

	//--------------------------------------------------------------------
	// Protected method(s)
	//--------------------------------------------------------------------


	/// <summary>
	/// convert person address object to a multi line String
	/// </summary>
	/// <param name="personAddress"></param>
	/// <returns></returns>
	protected String getMultiLineAddress (Address personAddress)
	{
		if (personAddress == null)
			return null;
		StringBuffer multiLineAddress = new StringBuffer ();
		multiLineAddress.append (personAddress.getLine1());
		if (personAddress.getLine2() != null && personAddress.getLine2().length() > 0)
			multiLineAddress.append ("\n").append (personAddress.getLine2());
		if (personAddress.getLine3() != null && personAddress.getLine3().length() > 0)
			multiLineAddress.append ("\n").append (personAddress.getLine3());
		return getString(multiLineAddress.toString ());
	}
/*
	protected VHA.Enrollment.Business.Person.Person PowerOfAttorney
	{
		get
		{
			if (powerOfAttorney == null && VeteranRepresentatives != null && !historicalCopy)
			{
				foreach (VHA.Enrollment.Business.Person.Person rep in VeteranRepresentatives)
				{
					if ( rep.VeteranRepresentativeRole != null && rep.VeteranRepresentativeRole.TypeCd != null )
						if ( rep.VeteranRepresentativeRole.TypeCd.Equals (VeteranRepresentativeRole.TYPE_POWER_OF_ATTORNEY) )
						{
							powerOfAttorney = rep;
							break;
						}
				}
			}
			return powerOfAttorney;
		}
	}
*/	

	/// <summary>
	/// get a collection of veteran representatives
	/// </summary>
	protected List getVeteranRepresentatives()
	{
/*	    
		if ( veteranRepresentatives == null && !historicalCopy )
			veteranRepresentatives = VeteranRepresentativeBroker.GetBrokerInstance ().GetCurrentVetRepsByVetId (VeteranId);
*/		return veteranRepresentatives;
	}



	/**************
	 *            *
	 *  Exceptions*
	 *            *
	 * ************/
/*
	public boolean isVeteranNotHomeless ()
	{
		if ( Veteran != null && Veteran.IsHomeless == null )
			return true;
		return !Veteran.IsHomeless.IsTrue ();
	}

	public boolean noDateOfDeathExists()
	{
		if (Veteran != null && Veteran.Death == null || Veteran.Death.DeathDt == null )
			return true;
			
		return false;
	}
	
	public boolean isAddressDeliverable ()
	{
		if (LocalVeteranAddress == null)
			return false;

		return true;
	}

	public boolean isSsnVerifiedBySSA ()
	{
		if (Veteran != null)
		{
			String ssaVerificationStatusCd = Veteran.SsaVerificationStatusCd;
			return ssaVerificationStatusCd != null && ssaVerificationStatusCd.equals("02");
		}
		return false;
	}


	public virtual boolean isRequiredFieldsMissing () 
	{
		//!!!!!! Temporary disable this for SQA testing !!!!!!!!

		return false;

		// 1. populate (with reflection) the data elements table with value
		// 2. if any data element value is null, return false
		// 3. the hashtable can be used by formatter

		boolean result = false;

		if (dataElementTable == null || dataElementTable.Count == 0)
			return result;

		String [] nameArray = new String[dataElementTable.Count];
		dataElementTable.Keys.CopyTo(nameArray,0);

		Type objType = this.GetType();
		System.Reflection.PropertyInfo prop = null;
		object tagValue = null;

//ArrayList misMatched = new ArrayList();
		for (int i=0; i< nameArray.Length; i++)
		{
			prop = objType.GetProperty(nameArray[i]);
			if (prop != null)
			{
				tagValue = prop.GetValue(this, null);

				if(tagValue == null)
				{
					missingDataElements.Add(nameArray[i]); //add name for the missing data element
					result = true;
				} 
				else
				{
					dataElementTable[nameArray[i]] = tagValue.toString();
				}
			} 
			else
			{
//misMatched.Add(nameArray[i]);
				//not a valid data element!
				throw new Exception("Invalid Data Element: " + nameArray[i] 
					+ "!! Data element from database does not match the transmission object");

			}
		}		

		return result;
	}

	/// <summary>
	/// Get the names of missing data element (failed IsRequiredFieldsMissing)
	/// </summary>
	/// <returns></returns>
	public ICollection GetMissingDataElements()
	{
		return missingDataElements;
	}



	//Exception: Only a Pseudo SSN Exists
	public virtual boolean HasPseudoSSNOnly()
	{
		if ((VeteranSsn == null || VeteranSsn.Length ==0) &&
			(VeteranPseudoSSN != null && VeteranPseudoSSN.Length > 0))
			return true;

		return false;
	}

	//Duplicate Record Exists
	public boolean HasDuplicateRecord()
	{
		//TODO: this use case has not been started yet! Talk to Kes
		return false;
	}
*/
	public boolean isHistoricalCopy()
	{
		return historicalCopy;
	}
	
	public void isHistoricalCopy(boolean isHist)
	{
		historicalCopy = isHist;
	}

    /**
     * @return Returns the lookupService.
     */
    public LookupService getLookupService() {
        return lookupService;
    }
    /**
     * @param lookupService The lookupService to set.
     */
    public void setLookupService(LookupService lookupService) {
        this.lookupService = lookupService;
    }
	/**************************************
	 *  Rules common to all transmissions *
	 * ************************************/



	protected boolean isThisAddressDeliverable(Address addr)
	{
		//handle both US and forgien address now (GetState() and GetZipPostalCode())
		return (addr != null &&
/*
	    (addr.getAddressLine1() != null && addr.getAddressLine1().length() > 0) &&
		(addr.getAddressCity() != null && addr.getAddressCity().length() > 0) &&
		(addr.State != null && GetState(addr).Length > 0) &&
		(addr.Zip != null && this.GetZipPostalCode(addr).Length > 0));
*/		(addr.getLine1() != null && addr.getLine1().length() > 0) &&
		(addr.getCity() != null && addr.getCity().length() > 0) &&
		(addr.getState() != null && addr.getPostalCode().length() > 0) &&
		(addr.getZipCode() != null && addr.getZipCode().length() > 0));
	}
	//--------------------------------------------------------------------
	// Private method(s)
	//--------------------------------------------------------------------

	//mailing status of 0-send, 01-sent, 02-mailed by HEC, 07 mailed by AAC
	//rejected mail does not count
	private boolean isLetterMailedAfterDays (List mailingStatusLinkLst, int days)
	{
	    if (mailingStatusLinkLst == null || mailingStatusLinkLst.size() == 0)
	        return false;
	    
	    String statusCd = null;
	    MailingStatusLink link = null;
	    for (int i=0; i< mailingStatusLinkLst.size(); i++)
	    {
	        link = ((MailingStatusLink)mailingStatusLinkLst.get(i));
	        statusCd = link.getMailingStatus().getCode();
	 
			if (statusCd != null && 
				statusCd.equals("0") || statusCd.equals("01") || 
				statusCd.equals("02") || statusCd.equals("07"))
			{
			    //mailed, now chech days
			    if (days == 0)
			        return true;
			    else
			        return (this.todayDt.compareTo(LetterFormatHelper.addDays(todayDt, days)) >=0);
			}
	    }
		return false;
	}

	//--------------------------------------------------------------------
	// Non-static attributes
	//--------------------------------------------------------------------

	protected PersonHelperService helperService;
	//used by SSNTransmission
//	protected AppUser applicationUser;
	
	protected List logs;
	
//	protected Set ssns = null;
	
	protected Person vet;

	//used by SSNTransmission
	protected Hashtable dataElementTable = null;
	protected String vetVISN = null;

	//used by rule- HasPseudoOnly
	protected boolean hasPseudoSSNOnly;


	protected Date todayDt = null;
	
	protected GregorianCalendar cal = null;
	

	private String caseNumber; //passin
	private String barcodeData;
	private Address localVeteranAddress;
	private String formNumber = EMPTY_STRING;
	private String incomeYear; //pass in
	private String aacVersionNumber; //pass in
	private BigDecimal workflowCaseId; //pass in

	private static Hashtable addressPriorityTable;

	private List veteranRepresentatives;
//	private VHA.Enrollment.Business.Person.Person powerOfAttorney;

	private String currentRepresentative;
	private String currentRepresentativePhone;

	//veteran info.
	private boolean vetSsnVerified;
	private String vetTitle;
	private String veteranFirstName;
	private String veteranLastName;
	private String veteranMiddleName;
	private String veteranSuffix;
	private AddressType veteranAddressType;
	private String veteranAddressLine1;
	private String veteranAddressLine2;
	private String veteranAddressLine3;
	private String veteranCity;
	private String veteranState;
	private String veteranCountyOrProvince;
	private String veteranZipCodeOrPostalCode;
	private String veteranCountry;
	private String veteranCountryName;
	private String veteranDateOfDeath;
	private String homePhoneNumber;
	private String workPhoneNumber;
	
	protected String veteranSsn;
	private String stationNumber;
	private String todaysDate;
	private String undelivRetAddress;;
	private String veteranGender;
	private String userNumber;

	private String veteranName;
	private String veteranDOB;

	private String workloadStatusCode;
	private String workloadActivityCode;
	private String currentRepPhoneNumber; //pass in if available
		
	private String mailingAddress;


	private ArrayList missingDataElements = new ArrayList();
	
	private Address mailingAdress = null;

	private String originationTypeCode;
	
	private String veteranPersonIdentifier = null;
	
	protected LookupService lookupService = null;	
    
    /**
     * @return Returns the mailingAdrr.
     */
    public Address getMailingAdress() {
        setVeteranRelatedProperties();
        return mailingAdress;
    }
    /**
     * @param mailingAdrr The mailingAdrr to set.
     */
    public void setMailingAdress(Address mailingAdress) {
        this.mailingAdress = mailingAdress;
    }

	/**
	 * @return Returns the veteranCountyOrProvince.
	 */
	public String getVeteranCountyOrProvince() {
		setVeteranRelatedProperties();		
		return getString(veteranCountyOrProvince);
	}

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

	/**
	 * @return Returns the veteranZipCodeOrPostalCode.
	 */
	public String getVeteranZipCodeOrPostalCode() {
		setVeteranRelatedProperties();
		return getString(veteranZipCodeOrPostalCode);
	}

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


	/**
	 * @return Returns the veteranCountryName.
	 */
	public String getVeteranCountryName() {
		setVeteranRelatedProperties();
		return getString(veteranCountryName);
	}

	/**
	 * @param veteranCountryName The veteranCountryName to set.
	 */
	public void setVeteranCountryName(String veteranCountryName) {
		this.veteranCountryName = veteranCountryName;
	}
	
	/* It is important that this is an ordered List for usage in AACExportCommand */
	public List getPOAsWithAddresses() {
		List poas = new ArrayList();
		if (vet == null || vet.getAssociations() == null
				|| vet.getAssociations().size() == 0)
			return poas;

		//want  all POAs (could be more than one)
		Set assocs = vet.getAssociations();
		Iterator itr = assocs.iterator();
		Association assoc = null;
		while(itr.hasNext()) {
			assoc = (Association) itr.next();
			if(assoc.getType() != null && assoc.getType().getCode().equals(AssociationType.CODE_POWER_OF_ATTORNEY.getCode())) {
				// the POA must have a non-null Address
				if(assoc.getAddress() != null)
					poas.add(assoc);
			}
		}
		return poas;
	}
	
	// CCR 12825
	public Name getPrimaryNextOfKinName() {
		setVeteranRelatedProperties();		
		Name nokName = null;
		if (vet != null) {
			Association primaryNok = Association.getAssociationOfType(vet.getAssociations(), 
					AssociationType.CODE_PRIMARY_NEXT_OF_KIN.getCode());
			nokName = primaryNok != null ? primaryNok.getRepresentativeName() : null;			
		}
		return nokName;
	}

	// CCR 12825	
	public String getVeteranPersonIdentifier() {
		setVeteranRelatedProperties();		
		return this.getString(veteranPersonIdentifier);
	}

	// CCR 12825	
	public void setVeteranPersonIdentifier(String veteranPersonIdentifier) {
		this.veteranPersonIdentifier = veteranPersonIdentifier;
	}
}
