/**
 * Created on 4:44:56 PM Jan 11, 2005
 * Project: UI
 */
package gov.va.med.esr.ui.comms.action;

// Java classes
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.mlw.vlh.ValueList;

import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.comparators.NullComparator;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

import gov.va.med.esr.common.model.CommonEntityKeyFactory;
import gov.va.med.esr.common.model.comms.CommsLogEntry;
import gov.va.med.esr.common.model.comms.Correspondence;
import gov.va.med.esr.common.model.comms.DeliveryPreference;
import gov.va.med.esr.common.model.comms.GeocodeTransmit;
import gov.va.med.esr.common.model.comms.HandBookMailQueue;
import gov.va.med.esr.common.model.comms.HealthBenefitPlan;
import gov.va.med.esr.common.model.comms.HecRejectReason;
import gov.va.med.esr.common.model.comms.VCDeterminationHistoryForm;
import gov.va.med.esr.common.model.comms.Waittime;
import gov.va.med.esr.common.model.ee.IRS1095B;
import gov.va.med.esr.common.model.ee.MECPeriod;

import gov.va.med.esr.common.model.ee.SpecialFactor;
import gov.va.med.esr.common.model.lookup.ComLetterTemplateType;
import gov.va.med.esr.common.model.lookup.ComLetterTemplateType.Code;
import gov.va.med.esr.common.model.lookup.ComMailingStatusType;
import gov.va.med.esr.common.model.lookup.PhoneType;
import gov.va.med.esr.common.model.lookup.HandBookMailStatusType;
import gov.va.med.esr.common.model.messaging.IrsTransmissionLogDetailEntry;

import gov.va.med.esr.common.model.party.Phone;
import gov.va.med.esr.common.model.party.SimpleAddress;
import gov.va.med.esr.common.model.person.DeathRecord;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.security.ESRUserPrincipal;
import gov.va.med.esr.service.DuplicatePrintRequestServiceException;
import gov.va.med.esr.service.VeteransChoiceInformationService;
import gov.va.med.esr.service.external.VHICCardDetailInfo;
import gov.va.med.esr.service.external.VHICCardInfo;
import gov.va.med.esr.service.trigger.LetterTrigger;
import gov.va.med.esr.service.trigger.LetterTriggerEvent;
import gov.va.med.esr.service.trigger.LetterTriggerIdentity;
import gov.va.med.esr.ui.ApplicationConstants;
import gov.va.med.esr.ui.common.action.PersonAbstractAction;
import gov.va.med.esr.ui.common.util.DateUtils;
import gov.va.med.esr.ui.util.SessionManager;
import gov.va.med.fw.security.SecurityContext;
import gov.va.med.fw.service.ServiceConfigurationException;
import gov.va.med.fw.ui.UIConstants;
import gov.va.med.fw.ui.struts.ValueListActionUtils;

public class CommsLogAction extends PersonAbstractAction
{
	protected static String HANDBOOK = "Handbook";
	protected static String NON_HANDBOOK = "Non Handbook";
	protected static String IRS_SUBMIT="IRS";
	private String BATCH_TYPE = "V";
	private String CORRECTION_IND = "C";

    public CommsLogAction()
    {
        super();
    }

    /**
     * Displays a search record
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception Thrown if failed to process
     */
    public ActionForward display(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {

        // Ensure we have a valid comms form
        CommsLogForm commsLogForm = getCommsLogForm(form);

        // Get the Person object from the cache
        Person person = getSelectedPerson(request);

        if (SessionManager.isAddAPerson(request)) {
        	return mapping.findForward("commsLog");
        }

         List ls = getCommsLogService()
            .findLogEntriesByPersonId(person.getPersonEntityKey().getKeyValueAsString());

        // Get the value list information from the future EGT Settings list
        ValueList valueList = ValueListActionUtils.getValueList(form,
            request, "commsLogTableId", "commsLogAdapter", ls);

        // Backup the ValueListInfo into session and store the resultant ValueList on the request
        ValueListActionUtils.setValueList(request, valueList, "vlhlist");


        return mapping.findForward("commsLog");
    }

    // 3.5 CCR 10956 and CCR 10960
    /**
     * Displays the raw message data
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception Thrown if failed to process
     */
    public ActionForward viewRawData(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {
        // Ensure we have a valid comms form
        CommsLogForm commsLogForm = getCommsLogForm(form);
		Person person = getSelectedPerson(request);
		String handbook_mail_queue_id = request.getParameter("ver");
		int receipt_id = Integer.valueOf(handbook_mail_queue_id);

        List ls = getHandBookService().getRawProfileData(person.getVPIDValue(), receipt_id);
        String rawData = "";

        Iterator iter = ls.iterator();
        while (iter.hasNext()) {
        	HealthBenefitPlan hbr = (HealthBenefitPlan)iter.next();
        	rawData = rawData += hbr.getHealthBenefitCategory() + "^" + hbr.getHealthBenefitCode() + "^" + hbr.getCoveragePlanCode() + "<br/>";
        }

        commsLogForm.setRawData(rawData);


        return mapping.findForward("viewRawData");
    }
    /**
     * Displays list of handbook status
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception Thrown if failed to process
     */
    public ActionForward displayHandbookStatus(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {

       // Ensure we have a valid comms form
        CommsLogForm commsLogForm = getCommsLogForm(form);

        // Get the Person object from the cache
        Person person = getSelectedPerson(request);

        if (SessionManager.isAddAPerson(request)) {
        	return mapping.findForward("handbookStatus");
        }

        // 3.6 CCR 10960
        List ls = getHandBookService()
            .findHandbookEntriesByPersonId(person.getPersonEntityKey().getKeyValueAsString());

        // allow the user to manually mail a handbook if there if there isn’t a Health Benefits Handbook
        // with a status of Send to CMS or Sent to CMS.
        // NOTE: also check enrollment status and whether or not the individual is alive.
        commsLogForm.setHandbookMailValidationErrors(getHandBookService().checkHandbookMailValidation(person));

        // Get the value list information from the future EGT Settings list
        ValueList valueList = ValueListActionUtils.getValueList(form,
        		request, "commsLogTableId", "commsLogAdapter", ls);

        // Backup the ValueListInfo into session and store the resultant ValueList on the request
        ValueListActionUtils.setValueList(request, valueList, "vlhlist");

        List lsHandbookTemplate = getHandBookService().findHandbookTemplate();

        // Get the value list information from the future EGT Settings list
        ValueList handbookValueList = ValueListActionUtils.getValueList(form,
        		request, "handbookTemplateTableId", "commsLogAdapter", lsHandbookTemplate);

        // Backup the ValueListInfo into session and store the resultant ValueList on the request
        ValueListActionUtils.setValueList(request, handbookValueList, "vlhlistHandbook");


        return mapping.findForward("handbookStatus");
    }

    /**
     * Displays a message data
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception Thrown if failed to process
     */
    public ActionForward displayAvailMailing(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {

        List ls = getCommsLetterRequestService().getAvailableLettersForMailing();

        // Get the value list information from the future EGT Settings list
        ValueList valueList = ValueListActionUtils.getValueList(form,
            request, "commsAvailMailTableId", "commsAvailMailAdapter", ls);

        // Backup the ValueListInfo into session and store the resultant ValueList on the request
        ValueListActionUtils.setValueList(request, valueList, "vlhlist");

        return mapping.findForward("availMailing");
    }

    public ActionForward displayRejectReason(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {


        return mapping.findForward("reject");
    }

    public ActionForward displayDetail(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {
    	populateActionForm(form,request,NON_HANDBOOK);
        return mapping.findForward("detail");
    }

    public ActionForward displayHandbookDetail(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {
    	populateActionForm(form,request,HANDBOOK);
        return mapping.findForward("handbookDetail");
    }

    public ActionForward displayDeliveryPreferences(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception
    {
        // Get delivery preferences specific form
    	DeliveryPreferencesForm dpForm =
 	            (form instanceof DeliveryPreferencesForm) ? (DeliveryPreferencesForm)form : null;
 	    if (dpForm == null)
 	    {
 	        throw new ServiceConfigurationException("DeliveryPreferencesForm not properly configured.");
 	    }

        dpForm.setAddAPerson(SessionManager.isAddAPerson(request));

        // Get the Person object from the cache
        Person person = getSelectedPerson(request);

        DeliveryPreference dp = getHandBookService().findDeliveryPreferenceByPersonId(person.getPersonEntityKey().getKeyValueAsString());

        if (dp != null)
        {
            conversionService.convert(dp, dpForm);
        }

        // Return to the delivery preferences screen

//       return mapping.findForward("detail");
        return mapping.findForward("deliveryPreferences");
    }

    /**
     * This method populates CommsLogEntry and ActionMessages.
     * @param form
     * @param request
     * @throws Exception
     */
    protected void populateActionForm( ActionForm form,HttpServletRequest request, String commType)
    throws Exception
    {
    	 // Ensure we have a valid comms form
        CommsLogForm commsLogForm = getCommsLogForm(form);

        if (commType.equals(HANDBOOK)) {
	        HandBookMailQueue entry =
	            getHandBookService().getHandbookMailQueueEntry(CommonEntityKeyFactory.createHandBookMailQueueEntityKey(
	                commsLogForm.getSelectedCommsLogId()));
	        commsLogForm.setSelectedHandbookLog(entry);

	        // get the list of COMMENTS that have been added for this Handbook Mail Queue entry
	        List commentList =
	        	getHandBookService().getHandbookMailQueueCommentHistory( new BigDecimal(commsLogForm.getSelectedCommsLogId()));

	        // Get the value list information from the future EGT Settings list
	        ValueList valueList = ValueListActionUtils.getValueList(form,
	        		request, "handbookCommentsTableId", "commsLogAdapter", commentList);

	        // Backup the ValueListInfo into session and store the resultant ValueList on the request
	        ValueListActionUtils.setValueList(request, valueList, "vlhCommentList");

	        // get the list of STATUSES that have been added for this Handbook Mail Queue entry
	        List statusList =
	        	getHandBookService().getHandBookMailStatusHistory( new BigDecimal(commsLogForm.getSelectedCommsLogId()));

	        // Get the value list information from the future EGT Settings list
	        ValueList valueList2 = ValueListActionUtils.getValueList(form,
	        		request, "handbookStatusTableId", "commsLogAdapter", statusList);

	        // Backup the ValueListInfo into session and store the resultant ValueList on the request
	        ValueListActionUtils.setValueList(request, valueList2, "vlhStatusList");

	        // get the correct ADDRESS record.  NOTE: the address ID in the handbook mail queue table may have been changed since the
	        // time this handbook was mailed out.
	        HandBookMailQueue handbook = commsLogForm.getSelectedHandbookLog();
	        handbook.setAddress(getHandBookService().getHandBookMailingAddress(handbook));
	        commsLogForm.setSelectedHandbookLog(handbook);

        } else {
	        CommsLogEntry entry =
	            getCommsLogService().getCommsLogEntry(CommonEntityKeyFactory.createCommsLogEntryEntityKey(
	                commsLogForm.getSelectedCommsLogId()));
	        commsLogForm.setSelectedCommsLog(entry);

	        // Get the value list information from the future EGT Settings list
	        ValueList valueList = ValueListActionUtils.getValueList(form,
	        		request, "mailStatusTableId", "commsLogAdapter", entry.getMailingStatusLinks());

	        // Backup the ValueListInfo into session and store the resultant ValueList on the request
	        ValueListActionUtils.setValueList(request, valueList, "vlhlist");

	        //get the hec reject reasons and the corresponding validation messages
	        if (entry.getLatestMailingStatus().getMailingStatus().getCode()
	            .equals(ComMailingStatusType.REJECT_AT_HEC.getName()))
	        {
	            Iterator i = entry.getHecRejectionReasons().iterator();
	            while (i.hasNext())
	            {
	                addActionMessage(request,
	                    ((HecRejectReason)i.next()).getHecRejectReasonDescription());
	            }
	        }
        }
    }

    public ActionForward update(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {

        try
        {
            // Get the Person object from the cache
            Person person = getSelectedPerson(request);

            // Ensure we have a valid comms form
            CommsLogForm commsLogForm = getCommsLogForm(form);

            List conditions;

            ComLetterTemplateType formNumber = (ComLetterTemplateType)
                getLookupCacheService().getByCodeFromCache(ComLetterTemplateType.class,
                    commsLogForm.getSelectedFormNumber());

            String caseId = commsLogForm.getSelectedCaseId();
            String comment = formatComment(commsLogForm.getNewComment(), request);

            //TODO need to check if the user has permission to override

            if (commsLogForm.isOverride())
            {
                if (commsLogForm.isRemailInd())
                    conditions = getCommsLetterRequestService().requestAacLetter(person,
                    		new LetterTriggerIdentity(formNumber, LetterTrigger.CategoryType.VETERAN_LETTER),
                    		caseId, LetterTriggerEvent.REMAIL_MAIL, Boolean.TRUE, comment);
                else
                    conditions = getCommsLetterRequestService().requestAacLetter(person,
                    		new LetterTriggerIdentity(formNumber, LetterTrigger.CategoryType.VETERAN_LETTER),
                    		caseId, LetterTriggerEvent.MANUAL_MAIL, Boolean.TRUE, comment);

                commsLogForm.setFailedConditions(conditions);
            }
        }
        catch (DuplicatePrintRequestServiceException e)
        {
            addActionMessage(request, "message.comms.duplicateLetter");
        }


        return display(mapping, form, request, response);
    }

    public ActionForward remail(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {

        String caseId = null;
        ComLetterTemplateType formNumber = null;
        List conditions = null;

        // Get the Person object from the cache
        Person person = getSelectedPerson(request);

        // Ensure we have a valid comms form
        CommsLogForm commsLogForm = getCommsLogForm(form);

        String id = commsLogForm.getSelectedCommsLogId();
        CommsLogEntry entry =
            getCommsLogService().getCommsLogEntry(CommonEntityKeyFactory.createCommsLogEntryEntityKey(
                commsLogForm.getSelectedCommsLogId()));

        LetterTrigger.CategoryType categoryType = LetterTrigger.CategoryType.VETERAN_LETTER;
        if (entry != null)
        {
        	if(CommsLogEntry.RECIPIENT_SPOUSE.equals(entry.getRecipient()))
        		categoryType = LetterTrigger.CategoryType.SPOUSE_LETTER;
        	else if(CommsLogEntry.RECIPIENT_DEPENDENT.equals(entry.getRecipient()))
        		categoryType = LetterTrigger.CategoryType.DEPENDENT_LETTER;

        	// set to the one being remailed since it will have the same form number and name
        	commsLogForm.setSelectedCommsLog(entry);

            //convert string to letterTrigget.datatype
            String formNbr = entry.getFormNumber();
            commsLogForm.setSelectedFormNumber(formNbr);

            formNumber = (ComLetterTemplateType)
                getLookupCacheService().getByCodeFromCache(ComLetterTemplateType.class,
                    formNbr);

            if (entry.getWorkflowCaseId() != null)
                caseId = entry.getWorkflowCaseId().toString();
            commsLogForm.setSelectedCaseId(caseId);

            commsLogForm.setRemailInd(true);
        }

        try
        {
            conditions = getCommsLetterRequestService().requestAacLetter(person, new LetterTriggerIdentity(formNumber, categoryType), caseId,
                LetterTriggerEvent.REMAIL_MAIL, Boolean.FALSE);
            commsLogForm.setFailedConditions(conditions);
        }
        catch (DuplicatePrintRequestServiceException e)
        {
            addActionMessage(request, "message.comms.duplicateLetter");
        }

        if (processValidationMsgs(conditions, request, commsLogForm))
        {
            return mapping.findForward("reject");
        }

        return display(mapping, form, request, response);
    }

    public ActionForward cancel(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {

        // Ensure we have a valid comms form
        CommsLogForm commsLogForm = getCommsLogForm(form);

        commsLogForm.setSelectedCaseId(null);
        commsLogForm.setSelectedFormNumber(null);
        commsLogForm.setSelectedCommsLogId(null);

        return display(mapping, form, request, response);
    }

    public ActionForward mail(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {

        List conditions = null;

        // Get the Person object from the cache
        Person person = getSelectedPerson(request);

        // Ensure we have a valid comms form
        CommsLogForm commsLogForm = getCommsLogForm(form);

        String formNbr = commsLogForm.getSelectedFormNumber();
        commsLogForm.setSelectedFormNumber(formNbr);

        ComLetterTemplateType formNumber = (ComLetterTemplateType)
            getLookupCacheService().getByCodeFromCache(ComLetterTemplateType.class,
                formNbr);
        commsLogForm.setSelectedFormName(formNumber.getName());

        commsLogForm.setRemailInd(false);

        String caseId = null;
        commsLogForm.setSelectedCaseId(caseId);

        // is this a HANDBOOK?
        String isHandbook = request.getParameter("handbook");
        if (isHandbook != null && isHandbook.equals("Y")) {
        	try {
        		conditions = getHandBookService().requestHandBook(person.getEntityKey().getKeyValueAsString(), new LetterTriggerIdentity(formNumber, LetterTrigger.CategoryType.VETERAN_LETTER));
        		commsLogForm.setFailedConditions(conditions);
        	}
        	catch (DuplicatePrintRequestServiceException e)
        	{
        		addActionMessage(request, "message.comms.duplicateLetter");
        	}

        	if (processValidationMsgs(conditions, request, commsLogForm))
        	{
        		return mapping.findForward("reject");
        	}
	        return displayHandbookStatus(mapping, form, request, response);

        } else {
        	try
        	{
        		conditions = getCommsLetterRequestService().requestAacLetter(person,
        				new LetterTriggerIdentity(formNumber, LetterTrigger.CategoryType.VETERAN_LETTER), caseId,
	                LetterTriggerEvent.MANUAL_MAIL, Boolean.FALSE);
	            commsLogForm.setFailedConditions(conditions);
	        }
	        catch (DuplicatePrintRequestServiceException e)
	        {
	            addActionMessage(request, "message.comms.duplicateLetter");
	        }

	        if (processValidationMsgs(conditions, request, commsLogForm))
	        {
	            return mapping.findForward("reject");
	        }
	        return display(mapping, form, request, response);
       }

    }

    /**
     * Displays list of handbook status
     *
     * @param mapping An action mapping
     * @param form A form bean
     * @param request A http request from an search.jsp page
     * @param response A http response to stream data to a next page
     *
     * @return An action forward class encapsulating information about a next page
     * @throws Exception Thrown if failed to process
     */
    public ActionForward displayVHICCardStatus(ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception
    {


    	 // Ensure we have a valid comms form
        CommsLogForm commsLogForm = getCommsLogForm(form);

        VHICCardInfo vhicCardInfo = getVhicCardInfoService().getVhicCardInfo();

        commsLogForm.setVhicCardInfo(vhicCardInfo);

        List<VHICCardDetailInfo> ls = getVhicCardInfoService().getVhicCardInfo().getVhicCardDetailInfoList();

        // Get the value list information
        ValueList valueList = ValueListActionUtils.getValueList(form,
        		request, "vhicCardStatusTableId", "commsLogAdapter", ls);

        // Backup the ValueListInfo into session and store the resultant ValueList on the request
        ValueListActionUtils.setValueList(request, valueList, "vlhlist");

        return mapping.findForward("vhicCardStatus");
    }

    public ActionForward displayIRSCorrectionForYear(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {
    	 return displayIRSCorrection(mapping, form, request, response);
    }

    @SuppressWarnings("unchecked")
	public ActionForward displayACADetail(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {

    		Correspondence entry = this.getCorrespondenceService().getCorrespondenceWithHistory(new BigDecimal(request.getParameter("submissionId")));


    		if (entry == null) {
    			this.addActionMessage(request, "errorCorrNotFound");


	    		List ls = ValueListActionUtils.getCachedResults(request.getSession(), "irsCommTableId");

	    		if (ls != null) {
	    			ValueList valueList = ValueListActionUtils.getValueList(form,
		    	            request, "irsCommTableId", "commsLogAdapter", ls);

	    			ValueListActionUtils.setValueList(request, valueList, "vlhlist");
	    			return mapping.findForward("irsSubmission");
	    		}

	    		return displayIRSSubmission(mapping, form, request, response);
    		}

    		CommsLogForm commsLogForm = getCommsLogForm(form);
    		commsLogForm.setSelectedFormNumber(entry.getLetterTemplate().getCommsTemplateFormNumber());
    		commsLogForm.setSelectedFormName(entry.getLetterTemplate().getCommsTemplateName());
    		commsLogForm.setSelectedCommsLogId(entry.getEntityKey().getKeyValueAsString());
    		commsLogForm.setSelectedCorrespondence(entry);

    		ArrayList<Correspondence> statusList = entry.getStatusHistory();

    		ValueList valueList2 = ValueListActionUtils.getValueList(form,
	        		request, "corrStatusTableId", "commsLogAdapter", statusList);

    		ValueListActionUtils.setValueList(request, valueList2, "vlhStatusList");


	    	return mapping.findForward("acaDetail");
        }

    @SuppressWarnings("unchecked")
	public ActionForward displayACADoc(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {

	    	return mapping.findForward("acaDetail");
        }


    @SuppressWarnings("unchecked")
	public ActionForward displayIRSCorrection(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception {

    		CommsLogForm commsLogForm = getCommsLogForm(form);

	    	List taxYearList = this.getIrsTransmissionService().getAllowedCorrectionYears
	    			(getSelectedPerson(request).getPersonEntityKey());

	    	if (taxYearList == null || taxYearList.isEmpty()) {
	    		this.addActionMessage(request, "errorNoCorrect");


	    		List ls = ValueListActionUtils.getCachedResults(request.getSession(), "irsCommTableId");

	    		if (ls != null) {
	    			ValueList valueList = ValueListActionUtils.getValueList(form,
		    	            request, "irsCommTableId", "commsLogAdapter", ls);

	    			ValueListActionUtils.setValueList(request, valueList, "vlhlist");
	    			return mapping.findForward("irsSubmission");
	    		}

	    		return displayIRSSubmission(mapping, form, request, response);
	    	}

	    	Collections.sort(taxYearList);
	    	Collections.reverse(taxYearList);
	    	commsLogForm.setTaxYearSel(taxYearList.get(0).toString());

	    	IrsTransmissionLogDetailEntry recent = this.getIrsTransmissionService().getMostRecentTransmissionForYear
	    			(getSelectedPerson(request).getPersonEntityKey(), commsLogForm.getTaxYearSel(), true);

	    	populateCorrectionForm(commsLogForm, recent, taxYearList, request);



	    	return mapping.findForward("irsCorrection");
        }



    @SuppressWarnings("unchecked")
	public IRS1095B convert1095(ActionForm form, HttpServletRequest request) throws Exception{
    	IRS1095B entry = new IRS1095B(getSelectedPerson(request));
    	MECPeriod p = new MECPeriod();
    	CommsLogForm dataRecord = getCommsLogForm(form);

    	p.setCoverageMonths(buildCoverageMap(dataRecord));

    	p.setCoveredAll12Months(isCoveredAll12Months(dataRecord));

    	entry.setMecPeriod(p);

    	entry.setAddress(getSelectedPerson(request).getPermanentAddress());

    	return entry;
    }

    private boolean isCoveredAll12Months(CommsLogForm dataRecord) {

       	if (dataRecord.isCoveredJan() &&
       			dataRecord.isCoveredFeb() &&
		       	dataRecord.isCoveredMar() &&
		       	dataRecord.isCoveredApr() &&
		       	dataRecord.isCoveredMay() &&
		       	dataRecord.isCoveredJun() &&
		       	dataRecord.isCoveredJul() &&
		       	dataRecord.isCoveredAug() &&
		       	dataRecord.isCoveredSep() &&
		       	dataRecord.isCoveredOct() &&
		       	dataRecord.isCoveredNov() &&
		       	dataRecord.isCoveredDec()) {
       		return true;
       	}

       	return false;
       }

    @SuppressWarnings("unchecked")
   	private HashMap buildCoverageMap(CommsLogForm dataRecord) {
       	HashMap coverageMap = new HashMap();

       	coverageMap.put("1", (dataRecord.isCoveredJan()) ? true : false);
       	coverageMap.put("2", (dataRecord.isCoveredFeb()) ? true : false);
       	coverageMap.put("3", (dataRecord.isCoveredMar()) ? true : false);
       	coverageMap.put("4", (dataRecord.isCoveredApr()) ? true : false);
       	coverageMap.put("5", (dataRecord.isCoveredMay()) ? true : false);
       	coverageMap.put("6", (dataRecord.isCoveredJun()) ? true : false);
       	coverageMap.put("7", (dataRecord.isCoveredJul()) ? true : false);
       	coverageMap.put("8", (dataRecord.isCoveredAug()) ? true : false);
       	coverageMap.put("9", (dataRecord.isCoveredSep()) ? true : false);
       	coverageMap.put("10", (dataRecord.isCoveredOct()) ? true : false);
       	coverageMap.put("11", (dataRecord.isCoveredNov()) ? true : false);
       	coverageMap.put("12", (dataRecord.isCoveredDec()) ? true : false);

       	return coverageMap;
       }


    public ActionForward submitIRS(ActionMapping mapping,
   		 ActionForm form,
   	        HttpServletRequest request,
   	        HttpServletResponse response)
   	        throws Exception
   	    {
    		ArrayList<IRS1095B> submission = new ArrayList<IRS1095B>();
    		IRS1095B correction = (convert1095(form, request));
    		submission.add(correction);


    		//submit to irs via service layer
    		this.getIrsTransmissionService().sendSubmit(submission, BATCH_TYPE, CORRECTION_IND, getCommsLogForm(form).getTaxYearSel());

    		//trigger correction mailing to the queue
    		Correspondence corr = new Correspondence(getSelectedPerson(request));
    		Calendar cal = Calendar.getInstance();
    		cal.set(Calendar.YEAR, Integer.valueOf(getCommsLogForm(form).getTaxYearSel()));
	    	corr.setEffectiveDate(cal.getTime());

	    	this.getCorrespondenceService().triggerNewCMSCorrespondence(corr, ComLetterTemplateType.FORM_NUMBER_800);

       		this.addInformationMessage(request, "sendCorrect");
       		return displayIRSSubmission(mapping, form, request, response);
       }

    public ActionForward remailACA(ActionMapping mapping,
      		 ActionForm form,
    	        HttpServletRequest request,
    	        HttpServletResponse response)
    	        throws Exception
    	    {

    			this.getCorrespondenceService().remailCorrespondence(new BigDecimal(request.getParameter("submissionId")));

    			this.addInformationMessage(request, "sendRemail");
    			return displayIRSSubmission(mapping, form, request, response);
    	    }

    public ActionForward sendReplacement(ActionMapping mapping,
      		 ActionForm form,
      	        HttpServletRequest request,
      	        HttpServletResponse response)
      	        throws Exception
      	    {
    			String submissionId = request.getParameter(("submissionId"));
    			String taxYear = request.getParameter("taxYear");
    			String err = this.getIrsTransmissionService().getMostRecentTransmissionForYear(getSelectedPerson(request).getPersonEntityKey(), taxYear, false).getErrorDescription();

    			if (err != null && err.length() > 0) {
	    			this.getIrsTransmissionService().retransmitFailedPersonSubmission(new BigDecimal(submissionId));

	          		this.addInformationMessage(request, "sendReplace");
    			} else {
    				this.addActionMessage(request, "errorReplace");
    			}
          		return displayIRSSubmission(mapping, form, request, response);
          }


    public ActionForward cancelIRS(ActionMapping mapping,
      		 ActionForm form,
      	        HttpServletRequest request,
      	        HttpServletResponse response)
      	        throws Exception {

          		return displayIRSSubmission(mapping, form, request, response);
          }

    public ActionForward cancelACADetail(ActionMapping mapping,
     		 ActionForm form,
     	        HttpServletRequest request,
     	        HttpServletResponse response)
     	        throws Exception {

         		return displayIRSSubmission(mapping, form, request, response);
         }

    public ActionForward cancelACAMail(ActionMapping mapping,
    		 ActionForm form,
    	        HttpServletRequest request,
    	        HttpServletResponse response)
    	        throws Exception {

    			this.getCorrespondenceService().cancelCorrespondence(new BigDecimal(request.getParameter("submissionId")));
    			this.addInformationMessage(request, "cancelMail");
        		return displayIRSSubmission(mapping, form, request, response);
        }

    @SuppressWarnings("unchecked")
	public ActionForward displayIRSSubmission(ActionMapping mapping,
		 ActionForm form,
	        HttpServletRequest request,
	        HttpServletResponse response)
	        throws Exception
	    {



    		List ls = this.getIrsTransmissionService().getTransmissionsByPersonId(getSelectedPerson(request).getPersonEntityKey());

    		ArrayList<Code> acaForm = new ArrayList();
    		acaForm.add(ComLetterTemplateType.FORM_NUMBER_800);
    		acaForm.add(ComLetterTemplateType.FORM_NUMBER_800A);
    		acaForm.add(ComLetterTemplateType.FORM_NUMBER_800D);
    		List lsmail = this.getCorrespondenceService().getPersonCorrespondence((BigDecimal)getSelectedPerson(request).getPersonEntityKey().getKeyValue(), acaForm);

			Collections.sort(ls, new BeanComparator(
					"batchTransmissionEntry.transmissionDate", new NullComparator()));

			Collections.sort(lsmail, new BeanComparator(
					"statusDate", new NullComparator()));

			Collections.reverse(ls);
			Collections.reverse(lsmail);

	        // Get the value list information
	        ValueList valueList = ValueListActionUtils.getValueList(form,
	            request, "irsCommTableId", "commsLogAdapter", ls);

	        ValueList valueListMail = ValueListActionUtils.getValueList(form,
		            request, "irsMailCommTableId", "commsLogAdapter", lsmail);

	        // Backup the ValueListInfo into session and store the resultant ValueList on the request
	        ValueListActionUtils.setValueList(request, valueList, "vlhlist");

	        ValueListActionUtils.setValueList(request, valueListMail, "vlhlistmail");


        return mapping.findForward("irsSubmission");
    }

    public ActionForward displayVHICCardStatusFromVHIC(ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response)
            throws Exception
        {


            //VHICCardInfo vhicCard = getVhicCardInfoService().getVHICCardStatusFromVHIC();  //TODO LC3 - Update code when VHIC web service is ready

            // Handle exception
               addActionMessage(request, new ActionMessage(
                  ApplicationConstants.MessageKeys.ERRORS_VHIC_SERVICE_CONNECTION));


            return displayVHICCardStatus(mapping, form, request, response);


        }

	public ActionForward displayVCDetermination(ActionMapping mapping,
			ActionForm form,
			HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		// Ensure we have a valid comms form
		CommsLogForm commsLogForm = getCommsLogForm(form);
		
		Person person = getSelectedPerson(request);
		VeteransChoiceInformationService vcis = this.getVeteransChoiceInformationService();
		GeocodeTransmit gt = vcis.fetchGeocodeTransmitRecord(person);
		List wts = vcis.fetchAllWaittimeRecords(person);
		commsLogForm.setGeocodeTransmit(gt);
		commsLogForm.setWaittimeList(wts);

		// query for vcis.fetAllWaittimeRecords() returns descending
		// order on PK so first list element is the latest record
		if(wts != null && wts.size() > 0){
			commsLogForm.setWaittime((Waittime) wts.get(0)); 
		}
		if(gt != null) {
		commsLogForm.setAddress(gt.getHistoricAddress().getAddress());
		}
		
		// Set the Veterans Choice Status
		commsLogForm.setVetChoiceStat(person.getVetChoiceStat());

		// Search for all phone types
		commsLogForm.setHomePhone("N/A");
		commsLogForm.setWorkPhone("N/A");
		commsLogForm.setCellPhone("N/A");
		commsLogForm.setTempPhone("N/A");
		Iterator phones = person.getPhones().iterator();
		while (phones.hasNext()) {
			Phone phone = (Phone) phones.next();
			if (phone.getType().getCode().equals(PhoneType.CODE_HOME.getCode())) {
				commsLogForm.setHomePhone(phone.getPhoneNumber());
			} else if (phone.getType().getCode().equals(PhoneType.CODE_BUSINESS.getCode())) {
				commsLogForm.setWorkPhone(phone.getPhoneNumber());
			} else if (phone.getType().getCode().equals(PhoneType.CODE_MOBILE.getCode())) {
				commsLogForm.setCellPhone(phone.getPhoneNumber());
			} else if (phone.getType().getCode().equals(PhoneType.CODE_TEMPORARY.getCode())) {
				commsLogForm.setTempPhone(phone.getPhoneNumber());				
			}
		}
		
		// Get information for Service Connection Awards
		commsLogForm.setServiceConnectionAward(
			person.getServiceConnectionAward() != null &&
			person.getServiceConnectionAward().getServiceConnectedIndicator() != null &&
			person.getServiceConnectionAward().getServiceConnectedIndicator() == true
				? "Yes" : "No");

		DateFormat df = new SimpleDateFormat("MM/dd/yyyy");

		// Get the Military Service Effective Date
		try {
			commsLogForm.setEffectiveDate(df.format(person.getEnrollmentDetermination().getEffectiveDate()));
		} catch (Exception ex ) {
			commsLogForm.setEffectiveDate("N/A");
		}

		// Get the Geocode Date
		try {
			commsLogForm.setGeocodeDate(df.format(gt.getGeocodeDate()));
		} catch (Exception ex ) {
			commsLogForm.setGeocodeDate("N/A");
		}

		// Get the combat Veteran Status
		Date today = new Date();
		Date combatStatusEndDate = person.getMilitaryService().getCombatVeteranEligibilityEndDate();
		commsLogForm.setCombatVeteranStatus(
			(combatStatusEndDate != null && combatStatusEndDate.compareTo(today) > 0) ? "Yes" : "No"
		);

		// Get the Special Factor
		commsLogForm.setSpecialAuthority("No");
		Iterator specialFactors = person.getSpecialFactors().iterator();
		while (specialFactors.hasNext()) {
			SpecialFactor specialFactor = (SpecialFactor) specialFactors.next();
			if (specialFactor.getSpecialFactorIndicator().equals("Y")) {
				commsLogForm.setSpecialAuthority("Yes");
			};
		}
		
		
		return mapping.findForward("vcDetermination");
	}

	
	public ActionForward displayVCDeterminationHistory(ActionMapping mapping,
			ActionForm form,
			HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		
		VCDeterminationHistoryForm history = (VCDeterminationHistoryForm) form;
		
		Person person = getSelectedPerson(request);
		VeteransChoiceInformationService vcis = this.getVeteransChoiceInformationService();
		//List vchist = vcis.fetchVCDeterminationHistory( input);
		
		List vcts = vcis.fetchVCChangeTimeLog(person);
		if(vcts == null){
			vcts = new ArrayList<String>();
			vcts.add(new Date().toString());
		}
		
		request.setAttribute("vctimelog", vcts);
		
		request.setAttribute("vchist", history);


		return mapping.findForward("vcDeterminationHistoryView");
	}


    /**
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    public void afterPropertiesSet()
    {
        // Check for required components here
    }

    @SuppressWarnings("unchecked")
	protected Map getKeyMethodMap()
    {
        Map map = new HashMap();
        map.put("title.commsLog", "display");
        map.put("title.availForMailing", "displayAvailMailing");
        map.put("title.rejectReason", "displayRejectReason");
        map.put("title.commsDetail", "displayDetail");
        map.put("title.handbookDetail", "displayHandbookDetail");
        map.put("title.deliveryPreferences", "displayDeliveryPreferences");
        //CCR 10386 Handbook project
        map.put("title.handbookStatus", "displayHandbookStatus");

        // 3.6 CCR 10956
        map.put("link.viewRawData", "viewRawData");

        map.put("button.mail", "mail");
        map.put("button.remail", "remail");
        map.put("title.remailACA", "remailACA");
        map.put("title.cancelACA", "cancelACAMail");
        map.put("button.update", "update");
        map.put("button.cancel", "cancel");

        map.put("title.vhicCardStatus", "displayVHICCardStatus");
        map.put("title.irsSubmission", "displayIRSSubmission");
        map.put("title.vcDetermination", "displayVCDetermination");
        map.put("title.vcDeterminationHistory", "displayVCDeterminationHistory");
        map.put("title.irsCorrection", "displayIRSCorrection");
        //map.put("link.sendReplacement", "sendReplacement");
        map.put("button.queryVHIC", "displayVHICCardStatusFromVHIC");
        map.put("button.submitIRS", "submitIRS");
        map.put("button.cancelIRS", "cancelIRS");
        map.put("button.viewDataTaxYear","displayIRSCorrectionForYear");
        map.put("title.acaDetail","displayACADetail");
        map.put("title.acaDoc","displayACADoc");
        map.put("text.returnACA", "cancelACADetail");
        map.put("text.cancelACAMail", "cancelACAMail");
        return map;
    }

    protected boolean processValidationMsgs(List conditions, HttpServletRequest request,
        CommsLogForm form)
    {
        // Condition is a list of 2 list:
        // 1) requiredFieldMissingList &
        // 2) otherReasonsList
        boolean hasRejects = false;
        if (conditions != null)
        {
            List processList = (List)conditions.get(0);
            form.setRequiredFieldMissingInd(true);
            if (processList.isEmpty())
            {
                processList = (List)conditions.get(1);
                form.setRequiredFieldMissingInd(false);
            }

            Iterator i = processList.iterator();
            while (i.hasNext())
            {
                addActionMessage(request, i.next().toString());
                hasRejects = true;
            }
        }

        // Return whether any rejects were present
        return hasRejects;
    }

    protected String formatComment(String comment, HttpServletRequest request)
    {
        // prepend date and user to comment
        String user = "weblogic";
        SecurityContext securityContext = getSecurityContext(request);
        if (securityContext != null)
        {
            ESRUserPrincipal userPrincipal = (ESRUserPrincipal)securityContext.getUserPrincipal();
            user = userPrincipal.getName();
        }

        StringBuffer format = new StringBuffer();
        Date dt = new Date();
        format.append(DateUtils.format(dt, null));
        format.append("   ");
        format.append(user);
        format.append("   ");
        format.append(comment);
        return format.toString();
    }

    protected CommsLogForm getCommsLogForm(ActionForm form)
        throws ServiceConfigurationException
    {
        CommsLogForm specificForm =
            (form instanceof CommsLogForm) ? (CommsLogForm)form : null;
        if (specificForm == null)
        {
            throw new ServiceConfigurationException(
                "CommsLogForm not properly configured.");
        }
        return specificForm;


    }

    public void populateCorrectionForm(CommsLogForm form, IrsTransmissionLogDetailEntry recent, List taxYearList,  HttpServletRequest request) {

    	form.setTaxYearList(taxYearList);
    	form.setAddress(getSelectedPerson(request).getPermanentAddress());
    	Calendar now = Calendar.getInstance();


    	if (recent.getSubmittedData() != null && recent.getSubmittedData().getMecPeriod() != null) {

	    	form.setCoveredJan((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("1") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("1")  : false );
	    	form.setCoveredFeb((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("2") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("2")  : false );
	    	form.setCoveredMar((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("3") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("3") :  false);
	    	form.setCoveredApr((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("4") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("4")  : false );
	    	form.setCoveredMay((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("5") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("5")  : false );
	    	form.setCoveredJun((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("6") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("6")  : false );
	    	form.setCoveredJul((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("7") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("7")  : false );
	    	form.setCoveredAug((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("8") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("8")  : false );
	    	form.setCoveredSep((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("9") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("9")  : false );
	    	form.setCoveredOct((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("10") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("10")  : false );
	    	form.setCoveredNov((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("11") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("11")  : false );
	    	form.setCoveredDec((boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().containsKey("12") ? (Boolean)recent.getSubmittedData().getMecPeriod().getCoverageMonths().get("12")  : false );
	    } else {
	    	MECPeriod m = this.getIrsTransmissionService().combineAllPeriods(recent.getPersonId(), now.get(Calendar.YEAR));
	    	form.setCoveredJan((boolean)m.getCoverageMonths().containsKey("1") ? (Boolean)m.getCoverageMonths().get("1")  : false );
	    	form.setCoveredFeb((boolean)m.getCoverageMonths().containsKey("2") ? (Boolean)m.getCoverageMonths().get("2")  : false );
	    	form.setCoveredMar((boolean)m.getCoverageMonths().containsKey("3") ? (Boolean)m.getCoverageMonths().get("3") :  false);
	    	form.setCoveredApr((boolean)m.getCoverageMonths().containsKey("4") ? (Boolean)m.getCoverageMonths().get("4")  : false );
	    	form.setCoveredMay((boolean)m.getCoverageMonths().containsKey("5") ? (Boolean)m.getCoverageMonths().get("5")  : false );
	    	form.setCoveredJun((boolean)m.getCoverageMonths().containsKey("6") ? (Boolean)m.getCoverageMonths().get("6")  : false );
	    	form.setCoveredJul((boolean)m.getCoverageMonths().containsKey("7") ? (Boolean)m.getCoverageMonths().get("7")  : false );
	    	form.setCoveredAug((boolean)m.getCoverageMonths().containsKey("8") ? (Boolean)m.getCoverageMonths().get("8")  : false );
	    	form.setCoveredSep((boolean)m.getCoverageMonths().containsKey("9") ? (Boolean)m.getCoverageMonths().get("9")  : false );
	    	form.setCoveredOct((boolean)m.getCoverageMonths().containsKey("10") ? (Boolean)m.getCoverageMonths().get("10")  : false );
	    	form.setCoveredNov((boolean)m.getCoverageMonths().containsKey("11") ? (Boolean)m.getCoverageMonths().get("11")  : false );
	    	form.setCoveredDec((boolean)m.getCoverageMonths().containsKey("12") ? (Boolean)m.getCoverageMonths().get("12")  : false );
	    }
    }

}