/********************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.esr.ui.militaryservice.action;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.ee.CampLejeuneVerificationMethod;
import gov.va.med.esr.common.model.ee.CombatEpisode;
import gov.va.med.esr.common.model.lookup.Indicator;
import gov.va.med.esr.common.model.lookup.OEFOIFSource;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.util.CommonDateUtils;
import gov.va.med.esr.ui.ApplicationConstants.MessageKeys;
import gov.va.med.esr.ui.common.util.DateUtils;
import gov.va.med.esr.ui.util.SessionManager;
import gov.va.med.fw.util.StringUtils;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;

/**
 * Provides validation methods for military service.
 *
 * @author Muddaiah Ranga
 * @version 3.0
 */
public class MilitaryServiceValidator implements MilitaryServiceConstants
{
    /**
     * Validates the military service form.
     *
     * @param form the military service form.
     * @param request the request object.
     *
     * @return the action messages.
     */
    protected static ActionMessages validateMilitaryService(MilitaryServiceInfoForm form,HttpServletRequest request, Person person)
    {
        MessageResources messageResources = form.getResources(request);
        ActionMessages messages = form.getActionMessages(request);

        //validateCurrentMilitaryService(form,messages,messageResources);
        validateMedalOfHonor(form,messages,messageResources);
        validateCampLejeune(form,messages,messageResources);

        //Create a map of OefOif Combat Episodes
        Map oefOifCombatEpisodeMap = new HashMap();

        if (person != null && person.getMilitaryService() != null) {
        	oefOifCombatEpisodeMap = MilitaryServiceActionHelper.getMapFromCollection(person.getMilitaryService().getCombatEpisodes());
        }

        for(int i=0; i<form.getOefOifCombatEpisodeIdList().size(); i++)
        {
            String id = (String)form.getOefOifCombatEpisodeId(i);
            CombatEpisode episode = (StringUtils.isNotEmpty(id)) ? (CombatEpisode)oefOifCombatEpisodeMap.get(id) : null;
            String oefOifSource = form.getOefOifCombatSource(i);

            //Validate only HEC records and those modified by HEC
            if(StringUtils.equals(oefOifSource,OEFOIFSource.CODE_CENTRALIZED_ELIGIBILITY_VERIFICATION.getCode()) ||
               form.isOefOifCombatEpisodeChanged(i,episode) ) {
                validateOefOifCombatEpisode(form,i,messages,messageResources);
            }
        }

        boolean isAddAPerson = false;
        isAddAPerson = SessionManager.isAddAPerson(request);
        form.setAddAPerson(isAddAPerson);


        for(int i=0; i<form.getServiceEpisodeIdList().size(); i++)
        {
            validateServiceEpisode(form,i,messages,messageResources);
        }

        for(int i=0; i<form.getConflictEpisodeIdList().size(); i++)
        {
            validateConflictEpisode(form,i,messages,messageResources);
        }
        return messages;
    }

    private static void validateMedalOfHonor(MilitaryServiceInfoForm form, ActionMessages errors, MessageResources messageResources)
    {
    	if ( StringUtils.isNotBlank(form.getMohInd()) && "y".equalsIgnoreCase(form.getMohInd()) )
		{
    		String label = null;
    		String labelTxt = null;
    		boolean isValid = true;
    		String mohDocumentReceiptDate = form.getDocumentReceiptDate();
            label = "Medal of Honor "+messageResources.getMessage(LABEL_MOH_DOCUMENT_RECEIPT_DATE);

              if (StringUtils.isNotEmpty(mohDocumentReceiptDate)){
            	 try {
            	  isValid = validateDate(mohDocumentReceiptDate,"documentReceiptDate",label,errors);
            	  if (isValid){
            		CommonDateUtils.getDate(mohDocumentReceiptDate, true);
    				Date receiptdate = DateUtils.getDate(mohDocumentReceiptDate, true);
    	            Date current = DateUtils.getCurrentDateTime();
    	            if (receiptdate!=null && receiptdate.compareTo(current) > 0) {
    	            	 errors.add("documentReceiptDate",new ActionMessage(MessageKeys.ERRORS_DETAIL, label+" cannot be a future date"));
    	            }
            	  }

            	  if (StringUtils.isEmpty(form.getDocumentType()))
      			  {
            		  labelTxt = messageResources.getMessage(LABEL_MOH_DOCUMENT_TYPE);
                      errors.add("documentType",new ActionMessage(MessageKeys.ERRORS_REQUIRED,labelTxt));
      			  }

            	  labelTxt = null;
            	  if (StringUtils.isEmpty(form.getDataSource()))
      			  {
            		  labelTxt = messageResources.getMessage(LABEL_MOH_DOCUMENT_SOURCE);
                      errors.add("dataSource",new ActionMessage(MessageKeys.ERRORS_REQUIRED,labelTxt));
      			  }

            	 }catch (Exception e){
            		 // should never throw exception here as it is valid date
            		 errors.add("documentReceiptDate", new ActionMessage(MessageKeys.ERRORS_DETAIL, label+" must be a precise date."));
            	 }
              }
		}
    }

    private static void validateCurrentMilitaryService(MilitaryServiceInfoForm form, ActionMessages errors, MessageResources messageResources)
    {
        String label = null;
        if(StringUtils.isEmpty(form.getDischargeDueToDisability()))
        {
            label = messageResources.getMessage(LABEL_DISCHARGE_DUE_TO_DISABILITY);
            errors.add("dischargeDueToDisability",new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
        }

        if(StringUtils.isEmpty(form.getRetirementDueToMilitaryDisability()))
        {
            label = messageResources.getMessage(LABEL_MILITARY_DISABILITY_RETIRMENT);
            errors.add("retirementDueToMilitaryDisability",new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
        }

        if(StringUtils.isEmpty(form.getExposedToContaminants()))
        {
            label = messageResources.getMessage(LABEL_ENVIRONMENT_CONTAMINANTS);
            errors.add("exposedToContaminants",new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
        }

        if(StringUtils.isEmpty(form.getShad()))
        {
            label = messageResources.getMessage(LABEL_SHAD);
            errors.add("shad",new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
        }
        if(form.getCampLejeuneVerificationComments().length()>200)
        {
        	label = messageResources.getMessage(LABEL_CAMPLEJEUNE);
        	errors.add("campLejeuneVerificationComments", new ActionMessage("Comments is limitted to 200 characters"));
        }

    }

    private static void validateServiceEpisode(MilitaryServiceInfoForm form, int serviceEpisodeIndex,ActionMessages errors,MessageResources messageResources)
    {

    	if(form.isAddAPerson()){
    		if(form.isServiceEpisodeEmpty(serviceEpisodeIndex)){
    			validateMilitaryServiceNumber(form, serviceEpisodeIndex, errors, messageResources);
                validateMilitaryServiceComponent(form, serviceEpisodeIndex, errors, messageResources);
    			validateMilitaryServiceElements(form, serviceEpisodeIndex, errors, messageResources);
    		}
    		else{
    			validateMilitaryServiceComponent(form, serviceEpisodeIndex, errors, messageResources);
    			validateMilitaryServiceElements(form, serviceEpisodeIndex, errors, messageResources);
    		}
    	}
    	else{
    		if(!form.isServiceEpisodeEmpty(serviceEpisodeIndex))
            {
                validateMilitaryServiceElements(form, serviceEpisodeIndex, errors, messageResources);
            }
    	}

    }

    private static void validateMilitaryServiceElements(MilitaryServiceInfoForm form, int serviceEpisodeIndex, ActionMessages errors, MessageResources messageResources) {
		String index = "[" + serviceEpisodeIndex + "]";
		String label = null;

		String branchOfService = (String)form.getServiceEpisodeBranchOfServiceList().get(serviceEpisodeIndex);
		if(StringUtils.isEmpty(branchOfService))
		{
		    label = messageResources.getMessage(LABEL_BRANCH_OF_SERVICE);
		    errors.add("serviceEpisodeBranchOfService" + index,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
		}

		String entryDate = (String)form.getServiceEpisodeEntryDateList().get(serviceEpisodeIndex);
		label = messageResources.getMessage(LABEL_SERVICE_ENTERY_DATE);
		validateDate(entryDate,"serviceEpisodeEntryDate" + index,label,errors);

		String separationDate = (String)form.getServiceEpisodeSeparationDateList().get(serviceEpisodeIndex);
		label = messageResources.getMessage(LABEL_SERVICE_SEPARATION_DATE);
		validateDate(separationDate,"serviceEpisodeSeparationDate" + index,label,errors);

		String dischargeType = (String)form.getServiceEpisodeDischargeTypeList().get(serviceEpisodeIndex);
		if(StringUtils.isEmpty(dischargeType))
		{
		    label = messageResources.getMessage(LABEL_DISCHARGE_TYPE);
		    errors.add("serviceEpisodeDischargeType" + index,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
		}
	}

    private static void validateMilitaryServiceComponent(MilitaryServiceInfoForm form, int serviceEpisodeIndex, ActionMessages errors, MessageResources messageResources) {
		String index = "[" + serviceEpisodeIndex + "]";
		String label = null;

		String msComponent = (String)form.getServiceEpisodeServiceComponentList().get(serviceEpisodeIndex);
		if(StringUtils.isEmpty(msComponent))
		{
		    label = messageResources.getMessage(LABEL_SERVICE_COMPONENT);
		    errors.add("serviceEpisodeServiceComponent" + index,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
		}
	}

    private static void validateMilitaryServiceNumber(MilitaryServiceInfoForm form, int serviceEpisodeIndex, ActionMessages errors, MessageResources messageResources) {
		String index = "[" + serviceEpisodeIndex + "]";
		String label = null;

		String msComponent = (String)form.getServiceEpisodeMilitaryServiceNumberList().get(serviceEpisodeIndex);
		if(StringUtils.isEmpty(msComponent))
		{
		    label = messageResources.getMessage(LABEL_MILITARY_SERVICE_NUMBER);
		    errors.add("serviceEpisodeMilitaryServiceNumber" + index,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
		}
	}


    private static void validateConflictEpisode(MilitaryServiceInfoForm form, int conflictEpisodeIndex,ActionMessages errors,MessageResources messageResources)
    {
        if(!form.isConflictEpisodeEmpty(conflictEpisodeIndex))
        {
            String index = "[" + conflictEpisodeIndex + "]";

            String label = null;
            String startDate = (String)form.getConflictEpisodeStartDateList().get(conflictEpisodeIndex);
            label = messageResources.getMessage(LABEL_CONFLICT_START_DATE);
            validateDate(startDate,"conflictEpisodeStartDate" + index,label,errors);

            String endDate = (String)form.getConflictEpisodeEndDateList().get(conflictEpisodeIndex);
            label = messageResources.getMessage(LABEL_CONFLICT_END_DATE);
            validateDate(endDate,"conflictEpisodeEndDate" + index,label,errors);

            String location = (String)form.getConflictEpisodeLocationList().get(conflictEpisodeIndex);
            if(StringUtils.isEmpty(location))
            {
                label = messageResources.getMessage(LABEL_CONFLICT_LOCATION);
                errors.add("conflictEpisodeLocation" + index,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
            }
        }
    }

    private static void validateOefOifCombatEpisode(MilitaryServiceInfoForm form, int oefOifCombatEpisode,ActionMessages errors,MessageResources messageResources)
    {
        if(!form.isOefOifCombatEpisodeEmpty(oefOifCombatEpisode))
        {
            String index = "[" + oefOifCombatEpisode + "]";

            String label = null;
            String startDate = (String)form.getOefOifCombatEpisodeStartDateList().get(oefOifCombatEpisode);
            label = messageResources.getMessage(LABEL_CONFLICT_START_DATE);
            validateDate(startDate,"oefOifCombatEpisodeStartDate" + index,label,errors);

            String endDate = (String)form.getOefOifCombatEpisodeEndDateList().get(oefOifCombatEpisode);
            label = messageResources.getMessage(LABEL_CONFLICT_END_DATE);
            validateDate(endDate,"oefOifCombatEpisodeEndDate" + index,label,errors);

            String location = (String)form.getOefOifCombatEpisodeLocationList().get(oefOifCombatEpisode);
            if(StringUtils.isEmpty(location))
            {
                label = messageResources.getMessage(LABEL_CONFLICT_LOCATION);
                errors.add("oefOifCombatEpisodeLocation" + index,new ActionMessage(MessageKeys.ERRORS_REQUIRED,label));
            }
        }
    }

    /**
     * Validate the date for the correct format.
     *
     * @param fieldValue the date field value
     * @param fieldName the field name
     * @param fieldLabel field label
     * @param errors the validation error object
     */
    private static boolean validateDate(String fieldValue,String fieldName,String fieldLabel,ActionMessages errors)
    {
        boolean isValid = true;
        if(StringUtils.isNotEmpty(fieldValue))
        {
            try
            {
                DateUtils.getDate(fieldValue);
            }
            catch (Exception ex)
            {
                isValid = false;
                try {
                    ImpreciseDate impDate = DateUtils.getImpreciseDate(fieldValue);
                    if(impDate != null) {
                        errors.add(fieldName,new ActionMessage(ERROR_DATE_MUST_BE_PRECISE,fieldLabel));
                    } else {
                        errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_INVALID,fieldLabel));
                    }
                } catch(Exception ex1) {
                    errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_INVALID,fieldLabel));
                }
            }
        }
        else
        {
            isValid = false;
            errors.add(fieldName,new ActionMessage(MessageKeys.ERRORS_REQUIRED,fieldLabel));
        }
        return isValid;
    }

    private static void validateCampLejeune(MilitaryServiceInfoForm form, ActionMessages errors, MessageResources messageResources) {

    	if ( form.getCampLejeuneInd()!= null && StringUtils.isNotBlank(form.getCampLejeuneInd()) && Indicator.YES.getCode().equalsIgnoreCase(form.getCampLejeuneInd()) )
		{
    		String label = null;
    		boolean isValid = true;
    		String campLejeuneChangeDate = form.getCampLejeuneChangeDate();
    		label = "Camp Lejeune "+messageResources.getMessage(LABEL_CLV_CHANGE_DATE);

          if (StringUtils.isNotEmpty(campLejeuneChangeDate)){

        	  isValid = validateDate(campLejeuneChangeDate,"campLejeuneChangeDate",label,errors);
        	  if (isValid){
        		CommonDateUtils.getDate(campLejeuneChangeDate, true);
				Date receiptdate = DateUtils.getDate(campLejeuneChangeDate, true);
	            Date current = DateUtils.getCurrentDateTime();
	            if (receiptdate!=null && receiptdate.compareTo(current) > 0) {
	            	 errors.add("campLejeuneChangeDate",new ActionMessage(MessageKeys.ERRORS_DETAIL, label+" cannot be a future date"));
	            }
        	  }
          }
		}
    	  if(form.getCampLejeuneVerificationComments()!= null && form.getCampLejeuneVerificationComments().length()>200)
          {

          	String label = messageResources.getMessage(LABEL_CLV_COMMENTS);
          	errors.add("campLejeuneVerificationComments", new ActionMessage(MessageKeys.ERRORS_DETAIL, label+"is limitted to 200 characters"));
          }

    	  // CCR13875
    	  List<String> clvms=null;
          if(form.getCampLejeuneVerificationMethods()!= null)
             clvms =Arrays.asList(form.getCampLejeuneVerificationMethods());
          Iterator clvmsIter = (clvms != null) ? clvms.iterator() : null;
          if(clvmsIter!=null)
          {
              while (clvmsIter.hasNext()) {
                  String clveficationMethod = (String)clvmsIter.next();
                  if (clveficationMethod.equalsIgnoreCase("7")&&((form.getCampLejeuneVerificationComments() == null) || (form.getCampLejeuneVerificationComments().equals("")))){
                      String label = messageResources.getMessage(LABEL_CLV_COMMENTS);
                      errors.add("campLejeuneVerificationComments", new ActionMessage(MessageKeys.ERRORS_DETAIL, label+" are required when the verified method Other is selected."));
                   }
              }
          }
    }
}
