/********************************************************************
 * Copyright © 2006 VHA. All rights reserved
 ********************************************************************/


package gov.va.med.esr.common.batchprocess.datasync;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.collections.OrderedMap;
import org.apache.commons.collections.map.ListOrderedMap;
import org.apache.commons.lang.builder.ToStringBuilder;

import com.infomata.data.DataRow;

import gov.va.med.fw.io.AbstractRawFileDataContainer;
import gov.va.med.fw.io.ClassMapping;
import gov.va.med.fw.io.RawFileDataContainerUtils;
import gov.va.med.fw.util.StringUtils;

import gov.va.med.esr.common.batchprocess.DateFieldTransformer;
import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.ee.RatedDisability;
import gov.va.med.esr.common.model.lookup.AgentOrangeExposureLocation;
import gov.va.med.esr.common.model.lookup.DiagnosticExtremity;
import gov.va.med.esr.common.model.lookup.Disability;
import gov.va.med.esr.common.model.lookup.EligibilityStatus;
import gov.va.med.esr.common.model.lookup.EligibilityType;
import gov.va.med.esr.common.model.lookup.EmergencyResponse;
import gov.va.med.esr.common.model.lookup.RadiationExposureMethod;

/**
 * Initial javadoc for class HECLegacyEligibilityFileData.
 * TODO - Add content here
 * 
 * Created Mar 14, 2006 10:15:25 PM
 * @author DNS   BOHMEG
 */
public class HECLegacyEligibilityFileData extends AbstractRawFileDataContainer {
	/**
	 * 
	 */
	private static final long serialVersionUID = 25696906143571028L;
	private EligibilityStatus eligibilityStatus;
	private ImpreciseDate eligibilityStatusDate;
	private String eligibilityVerificationMethod;
	private EligibilityType eligibilityCode;
	private Set otherEligibilityCodes = new HashSet(); 
	private String serviceConnected;
	private Integer serviceConnectedPercentage;
	private String unemployable;
	private String pAndT;
	private ImpreciseDate pAndTEffectiveDate;
	private Set ratedDisabilities = new HashSet();
	private ImpreciseDate combinedSCPercentEffectiveDate;
	private String receivingVAPension;
	private String receivingAABenefits;
	private String receivingHouseholdBenefits;
	private String eligibleForMedicaid;
	private String dischargeDueToDisability;
	private String militaryDisabilityRetirement;
	private String receivingVADisability;
	private BigDecimal totalAnnualVACheckAmount;
	private String powStatusIndicated;
	private String ratedIncompetent;
	private ImpreciseDate ineligibleDate;
	private String ineligibleReason;
	private String ineligibleVaroDecision;
	private String exposedToAgentOrange;
	private AgentOrangeExposureLocation agentOrangeExposureLocation;
	private String radiationExposureIndicator;
	private RadiationExposureMethod radiationExposureMethod;
	private String environmentalContaminants;
	private String veteranIndicator;
	private EmergencyResponse emergencyResponse;
    
    private static final int VERIFY_METHOD_MAX_LENGTH = 50;
	
	static {
		RawFileDataContainerUtils.autoRegisterConvertersForClass();
	}
	
	/* (non-Javadoc)
	 * @see gov.va.med.fw.model.AbstractEntity#buildToString(org.apache.commons.lang.builder.ToStringBuilder)
	 */
	protected void buildToString(ToStringBuilder builder) {
		// TODO Auto-generated method stub

	}

	/**
	 * @return Returns the eligibilityVerificationMethod.
	 */
	public String getEligibilityVerificationMethod() {
		return eligibilityVerificationMethod;
	}

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

	/**
	 * @return Returns the dischargeDueToDisability.
	 */
	public String getDischargeDueToDisability() {
		return dischargeDueToDisability;
	}

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

	/**
	 * @return Returns the eligibleForMedicaid.
	 */
	public String getEligibleForMedicaid() {
		return eligibleForMedicaid;
	}

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

	/**
	 * @return Returns the environmentalContaminants.
	 */
	public String getEnvironmentalContaminants() {
		return environmentalContaminants;
	}

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

	/**
	 * @return Returns the exposedToAgentOrange.
	 */
	public String getExposedToAgentOrange() {
		return exposedToAgentOrange;
	}

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


	/**
	 * @return Returns the ineligibleReason.
	 */
	public String getIneligibleReason() {
		return ineligibleReason;
	}

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

	/**
	 * @return Returns the ineligibleVaroDecision.
	 */
	public String getIneligibleVaroDecision() {
		return ineligibleVaroDecision;
	}

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

	/**
	 * @return Returns the militaryDisabilityRetirement.
	 */
	public String getMilitaryDisabilityRetirement() {
		return militaryDisabilityRetirement;
	}

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

	/**
	 * @return Returns the pAndT.
	 */
	public String getPAndT() {
		return pAndT;
	}

	/**
	 * @param andT The pAndT to set.
	 */
	public void setPAndT(String andT) {
		pAndT = andT;
	}


	/**
	 * @return Returns the powStatusIndicated.
	 */
	public String getPowStatusIndicated() {
		return powStatusIndicated;
	}

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

	/**
	 * @return Returns the radiationExposureIndicator.
	 */
	public String getRadiationExposureIndicator() {
		return radiationExposureIndicator;
	}

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

	/**
	 * @return Returns the ratedIncompetent.
	 */
	public String getRatedIncompetent() {
		return ratedIncompetent;
	}

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

	/**
	 * @return Returns the receivingAABenefits.
	 */
	public String getReceivingAABenefits() {
		return receivingAABenefits;
	}

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

	/**
	 * @return Returns the receivingHouseholdBenefits.
	 */
	public String getReceivingHouseholdBenefits() {
		return receivingHouseholdBenefits;
	}

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

	/**
	 * @return Returns the receivingVADisability.
	 */
	public String getReceivingVADisability() {
		return receivingVADisability;
	}

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

	/**
	 * @return Returns the receivingVAPension.
	 */
	public String getReceivingVAPension() {
		return receivingVAPension;
	}

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

	/**
	 * @return Returns the serviceConnected.
	 */
	public String getServiceConnected() {
		return serviceConnected;
	}

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

	/**
	 * @return Returns the unemployable.
	 */
	public String getUnemployable() {
		return unemployable;
	}

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

	/**
	 * @return Returns the combinedSCPercentEffectiveDate.
	 */
	public ImpreciseDate getCombinedSCPercentEffectiveDate() {
		return combinedSCPercentEffectiveDate;
	}

	/**
	 * @param combinedSCPercentEffectiveDate The combinedSCPercentEffectiveDate to set.
	 */
	public void setCombinedSCPercentEffectiveDate(
			ImpreciseDate combinedSCPercentEffectiveDate) {
		this.combinedSCPercentEffectiveDate = combinedSCPercentEffectiveDate;
	}

	/**
	 * @return Returns the eligibilityStatusDate.
	 */
	public ImpreciseDate getEligibilityStatusDate() {
		return eligibilityStatusDate;
	}

	/**
	 * @param eligibilityStatusDate The eligibilityStatusDate to set.
	 */
	public void setEligibilityStatusDate(ImpreciseDate eligibilityStatusDate) {
		this.eligibilityStatusDate = eligibilityStatusDate;
	}

	/**
	 * @return Returns the ineligibleDate.
	 */
	public ImpreciseDate getIneligibleDate() {
		return ineligibleDate;
	}

	/**
	 * @param ineligibleDate The ineligibleDate to set.
	 */
	public void setIneligibleDate(ImpreciseDate ineligibleDate) {
		this.ineligibleDate = ineligibleDate;
	}

	/**
	 * @return Returns the pAndTEffectiveDate.
	 */
	public ImpreciseDate getPAndTEffectiveDate() {
		return pAndTEffectiveDate;
	}

	/**
	 * @param andTEffectiveDate The pAndTEffectiveDate to set.
	 */
	public void setPAndTEffectiveDate(ImpreciseDate andTEffectiveDate) {
		pAndTEffectiveDate = andTEffectiveDate;
	}
	
	private void parseRatedDisabilities(String ratedDisabilitiesString) throws ParseException {		
		if(StringUtils.isBlank(ratedDisabilitiesString))
			return;
		
		Object[] groupedData = RawFileDataContainerUtils.parseMultipleValues(ratedDisabilitiesString, HECLegacyDataSynchronizationConstants.Delimiters.SECONDARY,
				HECLegacyDataSynchronizationConstants.Delimiters.TERTIARY, 6);		

		String[] data = null;
		int j = 0;
		try {
			for(int i=0; i<groupedData.length; i++) {
				data = (String[]) groupedData[i];
				RatedDisability rd = new RatedDisability();
				j = 0;
				rd.setDisability((Disability) RawFileDataContainerUtils.convertToLookup(Disability.class, data[j++]));			
				rd.setPercentage(Integer.valueOf(data[j++]));
				rd.setServiceConnected(Boolean.valueOf(data[j++]));
				rd.setDiagnosticExtremity((DiagnosticExtremity) RawFileDataContainerUtils.convertToLookup(DiagnosticExtremity.class, data[j++]));
				RawFileDataContainerUtils.setConvertedField(rd, "originalEffectiveRatingDate", data[j++]);
				RawFileDataContainerUtils.setConvertedField(rd, "ratingDate", data[j++]);				
				ratedDisabilities.add(rd);
			}
		} catch(Exception e) {
			ParseException e2 = new ParseException("Unable to parse text: " + data[j - 1], j - 1);
			e2.initCause(e);
			throw e2;			
		}
	}
	
	private String formatRatedDisabilities() throws Exception {
		StringBuffer buf = new StringBuffer();
		Iterator itr = ratedDisabilities != null ? ratedDisabilities.iterator() : null;
		RatedDisability rd = null;
		DateFieldTransformer tran = new DateFieldTransformer();
		tran.setDateFormat(HECLegacyDataSynchronizationConstants.Formats.DATE);
		while(itr != null && itr.hasNext()) {
			rd = (RatedDisability) itr.next();
			buf.append(RawFileDataContainerUtils.formatLookup(rd.getDisability())).append(HECLegacyDataSynchronizationConstants.Delimiters.TERTIARY);
			buf.append(rd.getPercentage() != null ? rd.getPercentage().toString() : StringUtils.EMPTY).append(HECLegacyDataSynchronizationConstants.Delimiters.TERTIARY);
			// all ESR RatedDisability's are ServiceConnected
			buf.append(HECLegacyDataSynchronizationProducerProcess.TRUE).append(HECLegacyDataSynchronizationConstants.Delimiters.TERTIARY);
			buf.append(RawFileDataContainerUtils.formatLookup(rd.getDiagnosticExtremity())).append(HECLegacyDataSynchronizationConstants.Delimiters.TERTIARY);
			buf.append(rd.getOriginalEffectiveRatingDate() != null ? tran.transformData("", rd.getOriginalEffectiveRatingDate()) : StringUtils.EMPTY).append(HECLegacyDataSynchronizationConstants.Delimiters.TERTIARY);
			buf.append(rd.getRatingDate() != null ? tran.transformData("", rd.getRatingDate()) : StringUtils.EMPTY);
			if(itr.hasNext())
				buf.append(HECLegacyDataSynchronizationConstants.Delimiters.SECONDARY);
		}
		return buf.toString();
	}
	
	/* (non-Javadoc)
	 * @see gov.va.med.fw.io.parser.RawFileDataContainer#setRawFileData(java.lang.String, com.infomata.data.DataRow)
	 */
	public void setRawFileData(String rawFileData, DataRow parsedRow, ClassMapping classMapping) throws Exception {
		int i=1; // ignore first element (data type)
		RawFileDataContainerUtils.setConvertedField(this, "eligibilityStatus", parsedRow.getString(i++));
		RawFileDataContainerUtils.setConvertedField(this, "eligibilityStatusDate", parsedRow.getString(i++));
		eligibilityVerificationMethod = StringUtils.truncToMaxLength(parsedRow.getString(i++), VERIFY_METHOD_MAX_LENGTH);
		RawFileDataContainerUtils.setConvertedField(this, "eligibilityCode", parsedRow.getString(i++));
		otherEligibilityCodes = RawFileDataContainerUtils.parseMultipleLookupValues(parsedRow.getString(i++),
				HECLegacyDataSynchronizationConstants.Delimiters.SECONDARY, EligibilityType.class);		
		serviceConnected = parsedRow.getString(i++);
		RawFileDataContainerUtils.setConvertedField(this, "serviceConnectedPercentage", parsedRow.getString(i++));
		unemployable = parsedRow.getString(i++);
		pAndT = parsedRow.getString(i++);
		RawFileDataContainerUtils.setConvertedField(this, "pAndTEffectiveDate", parsedRow.getString(i++));
		parseRatedDisabilities(parsedRow.getString(i++));
		RawFileDataContainerUtils.setConvertedField(this, "combinedSCPercentEffectiveDate", parsedRow.getString(i++));
		receivingVAPension = parsedRow.getString(i++);
		receivingAABenefits = parsedRow.getString(i++);
		receivingHouseholdBenefits = parsedRow.getString(i++);
		eligibleForMedicaid = parsedRow.getString(i++);
		dischargeDueToDisability = parsedRow.getString(i++);
		militaryDisabilityRetirement = parsedRow.getString(i++);
		receivingVADisability = parsedRow.getString(i++);
		RawFileDataContainerUtils.setConvertedField(this, "totalAnnualVACheckAmount", parsedRow.getString(i++));
		powStatusIndicated = parsedRow.getString(i++);
		ratedIncompetent = parsedRow.getString(i++);
		RawFileDataContainerUtils.setConvertedField(this, "ineligibleDate", parsedRow.getString(i++));
		ineligibleReason = parsedRow.getString(i++);
		ineligibleVaroDecision = parsedRow.getString(i++);
		exposedToAgentOrange = parsedRow.getString(i++);
		RawFileDataContainerUtils.setConvertedField(this, "agentOrangeExposureLocation", parsedRow.getString(i++));
		radiationExposureIndicator = parsedRow.getString(i++);
		RawFileDataContainerUtils.setConvertedField(this, "radiationExposureMethod", parsedRow.getString(i++));
		environmentalContaminants = parsedRow.getString(i++);
		veteranIndicator = parsedRow.getString(i++);
		RawFileDataContainerUtils.setConvertedField(this, "emergencyResponse", parsedRow.getString(i++));
	}

	/**
	 * @return Returns the agentOrangeExposureLocation.
	 */
	public AgentOrangeExposureLocation getAgentOrangeExposureLocation() {
		return agentOrangeExposureLocation;
	}
	
	/**
	 * @param agentOrangeExposureLocation The agentOrangeExposureLocation to set.
	 */
	public void setAgentOrangeExposureLocation(
			AgentOrangeExposureLocation agentOrangeExposureLocation) {
		this.agentOrangeExposureLocation = agentOrangeExposureLocation;
	}

	/**
	 * @return Returns the radiationExposureMethod.
	 */
	public RadiationExposureMethod getRadiationExposureMethod() {
		return radiationExposureMethod;
	}

	/**
	 * @param radiationExposureMethod The radiationExposureMethod to set.
	 */
	public void setRadiationExposureMethod(
			RadiationExposureMethod radiationExposureMethod) {
		this.radiationExposureMethod = radiationExposureMethod;
	}

	/**
	 * @return Returns the totalAnnualVACheckAmount.
	 */
	public BigDecimal getTotalAnnualVACheckAmount() {
		return totalAnnualVACheckAmount;
	}

	/**
	 * @param totalAnnualVACheckAmount The totalAnnualVACheckAmount to set.
	 */
	public void setTotalAnnualVACheckAmount(BigDecimal totalAnnualVACheckAmount) {
		this.totalAnnualVACheckAmount = totalAnnualVACheckAmount;
	}

	/**
	 * @return Returns the eligibilityCode.
	 */
	public EligibilityType getEligibilityCode() {
		return eligibilityCode;
	}

	/**
	 * @param eligibilityCode The eligibilityCode to set.
	 */
	public void setEligibilityCode(EligibilityType eligibilityCode) {
		this.eligibilityCode = eligibilityCode;
	}

	/**
	 * @return Returns the otherEligibilityCodes.
	 */
	public Set getOtherEligibilityCodes() {
		return otherEligibilityCodes;
	}

	/**
	 * @return Returns the eligibilityStatus.
	 */
	public EligibilityStatus getEligibilityStatus() {
		return eligibilityStatus;
	}

	/**
	 * @param eligibilityStatus The eligibilityStatus to set.
	 */
	public void setEligibilityStatus(EligibilityStatus eligibilityStatus) {
		this.eligibilityStatus = eligibilityStatus;
	}

	/**
	 * @return Returns the ratedDisabilities.
	 */
	public Set getRatedDisabilities() {
		return ratedDisabilities;
	}

	/**
	 * @return Returns the emergencyResponse.
	 */
	public EmergencyResponse getEmergencyResponse() {
		return emergencyResponse;
	}

	/**
	 * @param emergencyResponse The emergencyResponse to set.
	 */
	public void setEmergencyResponse(EmergencyResponse emergencyResponse) {
		this.emergencyResponse = emergencyResponse;
	}

	/* (non-Javadoc)
	 * @see gov.va.med.fw.io.RawFileDataContainer#getRawFileData()
	 */
	public OrderedMap getRawFileData() throws Exception {
		OrderedMap map = new ListOrderedMap();
		map.put("header", HECLegacyDataSynchronizationConstants.DataTypes.ELIGIBILITY_DATA_TYPE);
		map.put("eligibilityStatus", this.eligibilityStatus);
		map.put("eligibilityStatusDate", this.eligibilityStatusDate);
		map.put("eligibilityVerificationMethod", this.eligibilityVerificationMethod);
		map.put("eligibilityCode", this.eligibilityCode);
		map.put("otherEligibilityCodes", RawFileDataContainerUtils.formatMultipleValues(otherEligibilityCodes, 
				HECLegacyDataSynchronizationConstants.Delimiters.SECONDARY));
		map.put("serviceConnected", this.serviceConnected);
		map.put("serviceConnectedPercentage", this.serviceConnectedPercentage);
		map.put("unemployable", this.unemployable);
		map.put("pAndT", this.pAndT);
		map.put("pAndTEffectiveDate", this.pAndTEffectiveDate);
		map.put("ratedDisabilities", formatRatedDisabilities());
		map.put("combinedSCPercentEffectiveDate", this.combinedSCPercentEffectiveDate);
		map.put("receivingVAPension", this.receivingVAPension);
		map.put("receivingAABenefits", this.receivingAABenefits);
		map.put("receivingHouseholdBenefits", this.receivingHouseholdBenefits);
		map.put("eligibleForMedicaid", this.eligibleForMedicaid);
		map.put("dischargeDueToDisability", this.dischargeDueToDisability);
		map.put("militaryDisabilityRetirement", this.militaryDisabilityRetirement);
		map.put("receivingVADisability", this.receivingVADisability);
		map.put("totalAnnualVACheckAmount", this.totalAnnualVACheckAmount);
		map.put("powStatusIndicated", this.powStatusIndicated);
		map.put("ratedIncompetent", this.ratedIncompetent);
		map.put("ineligibleDate", this.ineligibleDate);
		map.put("ineligibleReason", this.ineligibleReason);
		map.put("ineligibleVaroDecision", this.ineligibleVaroDecision);
		map.put("exposedToAgentOrange", this.exposedToAgentOrange);
		map.put("agentOrangeExposureLocation", this.agentOrangeExposureLocation);
		map.put("radiationExposureIndicator", this.radiationExposureIndicator);
		map.put("radiationExposureMethod", this.radiationExposureMethod);
		map.put("environmentalContaminants", this.environmentalContaminants);
		map.put("veteranIndicator", this.veteranIndicator);
		map.put("emergencyResponse", this.emergencyResponse);
		return map;
	}

	/**
	 * @param otherEligibilityCodes The otherEligibilityCodes to set.
	 */
	public void setOtherEligibilityCodes(Set otherEligibilityCodes) {
		this.otherEligibilityCodes = otherEligibilityCodes;
	}
	
	public void addOtherEligibilityCode(EligibilityType other) {
		otherEligibilityCodes.add(other);	
	}

	/**
	 * @param ratedDisabilities The ratedDisabilities to set.
	 */
	public void setRatedDisabilities(Set ratedDisabilities) {
		this.ratedDisabilities = ratedDisabilities;
	}
	
	public void addRatedDisability(RatedDisability dis) {
		ratedDisabilities.add(dis);
	}

	/**
	 * @return Returns the serviceConnectedPercentage.
	 */
	public Integer getServiceConnectedPercentage() {
		return serviceConnectedPercentage;
	}

	/**
	 * @param serviceConnectedPercentage The serviceConnectedPercentage to set.
	 */
	public void setServiceConnectedPercentage(Integer serviceConnectedPercentage) {
		this.serviceConnectedPercentage = serviceConnectedPercentage;
	}

	public String getVeteranIndicator() {
		return veteranIndicator;
	}

	public void setVeteranIndicator(String veteranIndicator) {
		this.veteranIndicator = veteranIndicator;
	}
}
