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

package gov.va.med.esr.common.builder.comms;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import gov.va.med.esr.common.model.comms.CommsTemplate;
import gov.va.med.esr.common.model.lookup.ComLetterTemplateType;
import gov.va.med.esr.common.model.person.Association;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.util.LetterFormatHelper;
import gov.va.med.fw.service.AbstractComponent;


/**
 * Builds the common data elements for AAC Letter file.
 * 
 * Created Jul 7, 2006 3:20:02 PM
 * 
 * @author DNS   bohmeg
 */
public abstract class AbstractLetterFormatter extends AbstractComponent
		implements IFormatter {
	static final String VERSION = "00001";
	
	static final String EMPTY_STRING = StringUtils.EMPTY;

	public static final String FIELD_DELIMITER = "^\n";
	
    public static final String FIELD_SEPARATOR  = "|";
    
    static final String FORM_HEADER = "*FORM=";
	
	static final String VERSION_HEADER = "*VER=";
	
	static final String F01 = "* F01=";
	static final String F02 = "* F02=";
	static final String F03 = "* F03=";
	static final String F04 = "* F04=";
	static final String F05 = "* F05=";
	static final String F06 = "* F06=";
	static final String F07 = "* F07=";
	static final String F08 = "* F08=";
	static final String F09 = "* F09=";
	static final String F10 = "* F10=";
	
	protected String getString(String str) {
		return str == null ? EMPTY_STRING : str;
	}

	public List format(Person person, GenerateValues inputValues) {
		List data = new ArrayList();
						
		// add vet data
		data.add(buildFormDataElements(person, inputValues.getOrigTemplate(),
				(GeneralTransmission) inputValues.getTransmission(),
				inputValues, null));
		
		// add each POA data
		List poas = inputValues.getTransmission().getPOAsWithAddresses();		
		Iterator itr = poas != null ? poas.iterator() : null;
		while(itr != null && itr.hasNext()) {
			data.add(buildFormDataElements(person, inputValues.getOrigTemplate(),
					(GeneralTransmission) inputValues.getTransmission(),
					inputValues, (Association) itr.next()));			
		}
		
		return data;
	}

	protected final String buildFormDataElements(Person person, CommsTemplate template,
			GeneralTransmission transmission, GenerateValues inputValues, Association poa) {
		StringBuffer dataElements = new StringBuffer();
		// Common Data Elements
		buildHeader(dataElements, template, inputValues, poa);
		buildDataElementsA(dataElements, transmission, inputValues);
		buildDataElementsB(dataElements, transmission, inputValues, poa);
		buildDataElementsC(dataElements, transmission, inputValues);
		buildDataElementsD(dataElements, transmission, inputValues);
		buildDataElementsE(dataElements, transmission, inputValues, poa);
		buildDataElementsF(dataElements, transmission, inputValues, poa);
		buildDataElementsH(dataElements, transmission, inputValues);
        buildDataElementsH20(dataElements, transmission, inputValues,person);
       return dataElements.toString();
	}

	private void buildHeader(StringBuffer dataElements,
			CommsTemplate template, GenerateValues inputValues, Association poa) {
		String formNumber = template.getCommsTemplateFormNumber();
		if(poa != null) {
			formNumber = ComLetterTemplateType.FORM_NUMBER_650A.getCode();
		}
		
		dataElements.append(FORM_HEADER).append(
				LetterFormatHelper.toAACFormNumber(formNumber)).append(FIELD_DELIMITER)
				.append(VERSION_HEADER).append(
						LetterFormatHelper.toAACVerNumber(VERSION)).append(
						FIELD_DELIMITER);
	}

	protected void buildDataElementsA(StringBuffer dataElements,
			GeneralTransmission transmission, GenerateValues inputValues) {
		dataElements.append("* A00=").append(transmission.getVeteranTitle())
				.append(FIELD_DELIMITER).append("* A01=").append(
						transmission.getVeteranLastName()).append(
						FIELD_DELIMITER).append("* A02=").append(
						transmission.getVeteranFirstName()).append(
						FIELD_DELIMITER).append("* A03=").append(
						transmission.getVeteranMiddleName()).append(
						FIELD_DELIMITER).append("* A04=").append(
						transmission.getVeteranSuffix())
				.append(FIELD_DELIMITER).append("* A15=").append(
						LetterFormatHelper.toAACSsn(transmission
								.getVeteranSsn())).append(FIELD_DELIMITER)
				.append("* A16=").append(transmission.getVeteranGender())
				.append(FIELD_DELIMITER).append("* A17=").append(
						LetterFormatHelper.toAACDate(transmission
								.getVeteranDOB())).append(FIELD_DELIMITER);
	}

	protected final void buildDataElementsB(StringBuffer dataElements,
			GeneralTransmission transmission, GenerateValues inputValues, Association poa) {
		String addressLine1 = poa != null ? poa.getAddress().getLine1() : transmission.getVeteranAddressLine1();
		String combinedAddressLine2And3 = poa != null ? LetterFormatHelper.getMailingAddressLine2and3(poa.getAddress()) : 
			LetterFormatHelper.getMailingAddressLine2and3(transmission.getMailingAdress());
		String city = poa != null ? poa.getAddress().getCity() : transmission.getVeteranCity();
		String state = poa != null ? LetterFormatHelper.getMailingAddressState(poa.getAddress()) : transmission.getVeteranState();
		String zipOrPostal = poa != null ? LetterFormatHelper.getMailingAddressZipOrPostal(poa.getAddress()) : transmission.getVeteranZipCodeOrPostalCode();
		String countyOrProvince = poa != null ? LetterFormatHelper.getMailingAddressCountyOrProvince(poa.getAddress()) : transmission.getVeteranCountyOrProvince();
		String country = poa != null ? LetterFormatHelper.getMailingAddressCountry(poa.getAddress()) : transmission.getVeteranCountryName();
		
		dataElements.append("* B01=").append(transmission.getCaseNumber()).append(FIELD_DELIMITER).
							append("* B02=").append(LetterFormatHelper.getString(addressLine1).toUpperCase()).append(FIELD_DELIMITER).
							append("* B03=").append(LetterFormatHelper.getString(combinedAddressLine2And3).toUpperCase()).append(FIELD_DELIMITER).
							append("* B04=").append(LetterFormatHelper.getString(city).toUpperCase()).append(FIELD_DELIMITER).
							append("* B05=").append(LetterFormatHelper.getString(state).toUpperCase()).append(FIELD_DELIMITER).
							append("* B06=").append(LetterFormatHelper.getString(zipOrPostal).toUpperCase()).append(FIELD_DELIMITER).
							append("* B07=").append(LetterFormatHelper.getString(countyOrProvince).toUpperCase()).append(FIELD_DELIMITER).
							append("* B08=").append(transmission.getVeteranHomeTelephoneNumber()).append(FIELD_DELIMITER).
							append("* B09=").append(transmission.getVeteranWorkTelephoneNumber()).append(FIELD_DELIMITER).
							append("* B10=").append(truncateCountryName(LetterFormatHelper.getString(country).toUpperCase())).append(FIELD_DELIMITER);
	}
	
	/** limits to capped size */
	private String truncateCountryName(String countryName) {
		if(countryName == null)
			return EMPTY_STRING;
		
		if(countryName.length() > 50)
			countryName = countryName.substring(0, 50);
		return countryName;
	}

	protected void buildDataElementsC(StringBuffer dataElements,
			GeneralTransmission transmission, GenerateValues inputValues) {
		// defaults to empty data set
		dataElements.append("* C01=").append(
				EMPTY_STRING).append(FIELD_DELIMITER).append("* C02=").append(
				EMPTY_STRING).append(FIELD_DELIMITER).append("* C03=").append(
				EMPTY_STRING).append(FIELD_DELIMITER).append("* C04=").append(
				EMPTY_STRING).append(FIELD_DELIMITER).append("* C05=").append(
				EMPTY_STRING).append(FIELD_DELIMITER).append("* C06=").append(
				EMPTY_STRING).append(FIELD_DELIMITER);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see gov.va.med.esr.common.builder.comms.AbstractLetterFormatter#buildDataElementsD(java.lang.StringBuffer,
	 *      gov.va.med.esr.common.builder.comms.GeneralTransmission,
	 *      gov.va.med.esr.common.builder.comms.GenerateValues)
	 */
	protected void buildDataElementsD(StringBuffer dataElements,
			GeneralTransmission transmission, GenerateValues inputValues) {
		// defaults to empty data set
		dataElements.append("* D01=").append(
				EMPTY_STRING).append(FIELD_DELIMITER).append("* D02=").append(
				EMPTY_STRING).append(FIELD_DELIMITER).append("* D03=").append(
				EMPTY_STRING).append(FIELD_DELIMITER);
	}

	protected void buildDataElementsE(StringBuffer dataElements,
			GeneralTransmission transmission, GenerateValues inputValues, Association poa) {
		String barCode = poa != null ? LetterFormatHelper.BARCODE_POA_TOKEN : getBarcode(inputValues);
		
		// defaults to Extract Data/ID and Barcode
		dataElements.append("* E01=").append(EMPTY_STRING).append(
				FIELD_DELIMITER).append("* E02=").append(EMPTY_STRING).append(
				FIELD_DELIMITER).append("* E03=").append(EMPTY_STRING).append(
				FIELD_DELIMITER).append("* E04=").append(
				(new SimpleDateFormat("MMddyyyy")).format(new Date())).append(
				FIELD_DELIMITER). // date of extract, filled in during
				// batch processing
				append("* E05=").append(EMPTY_STRING).append(FIELD_DELIMITER)
				.append("* E06=").append(EMPTY_STRING).append(FIELD_DELIMITER)
				.append("* E07=").append(EMPTY_STRING).append(FIELD_DELIMITER)
				.append("* E08=").append(EMPTY_STRING).append(FIELD_DELIMITER)
				.append("* E09=").append(EMPTY_STRING).append(FIELD_DELIMITER)
				.append("* E10=").append(inputValues.getAacExtractId()).append(
						FIELD_DELIMITER). // extract id
				append("* E11=").append(barCode).append(
						FIELD_DELIMITER). // log (bar code) id
				append("* E19=").append(EMPTY_STRING).append(FIELD_DELIMITER);
	}
	
	protected String getBarcode(GenerateValues inputValues) {
		return LetterFormatHelper.formatBarcode(inputValues.getCommsLog().getBarcode());
	}

	protected final void buildDataElementsF(StringBuffer dataElements,
			GeneralTransmission transmission, GenerateValues inputValues, Association poa) {
		if(poa == null) {
			// these are empty for the vet letter
			dataElements.append(F01).append(EMPTY_STRING).append(FIELD_DELIMITER).
					append(F02).append(EMPTY_STRING).append(FIELD_DELIMITER).
					append(F03).append(EMPTY_STRING).append(FIELD_DELIMITER).
					append(F04).append(EMPTY_STRING).append(FIELD_DELIMITER).
					append(F05).append(EMPTY_STRING).append(FIELD_DELIMITER)
					.append(F06).append(EMPTY_STRING).append(FIELD_DELIMITER)
					.append(F07).append(EMPTY_STRING).append(FIELD_DELIMITER)
					.append(F08).append(EMPTY_STRING).append(FIELD_DELIMITER)
					.append(F09).append(EMPTY_STRING).append(FIELD_DELIMITER)
					.append(F10).append(EMPTY_STRING).append(FIELD_DELIMITER);
		} else {
			dataElements.append(F01).append(LetterFormatHelper.getPOAName(poa).toUpperCase()).append(FIELD_DELIMITER).
			append(F02).append(LetterFormatHelper.toAACFormNumber(transmission.getFormNumber())).append(FIELD_DELIMITER).
			append(F03).append(LetterFormatHelper.toAACVerNumber(VERSION)).append(FIELD_DELIMITER).
			append(F04).append(transmission.getVeteranAddressLine1().toUpperCase()).append(FIELD_DELIMITER).
			append(F05).append(LetterFormatHelper.getMailingAddressLine2and3(transmission.getMailingAdress()).toUpperCase()).append(FIELD_DELIMITER)
			.append(F06).append(transmission.getVeteranCity().toUpperCase()).append(FIELD_DELIMITER)
			.append(F07).append(transmission.getVeteranState().toUpperCase()).append(FIELD_DELIMITER)
			.append(F08).append(transmission.getVeteranZipCodeOrPostalCode().toUpperCase()).append(FIELD_DELIMITER)
			.append(F09).append(truncateCountryName(transmission.getVeteranCountryName().toUpperCase())).append(FIELD_DELIMITER)
			.append(F10).append(getBarcode(inputValues)).append(FIELD_DELIMITER);			
		}
	}
    protected abstract void buildDataElementsH(StringBuffer dataElements,
			GeneralTransmission transmission, GenerateValues inputValues);
    
    protected abstract void buildDataElementsH20(StringBuffer dataElements,
            GeneralTransmission transmission, GenerateValues inputValues, Person person);
     
   }