package gov.va.med.esr.ui.militaryservice.action;

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

import javax.servlet.http.HttpServletRequest;

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

import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.ee.AgentOrangeExposure;
import gov.va.med.esr.common.model.ee.CampLejeuneVerification;
import gov.va.med.esr.common.model.ee.CampLejeuneVerificationMethod;
import gov.va.med.esr.common.model.ee.CancelDecline;
import gov.va.med.esr.common.model.ee.CombatEpisode;
import gov.va.med.esr.common.model.ee.CombatService;
import gov.va.med.esr.common.model.ee.ConflictExperience;
import gov.va.med.esr.common.model.ee.EnvironmentalContaminationExposure;
import gov.va.med.esr.common.model.ee.HealthBenefitPlan;
import gov.va.med.esr.common.model.ee.IncompetenceRuling;
import gov.va.med.esr.common.model.ee.MilitaryService;
import gov.va.med.esr.common.model.ee.MilitaryServiceEpisode;
import gov.va.med.esr.common.model.ee.MilitaryServiceSiteRecord;
import gov.va.med.esr.common.model.ee.Pension;
import gov.va.med.esr.common.model.ee.RadiationExposure;
import gov.va.med.esr.common.model.ee.SHAD;

import gov.va.med.esr.common.model.lookup.AgentOrangeExposureLocation;
import gov.va.med.esr.common.model.lookup.ApplicationMethod;
import gov.va.med.esr.common.model.lookup.CampLejeuneChangeSource;
import gov.va.med.esr.common.model.lookup.CampLejeuneVerificationType;
import gov.va.med.esr.common.model.lookup.CancelDeclineReason;
import gov.va.med.esr.common.model.lookup.CombatPayType;
import gov.va.med.esr.common.model.lookup.ConflictLocation;
import gov.va.med.esr.common.model.lookup.DecorationStatus;
import gov.va.med.esr.common.model.lookup.DischargeType;
import gov.va.med.esr.common.model.lookup.FilipinoVeteranProof;
import gov.va.med.esr.common.model.lookup.Indicator;
import gov.va.med.esr.common.model.lookup.MilitaryServiceComponent;
import gov.va.med.esr.common.model.lookup.OEFOIFSource;
import gov.va.med.esr.common.model.lookup.PHDocumentType;
import gov.va.med.esr.common.model.lookup.PensionReasonCode;
import gov.va.med.esr.common.model.lookup.RadiationExposureMethod;
import gov.va.med.esr.common.model.lookup.ServiceBranch;
import gov.va.med.esr.common.model.lookup.ServicePeriod;
import gov.va.med.esr.common.model.lookup.VAFacility;
import gov.va.med.esr.common.model.person.BirthRecord;
import gov.va.med.esr.common.model.person.Person;
import gov.va.med.esr.common.model.person.SSN;
import gov.va.med.esr.ui.common.service.LookupCacheService;
import gov.va.med.esr.ui.common.util.DateUtils;
import gov.va.med.esr.ui.common.util.JspUtils;
import gov.va.med.esr.ui.conversion.UIConversionServiceImpl;
import gov.va.med.esr.ui.util.ConvertUtils;
import gov.va.med.fw.conversion.ConversionServiceException;
import gov.va.med.fw.util.StringUtils;

import gov.va.med.esr.common.model.ee.MedalOfHonor;
import gov.va.med.esr.common.model.lookup.MHDataSource;
/**
 * Converter for converting ActionForm to MilitaryService and vice versa.
 *
 * @author Muddaiah Ranga
 * @version 3.0
 */
public class MilitaryServiceConversionService extends UIConversionServiceImpl
{
	public Object convert(Object source, Class targetClass)
	throws ConversionServiceException
	{
	    return null;
	}

    protected void convertBean(Object source, Object target)
	throws ConversionServiceException
	{
        if(source instanceof Person && target instanceof MilitaryServiceInfoForm)
        {
            MilitaryServiceInfoForm form = (MilitaryServiceInfoForm)target;
            Person person = (Person)source;
            try {
            	populateForm(person,form);
            }
            catch (Exception ex)
            {
                throw new ConversionServiceException("Conversion Failed", ex);
            }
        }
        else if(target instanceof Person && source instanceof MilitaryServiceInfoForm)
        {
            try
            {
                MilitaryServiceInfoForm form = (MilitaryServiceInfoForm)source;
                Person person = (Person)target;
                updateMilitaryService(form,person);
            }
            catch(Exception ex)
            {
                throw new ConversionServiceException("Error occured while updating person from MilitaryServiceInfoForm.",ex);
            }
        }
	}

 	private void populateForm(Person person, MilitaryServiceInfoForm form) throws ConversionServiceException
 	{

 	    if(form == null || person == null) return;
       	Set ssns = person.getSsns();
       	if ((ssns != null) && (ssns.size() > 0))
       	{
	    	SSN ssn = (SSN) ssns.iterator().next ();
	 	    form.setSsn(ssn.getSsnText());
       	}

       	BirthRecord birthRecord = person.getBirthRecord();
       	if(birthRecord != null)
       	{
       	    ImpreciseDate birthDate = birthRecord.getBirthDate();
       	    form.setBirthDate(JspUtils.displayValue(birthDate,JspUtils.STANDARD_DATE_FORMAT));
       	}

       	AgentOrangeExposure agentOrangeExposure = (AgentOrangeExposure)person.getSpecialFactorByType(AgentOrangeExposure.class);
       	if(agentOrangeExposure != null)
       	{
 	       AgentOrangeExposureLocation location = agentOrangeExposure.getLocation();
 	       if(location != null) form.setAgentOrangeExposureLocation(location.getCode());
       	}

       	RadiationExposure radiationExposure = (RadiationExposure)person.getSpecialFactorByType(RadiationExposure.class);
       	if(radiationExposure != null)
       	{
 	      RadiationExposureMethod method = radiationExposure.getExposureMethod();
          if(method != null) form.setRadiationExposureMethod(method.getCode());
       	}

       	// CCR10803 Edit/Add/Display MOH
       	populateMedalOfHonor(form,person);
        //
       	//////////////////CLV////////////////////
       	populateCampLejeune(form,person);

       	EnvironmentalContaminationExposure contExp = (EnvironmentalContaminationExposure)person.getSpecialFactorByType(EnvironmentalContaminationExposure.class);
        Indicator envInd = (contExp != null) ? contExp.getEnvironmentalContaminationExposureIndicator() : null;
       	form.setExposedToContaminants((envInd != null) ? envInd.getCode() : Indicator.UNKNOWN.getCode());

       	SHAD shad = (SHAD)person.getShad();
       	form.setShad((shad != null && shad.getShadIndicator() != null) ? shad.getShadIndicator().getCode() : Indicator.UNKNOWN.getCode());


 	    form.setEligibleForClassIIDental(this.getIndicatorCode(person.getEligibleForClassIIDental()));
        Date dueDate = person.getClassIIDentalApplicationDueBefore();
	    if(dueDate != null) form.setClassIIDentalApplicationDueBefore(DateUtils.format(dueDate,DateUtils.MMDDYYYY));

 	    MilitaryService militaryService = person.getMilitaryService();
 	    if(militaryService != null)
 	    {
 	        form.setDischargeDueToDisability(this.getIndicatorCode(militaryService.getDischargeDueToDisability()));
 	        form.setRetirementDueToMilitaryDisability(this.getIndicatorCode(militaryService.getDisabilityRetirementIndicator()));

 	        Date endDate = militaryService.getCombatVeteranEligibilityEndDate();
 	        if(endDate != null) form.setEligibilityEndDate(DateUtils.format(endDate,DateUtils.MMDDYYYY));

            // Populate Combat Services
 	        populateCombatServiceFields(form,militaryService.getCombatServices());

 	        // Populate OEF/OIF Combat Episodes
 	        populateCombatEpisodeFields(form,militaryService.getCombatEpisodes());

 	        MilitaryServiceSiteRecord militaryServiceSiteRecord = militaryService.getHECMilitaryServiceSiteRecord();
 	        if(militaryServiceSiteRecord != null)
 	        {
 	            ServicePeriod servicePeriod = militaryServiceSiteRecord.getServicePeriod();
                if(servicePeriod != null) form.setPeriodOfService(servicePeriod.getCode());

                FilipinoVeteranProof filipinoVeteranProof = militaryServiceSiteRecord.getFilipinoVeteranProof();
                if(filipinoVeteranProof != null) form.setFilipinoVeteranProof(filipinoVeteranProof.getCode());

                Set serviceEpisodes = militaryServiceSiteRecord.getMilitaryServiceEpisodes();
                populateServiceEpisodeFields(form,serviceEpisodes);

                Set conflictExperiences = militaryServiceSiteRecord.getConflictExperiences();
                populateConflictEpisodeFields(form,conflictExperiences);
 	        }
 	    }
 	}
 	////////////////////////CLV//////////////////////////////
 	private void populateCampLejeune(MilitaryServiceInfoForm form, Person person)
 	{
 		/*AgentOrangeExposure agentOrangeExposure = (AgentOrangeExposure)person.getSpecialFactorByType(AgentOrangeExposure.class);
    	 Indicator envInd = (contExp != null) ? contExp.getEnvironmentalContaminationExposureIndicator() : null;
        	form.setExposedToContaminants((envInd != null) ? envInd.getCode() : Indicator.UNKNOWN.getCode());*/

 		CampLejeuneVerification clv = null;
 		if(person != null)
 		{
 			clv = (CampLejeuneVerification)person.getSpecialFactorByType(CampLejeuneVerification.class);

 			//clv = person.getCampLejeuneVerification();
 			form.setCampLejeuneInd((clv != null && clv.getSpecialFactorIndicator() != null) ? clv.getSpecialFactorIndicator().getCode() : Indicator.UNKNOWN.getCode());

 			if(clv!= null)
 			{
 				/*Indicator clvInd = clv.getSpecialFactorIndicator();
 						if(clvInd != null)
 				{
 					String clvStr = "";
 				   if(clvInd.getCode().equals("1")) //temp fix, should be fixed in UI
 		            	clvStr="y";
 		            else if(clvInd.getCode().equals("0"))
 		            	clvStr="n";

 					form.setCampLejeuneInd(clvStr);
 				}
 				else
 					form.setCampLejeuneInd(Indicator.UNKNOWN.getCode());*/

 				if( clv.getVerificationType()!= null && clv.getVerificationType()!= null)
 					form.setCampLejeuneVerificationMethod(clv.getVerificationType().getCode());
 				else
 					form.setCampLejeuneVerificationMethod("");

 				/////////////////////13629///////////////////////////////////////////////////////
 				if(clv.getInternalCampLejeuneVerificationMethods()!=null && clv.getInternalCampLejeuneVerificationMethods().size()>0)
 				{
 					Set<CampLejeuneVerificationMethod> clvms = clv.getInternalCampLejeuneVerificationMethods();
 					StringBuffer strMethod =  new StringBuffer();

 					for(CampLejeuneVerificationMethod clvm: clvms)
 					{
 						strMethod.append(clvm.getVerificationType().getCode());
 						strMethod.append(",");
 					}
 					form.setCampLejeuneVerificationMethods(strMethod.toString().split(","));
  				}

 				/////////////////////13629///////////////////////////////////////////////////////
 				if(clv.getComments()!=null)
 					form.setCampLejeuneVerificationComments(clv.getComments());
 				else
 					form.setCampLejeuneVerificationComments("");
 				if(clv.getChangeDate()!=null)
 					form.setCampLejeuneChangeDate(JspUtils.displayValue(clv.getChangeDate(), null));
 				if(clv.getChangeSite()!=null)
 					form.setCampLejeuneChangeSite(clv.getChangeSite().getDescription());
 				else
 					form.setCampLejeuneChangeSite("");
 				if(clv.getChangeSource()!=null)
 				{
 					if(clv.getChangeSource().getCode().equals(CampLejeuneChangeSource.CODE_HEC.getCode()) )
 					{
 						//form.setCampLejeuneChangeSource(getLoggedInUser().getName());
 						//13895//
 						if(clv.getModifiedBy()!=null && clv.getModifiedBy().getName()!= null && !clv.getModifiedBy().getName().equalsIgnoreCase("MsdsService"))
 							form.setCampLejeuneChangeSource(clv.getModifiedBy().getName());
 						else
 							form.setCampLejeuneChangeSource(clv.getChangeSource().getDescription());
 					}
 					else
 					{
 						form.setCampLejeuneChangeSource(clv.getChangeSource().getDescription());
 					}

 				}
 				else
 					form.setCampLejeuneChangeSource("");
 			}
 		}
 	}
 	private void populateMedalOfHonor(MilitaryServiceInfoForm form,Person person) {

		MedalOfHonor moh = this.getMoH(person);
		// moh indicator
 		form.setMohInd(this.getMedalOfHonorIndicator(person));
       	form.setOnFileMohInd(this.getMedalOfHonorIndicator(person));

        if (moh != null)
        {
	       	// display only field - status update date
        	form.setMhLastStatusUpdateDate(JspUtils.displayValue(moh.getStatusLastUpdateDate(), null));
	       	// display only field - deocoration status
	       	form.setStatus(moh.getStatus()==null? "" : moh.getStatus().getDescription());

	        // other editable fields
	        form.setDocumentReceiptDate(JspUtils.displayValue(moh.getDocumentReceiptDate(), null));
	        form.setOnFileDocumentReceiptDate(JspUtils.displayValue(moh.getDocumentReceiptDate(), null));

	        form.setDocumentType(moh.getDocumentType()==null? "" : moh.getDocumentType().getCode());
	        form.setOnFileDocumentType(moh.getDocumentType()==null? "" : moh.getDocumentType().getCode());

	        form.setDataSource(moh.getDataSource()==null? "" : moh.getDataSource().getCode());
	        form.setOnFileMohDataSource(moh.getDataSource()==null? "" : moh.getDataSource().getCode());
        }
        else {
        	form.setMhLastStatusUpdateDate(null);
        	form.setStatus("");

        	form.setDocumentReceiptDate( null);
 	        form.setOnFileDocumentReceiptDate(null);

 	        form.setDocumentType("");
 	        form.setOnFileDocumentType("");

 	        form.setDataSource("");
 	        form.setOnFileMohDataSource("");
        }
 	}

 	 private MedalOfHonor getMoH(Person person)
     {
     	if (person != null )
     	{
     		return person.getMedalOfHonor();
     	}
     	return null;
     }


   // Medal of Honor Indicator
	public String getMedalOfHonorIndicator(Person person) {
		MedalOfHonor moh = person.getMedalOfHonor();
		if (moh == null)
			return ConvertUtils.NULL_VALUE;
		else
			return ConvertUtils.convertYesNoNoData(moh.getMhIndicator());
	}

 	private void populateServiceEpisodeFields(MilitaryServiceInfoForm form, Set serviceEpisodes)
 	{
 	    if(serviceEpisodes != null && !serviceEpisodes.isEmpty())
 	    {
 	        List sortedServiceEpisodes = MilitaryServiceActionHelper.sortMilitaryServiceEpisodes(serviceEpisodes);
 	        MilitaryServiceEpisode serviceEpisode = null;

 	        String id=null,militaryServiceNumber=null,branchOfService=null,entryDate=null,separationDate=null,dischargeType=null,serviceComponent=null,hashCode=null;
 	        for(Iterator iter = sortedServiceEpisodes.iterator(); iter.hasNext();)
 	        {
 	            serviceEpisode = (MilitaryServiceEpisode)iter.next();
 	            if(serviceEpisode != null)
 	            {
 	            	id = (serviceEpisode.getEntityKey() != null) ? serviceEpisode.getEntityKey().getKeyValueAsString() : "";
 	                militaryServiceNumber = serviceEpisode.getServiceNumber();
 	                branchOfService = serviceEpisode.getServiceBranch() == null ? "" : serviceEpisode.getServiceBranch().getCode();
 	                entryDate = JspUtils.displayValue(serviceEpisode.getStartDate(),JspUtils.STANDARD_DATE_FORMAT);
 	                separationDate = JspUtils.displayValue(serviceEpisode.getEndDate(),JspUtils.STANDARD_DATE_FORMAT);
 	                dischargeType = serviceEpisode.getDischargeType() == null ? "" : serviceEpisode.getDischargeType().getCode();
 	                serviceComponent = serviceEpisode.getMilitaryServiceComponent() == null ? "" : serviceEpisode.getMilitaryServiceComponent().getCode();
 	                hashCode = String.valueOf(serviceEpisode.hashCode());
 	                form.addServiceEpisode(id,militaryServiceNumber,"",branchOfService,entryDate,separationDate,dischargeType,serviceComponent,hashCode);
 	            }
 	        }
 	    }
 	}

    private void populateCombatServiceFields(MilitaryServiceInfoForm form, Set combatServices)
    {
        if(combatServices != null && !combatServices.isEmpty())
        {
            List sortedCombatServices = MilitaryServiceActionHelper.sortCombatServices(combatServices);
            CombatService combatService = null;
            String id=null,startDate=null,endDate=null,location=null,source=null;
            for(Iterator iter = sortedCombatServices.iterator(); iter.hasNext();)
            {
                combatService = (CombatService)iter.next();
                if(combatService != null)
                {
                    id = (combatService.getEntityKey() != null) ? combatService.getEntityKey().getKeyValueAsString() : "";
                    startDate = combatService.getPayStartDate() == null ? "" : JspUtils.displayValue(combatService.getPayStartDate(),JspUtils.STANDARD_DATE_FORMAT);
                    endDate = combatService.getPayEndDate() == null ? "" : JspUtils.displayValue(combatService.getPayEndDate(),JspUtils.STANDARD_DATE_FORMAT);
                    location = combatService.getMsdsCountry() == null ? "" : combatService.getMsdsCountry().getName();
                    source = combatService.getCombatServiceSource() == null ? "" : combatService.getCombatServiceSource().getCode();
                    form.addCombatService(id,startDate,endDate,location,source);
                }
            }
        }
    }

    private void populateCombatEpisodeFields(MilitaryServiceInfoForm form, Set combatEpisodes)
    {
        if(combatEpisodes != null && !combatEpisodes.isEmpty())
        {
            List sortedCombatEpisodes = MilitaryServiceActionHelper.sortCombatEpisodes(combatEpisodes);
            CombatEpisode combatEpisode = null;
            String id=null,startDate=null,endDate=null,location=null,payType=null,source=null,hashCode=null;
            for(Iterator iter = sortedCombatEpisodes.iterator(); iter.hasNext();)
            {
                combatEpisode = (CombatEpisode)iter.next();
                if(combatEpisode != null)
                {
                    id = (combatEpisode.getEntityKey() != null) ?combatEpisode.getEntityKey().getKeyValueAsString() : "";
                    startDate = combatEpisode.getStartDate() == null ? "" : JspUtils.displayValue(combatEpisode.getStartDate(),JspUtils.STANDARD_DATE_FORMAT);
                    endDate = combatEpisode.getEndDate() == null ? "" : JspUtils.displayValue(combatEpisode.getEndDate(),JspUtils.STANDARD_DATE_FORMAT);
                    location = combatEpisode.getConflictLocation() == null ? "" : combatEpisode.getConflictLocation().getCode();
                    payType = combatEpisode.getCombatPayType() == null ? "" : combatEpisode.getCombatPayType().getCode();
                    if(combatEpisode.getOEFOIFSource() != null) {
                        source = combatEpisode.getOEFOIFSource() == null ? "" : combatEpisode.getOEFOIFSource().getCode();
                    } else {
                        source = combatEpisode.getOEFOIFStationNumber() == null ? "" : combatEpisode.getOEFOIFStationNumber().getFacilityName();
                    }
                    hashCode = String.valueOf(combatEpisode.hashCode());
                    form.addOefOifCombatEpisode(id,startDate,endDate,location,source,payType,hashCode);
                }
            }
        }
    }

 	private void populateConflictEpisodeFields(MilitaryServiceInfoForm form, Set conflictExperiences)
 	{
 	    if(conflictExperiences != null && !conflictExperiences.isEmpty())
 	    {
	        List sortedConflictExperiences = MilitaryServiceActionHelper.sortConflictExperiences(conflictExperiences);
 	        ConflictExperience conflictExperience = null;
 	        String id=null,startDate=null,endDate=null,location=null,hashCode = null;
 	        for(Iterator iter = sortedConflictExperiences.iterator(); iter.hasNext();)
 	 	   	{
 	            conflictExperience = (ConflictExperience)iter.next();
 	            if(conflictExperience != null)
 	            {
                    // id = conflictExperience.getEntityKey().getKeyValueAsString();
 	            	id = (conflictExperience.getEntityKey() != null) ?conflictExperience.getEntityKey().getKeyValueAsString() : "";
 	            	startDate = conflictExperience.getStartDate() == null ? "" : JspUtils.displayValue(conflictExperience.getStartDate(),JspUtils.STANDARD_DATE_FORMAT);
                    endDate = conflictExperience.getEndDate() == null ? "" : JspUtils.displayValue(conflictExperience.getEndDate(),JspUtils.STANDARD_DATE_FORMAT);
                    location = conflictExperience.getConflictLocation() == null ? "" : conflictExperience.getConflictLocation().getCode();
                    hashCode = String.valueOf(conflictExperience.hashCode());
                    form.addConflictEpisode(id,startDate,endDate,location,hashCode);
 	            }
 	 	   	}
 	    }
 	}

 	private void updateMilitaryService(MilitaryServiceInfoForm form, Person person)
 	throws ConversionServiceException
 	{
 		// CCR10353 Dental Indicator
 	  person.setEligibleForClassIIDental(this.getBooleanIndicatorCode(form.getEligibleForClassIIDental()));

 	  // CCR 10803 MOH
 	  setPersonMedalOfHonor(form,person);
 	  // end of CCR10803

 	  updateSpecialFactors(form,person);

 	   MilitaryService militaryService = person.getMilitaryService();
 	   if(militaryService == null)
 	   {
 	      militaryService = new MilitaryService();
 	      person.setMilitaryService(militaryService);
 	   }
 	   //update  due to disability
 	   militaryService.setDischargeDueToDisability(this.getBooleanIndicatorCode(form.getDischargeDueToDisability()));

 	   //update disability retirement status
 	   militaryService.setDisabilityRetirementIndicator(this.getBooleanIndicatorCode(form.getRetirementDueToMilitaryDisability()));

       // Update Oef/Oif Combat Episodes
 	   updateOefOifCombatEpisode(form,militaryService);

 	   MilitaryServiceSiteRecord hecMSSiteRecord = militaryService.getHECMilitaryServiceSiteRecord();
       boolean isNewHecSiteRecord = false;
 	   if(hecMSSiteRecord == null) {
          isNewHecSiteRecord = true;
          hecMSSiteRecord = new MilitaryServiceSiteRecord();
          hecMSSiteRecord.setSite((VAFacility)getLookup(VAFacility.class,VAFacility.CODE_HEC.getName()));
 	   }

 	   //update filipino veteran proof
 	   String filipinoVeteranProof = form.getFilipinoVeteranProof();
 	   hecMSSiteRecord.setFilipinoVeteranProof((FilipinoVeteranProof)getLookup(FilipinoVeteranProof.class,filipinoVeteranProof));

 	   //update service period
 	   String periodOfService = form.getPeriodOfService();
 	   hecMSSiteRecord.setServicePeriod((ServicePeriod)getLookup(ServicePeriod.class,periodOfService));

 	   updateMilitaryServiceEpisodes(form,hecMSSiteRecord);
 	   updateConflictExperiences(form,hecMSSiteRecord);

       // Add the new HEC record only when some data is populated
       if(isNewHecSiteRecord && !hecMSSiteRecord.isEmpty()) {
           militaryService.addMilitaryServiceSiteRecord(hecMSSiteRecord);
       }
 	}
 	private void setPersonMedalOfHonor(MilitaryServiceInfoForm form,Person person) throws ConversionServiceException {
 		try{
 			 LookupCacheService lookupCacheService = getLookupCacheService();

 			 // change indicator from yes or no to No data, MOH entry is not deleted from db
 			 // it is just set to null
 			 // however if it is No Data and remain unchanged in military screen, no MOH entry will be created
 			 // set medal of honor indicator first
 			  this.setMedalOfHonorIndicator(form, person);

 			  // retrieve moh after indicator was set
	          MedalOfHonor moh = (MedalOfHonor)person.getMedalOfHonor();

 	          String mohInd = form.getMohInd();
 	          String oldMohInd = form.getOnFileMohInd();

 	          // update other moh elements when indicator is yes
 	          if (StringUtils.isNotEmpty(mohInd) && "y".equalsIgnoreCase(mohInd) ){

 	        	 // in fact moh null check is not needed as it was checked in indicator setting
 	        	 if (moh == null)
 				 {
 					moh = new MedalOfHonor();
 					person.setMedalOfHonor(moh);
 				 }
 	        	 moh.setMhIndicator(Boolean.TRUE);

 	        	 Date documentReceiptDate = DateUtils.getDate(form.getDocumentReceiptDate());
 	        	 if (documentReceiptDate ==null )
 	        		 documentReceiptDate = DateUtils.getCurrentDate();
 	        	 moh.setDocumentReceiptDate(documentReceiptDate);

 	        	 moh.setDataSource((MHDataSource)lookupCacheService.getByCodeFromCache(MHDataSource.class, form.getDataSource()));
 	        	 moh.setDocumentType((PHDocumentType)lookupCacheService.getByCodeFromCache(PHDocumentType.class, form.getDocumentType()));
 	        	 moh.setStatus((DecorationStatus)lookupCacheService.getByCodeFromCache(DecorationStatus.class, DecorationStatus.CODE_CONFIRMED.getCode()));

 	        	 // TODO
 	        	 if (isAnyMOHDataChanged(form, person)){
 	        		 moh.setStatusLastUpdateDate(DateUtils.getCurrentDate());
 	        	 }
 	          }
 	          else if (StringUtils.isNotEmpty(oldMohInd) && "y".equalsIgnoreCase(oldMohInd) ){
 	        	 moh.setDataSource(null);
 	        	 moh.setDocumentReceiptDate(null);
 	        	 moh.setDocumentType(null);
 	        	 moh.setStatus(null);
 	        	 moh.setStatusLastUpdateDate(null);
 	          }
 		}
 		 catch (Exception ex)
         {
             throw new ConversionServiceException("Error occured while updating medal of honor information from MilitaryServiceInfoForm.", ex);
         }
 	}

 	private void setMedalOfHonorIndicator(MilitaryServiceInfoForm form,Person person) {

 		MedalOfHonor moh = person.getMedalOfHonor();
 		String setYes = form.getMohInd();

		if (setYes == null || setYes.equalsIgnoreCase(ConvertUtils.NULL_VALUE))
		{
			if (moh!=null) {
				moh.setMhIndicator(null);
				// System.out.println("setMedalOfHonor Indicator ----- moh indicator is set null");
			}
		}
		else
		{
			if (moh == null)
			{
				moh = new MedalOfHonor();
				person.setMedalOfHonor(moh);
			}
			boolean hasThisType = setYes.equalsIgnoreCase(ConvertUtils.YES_VALUE);
			moh.setMhIndicator(Boolean.valueOf(hasThisType));
			// System.out.println("setMedalOfHonor Indicator ----- moh indicator is set "+moh.getMhIndicator().toString());
		}
	}

 	// TODO
 	private boolean isAnyMOHDataChanged(MilitaryServiceInfoForm form,Person person ){

 		// if (form.getMohInd()!=null && form.getOnFileMohInd()!=null && !form.getMohInd().equals(form.getOnFileMohInd()))
 		// when come here, the moh indicator is yes, only check if it is changed from no or no data
 		if (form.getOnFileMohInd()!=null && ("n".equalsIgnoreCase(form.getOnFileMohInd()) || "nd".equalsIgnoreCase(form.getOnFileMohInd())) )
 			return true;

 		if (form.getDataSource()!= null && form.getDataSource().trim().length() > 0){
 			if (StringUtils.isEmpty(form.getOnFileMohDataSource()) )
 				return true;
 			else if (!form.getDataSource().equals(form.getOnFileMohDataSource()))
 				return true;
 		}
 		else return (StringUtils.isNotEmpty(form.getOnFileMohDataSource()));

 		if (form.getDocumentReceiptDate()!= null && form.getDocumentReceiptDate().trim().length() > 0){
 			if (StringUtils.isEmpty(form.getOnFileDocumentReceiptDate()) )
 				return true;
 			else if (!form.getDocumentReceiptDate().equals(form.getOnFileDocumentReceiptDate()))
 				return true;
 		}
 		else return (StringUtils.isNotEmpty(form.getOnFileDocumentReceiptDate()));

 		if (form.getDocumentType()!= null && form.getDocumentType().trim().length() > 0){
 			if (StringUtils.isEmpty(form.getDocumentType()) )
 				return true;
 			else if (!form.getDocumentType().equals(form.getOnFileDocumentType()))
 				return true;
 		}
 		else return (StringUtils.isNotEmpty(form.getOnFileDocumentType()));

 		return false;
 	}


 	private void updateSpecialFactors(MilitaryServiceInfoForm form,Person person)
 	throws ConversionServiceException
 	{
         try
         {
            // AGENT ORANGE EXPOSURE LOCATION
             String aoel = form.getAgentOrangeExposureLocation();
             AgentOrangeExposureLocation location = (AgentOrangeExposureLocation)getLookup(AgentOrangeExposureLocation.class, aoel);
             AgentOrangeExposure ao = (AgentOrangeExposure)person.getSpecialFactorByType(AgentOrangeExposure.class);
             if(location != null) {
                 if(ao == null) {
                     ao = new AgentOrangeExposure();
                     person.addSpecialFactor(ao);
                 }
                 ao.setLocation(location);
             } else {
                 if(ao != null) {
                     ao.setLocation(null);
                 }
             }

             // RADIATION EXPOSURE METHOD
             String rem = form.getRadiationExposureMethod();
             RadiationExposureMethod method = (RadiationExposureMethod)getLookup(RadiationExposureMethod.class, rem);
             RadiationExposure re = (RadiationExposure)person.getSpecialFactorByType(RadiationExposure.class);
             if(method != null) {
                if (re == null) {
                    re = new RadiationExposure();
                    person.addSpecialFactor(re);
                }
                re.setExposureMethod(method);
             } else {
                if(re != null) {
                    re.setExposureMethod(null);
                }
             }

            // ENVIRONMENTAL CONTAMINATION EXPOSURE
            EnvironmentalContaminationExposure contaminationExposure = (EnvironmentalContaminationExposure)person.getSpecialFactorByType(EnvironmentalContaminationExposure.class);
            String expToContaminants = form.getExposedToContaminants();
            Indicator expToContaminantsInd = (Indicator)this.getLookup(Indicator.class, expToContaminants);
            if(StringUtils.isNotEmpty(expToContaminants)) {
                if(contaminationExposure == null) {
                    contaminationExposure = new EnvironmentalContaminationExposure();
                    person.addSpecialFactor(contaminationExposure);
                }
                contaminationExposure.setEnvironmentalContaminationExposureIndicator(expToContaminantsInd);
            } else {
                if(contaminationExposure != null) {
                    contaminationExposure.setEnvironmentalContaminationExposureIndicator(expToContaminantsInd);
                }
            }

            // SHAD
            SHAD SHAD = (SHAD)person.getShad();
            if(StringUtils.isNotEmpty(form.getShad())) {
                if(SHAD == null) {
                    SHAD = new SHAD();
                    person.setShad(SHAD);
                }
                SHAD.setShadIndicator((Indicator)this.getLookup(Indicator.class, form.getShad()));
            } else {
                if ((SHAD != null && SHAD.getShadIndicator() != null) && (Indicator.YES.getCode().equals(SHAD.getShadIndicator().getCode())))
                {
                    SHAD.setShadIndicator((Indicator)this.getLookup(Indicator.class, Indicator.NO.getCode()));
                }
            }
            /////////////////////////////////////////CLV//////////////////////////////////////////////////////
            CampLejeuneVerification clv =(CampLejeuneVerification)person.getSpecialFactorByType(CampLejeuneVerification.class);
            String clvStr = form.getCampLejeuneInd();

            	if(clvStr!= null && clvStr.equals("y")) //temp fix, should be fixed in UI
            		clvStr="1";
            	else if(clvStr!= null && clvStr.equals("n"))
            		clvStr="2";

            Indicator clvInd =(Indicator)this.getLookup(Indicator.class,clvStr );

            	if(clv ==null)
            	{
            		clv = new CampLejeuneVerification();
            		person.addSpecialFactor(clv);
            		clv = (CampLejeuneVerification)person.getSpecialFactorByType(CampLejeuneVerification.class);//re-get clv from person
            	}


            	clv.setSpecialFactorIndicator(clvInd);
            String clvVMStr=form.getCampLejeuneVerificationMethod();

            CampLejeuneVerificationType clvtype = (CampLejeuneVerificationType)this.getLookup(CampLejeuneVerificationType.class, clvVMStr);
            /////////////////////13629////////////////////////////////////////////////////
            List<String> clvms=null;
            if(form.getCampLejeuneVerificationMethods()!= null)
             clvms =Arrays.asList(form.getCampLejeuneVerificationMethods());
            if(clvms!=null)
            {
            	if(clv.getInternalCampLejeuneVerificationMethods()!=null)
            	{
            		for (Iterator iter = clv.getInternalCampLejeuneVerificationMethods().iterator(); iter.hasNext();) {
            			CampLejeuneVerificationMethod clm = (CampLejeuneVerificationMethod) iter.next();

            			if(!clvms.contains(clm.getVerificationType().getCode()))
            			{
            				//clv.removeCampLejeuneVerificationMethodByType(clm.getVerificationType());
            				iter.remove();
            			}
            		}
            	}
            	//clv.removeAllCampLejeuneVerificationMethods();
            	for(String clvVMStr1: clvms)
            	{
            		CampLejeuneVerificationType clvtype1 = (CampLejeuneVerificationType)this.getLookup(CampLejeuneVerificationType.class, clvVMStr1);
            		if(clv.getCampLejeuneMethodByType(clvVMStr1)==null)
            		{
            			CampLejeuneVerificationMethod clvm = new CampLejeuneVerificationMethod();
            			clvm.setVerificationType(clvtype1);
            			clv.addCampLejeuneVerificationMethod(clvm);
            		}
            	}
            }
            ////////////////////13629/////////////////////////////////////////////////////
            clv.setVerificationType(clvtype);
            clv.setComments(form.getCampLejeuneVerificationComments());


            Date clvChangeDate = DateUtils.getDate(form.getCampLejeuneChangeDate());
        	 if (clvChangeDate ==null && clv != null && clv.getSpecialFactorIndicator() != null &&( Indicator.YES.getCode().equals(clv.getSpecialFactorIndicator().getCode())
        			 || Indicator.NO.getCode().equals(clv.getSpecialFactorIndicator().getCode())))
        		 clvChangeDate = DateUtils.getCurrentDate();
        	 clv.setChangeDate(clvChangeDate);
        	 //change site and change source are not editable
        	if(form.getCampLejeuneChangeSource()== null ||form.getCampLejeuneChangeSource().equals(""))
        	{
        		CampLejeuneChangeSource clcs = (CampLejeuneChangeSource)this.getLookup(CampLejeuneChangeSource.class, CampLejeuneChangeSource.CODE_HEC.getName());
        		clv.setChangeSource(clcs);
        	}
        	if(form.getCampLejeuneChangeSite()== null ||form.getCampLejeuneChangeSite().equals(""))
        	{
        		VAFacility vafac = (VAFacility)this.getLookup(VAFacility.class, VAFacility.CODE_HEC.getName());
        		clv.setChangeSite(vafac);
        	}
            /////////////////////////////////////////CLV/////////////////////////////////////////////////////

            // Dental - just copy the EligibleForClassIIDental flag.  The classIIDentalApplicationDueBefore is a
            // calculated value
            // move it to updateMilitaryService



         }
         catch (Exception ex)
         {
             throw new ConversionServiceException("Error occured while updating special factors from MilitaryServiceInfoForm.", ex);
         }
 	}

    private void updateOefOifCombatEpisode(MilitaryServiceInfoForm form, MilitaryService militaryService)
    throws ConversionServiceException
    {
        Map existingCombatEpisodeMap = MilitaryServiceActionHelper.getMapFromCollection(militaryService.getCombatEpisodes());

        //update combat episodes
        militaryService.removeAllCombatEpisodes();
        List combatEpisodeIds =  form.getOefOifCombatEpisodeIdList();
        if(combatEpisodeIds != null && !combatEpisodeIds.isEmpty())
        {
            for(int i=0; i<combatEpisodeIds.size(); i++)
            {
                String combatEpisodeId = (String)combatEpisodeIds.get(i);
                if(StringUtils.isEmpty(combatEpisodeId))
                {
                    if(!form.isOefOifCombatEpisodeEmpty(i))
                    {
                        //add a new combat episode
                        CombatEpisode newCombatEpisode = createNewCombatEpisode(form,i);
                        form.setOefOifCombatEpisodeHashCode(i,String.valueOf(newCombatEpisode.hashCode()));
                        militaryService.addCombatEpisode(newCombatEpisode);
                    }
                    continue;
                }
                if(!form.isOefOifCombatEpisodeEmpty(i))
                {
                    CombatEpisode combatEpisode = (CombatEpisode)existingCombatEpisodeMap.get(combatEpisodeId);

                    //update combat episode
                    if(combatEpisode == null) {
                        combatEpisode = createNewCombatEpisode(form,i);
                    } else {
                        if(form.isOefOifCombatEpisodeChanged(i,combatEpisode)) {
                            OEFOIFSource oefOifSource = (OEFOIFSource)getLookup(OEFOIFSource.class,OEFOIFSource.CODE_CENTRALIZED_ELIGIBILITY_VERIFICATION.getCode());
                            combatEpisode.setOEFOIFSource(oefOifSource);
                        }
                        combatEpisode = updateCombatEpisode(form,i,combatEpisode);
                    }
                    form.setOefOifCombatEpisodeHashCode(i,String.valueOf(combatEpisode.hashCode()));
                    militaryService.addCombatEpisode(combatEpisode);
                }
            }
        }
    }

    private CombatEpisode createNewCombatEpisode(MilitaryServiceInfoForm form, int index)
    throws ConversionServiceException
    {
        CombatEpisode newCcombatEpisode = new CombatEpisode();
        OEFOIFSource oefOifSource = (OEFOIFSource)getLookup(OEFOIFSource.class,OEFOIFSource.CODE_CENTRALIZED_ELIGIBILITY_VERIFICATION.getCode());
        newCcombatEpisode.setOEFOIFSource(oefOifSource);
        return updateCombatEpisode(form,index,newCcombatEpisode);
    }

    private CombatEpisode updateCombatEpisode(MilitaryServiceInfoForm form, int index, CombatEpisode combatEpisode)
    throws ConversionServiceException
    {
        ImpreciseDate startDate = DateUtils.getImpreciseDate(form.getOefOifCombatEpisodeStartDate(index));
        ImpreciseDate endDate = DateUtils.getImpreciseDate(form.getOefOifCombatEpisodeEndDate(index));

        ConflictLocation conflictLocation = (ConflictLocation)getLookup(ConflictLocation.class,form.getOefOifCombatEpisodeLocation(index));

        CombatPayType payType = (CombatPayType)getLookup(CombatPayType.class,form.getOefOifCombatPayType(index));

        combatEpisode.setStartDate(startDate);
        combatEpisode.setEndDate(endDate);
        combatEpisode.setConflictLocation(conflictLocation);
        combatEpisode.setCombatPayType(payType);
        return combatEpisode;
    }

 	private void updateMilitaryServiceEpisodes(MilitaryServiceInfoForm form, MilitaryServiceSiteRecord hecMSSiteRecord)
 	throws ConversionServiceException
 	{
 	    Set existingServiceEpisodes = hecMSSiteRecord.getMilitaryServiceEpisodes();
 	    Map existingServiceEpisodeMap = MilitaryServiceActionHelper.getMapFromCollection(existingServiceEpisodes);

 	    //update service episodes
 	    hecMSSiteRecord.removeAllMilitaryServiceEpisodes();
 	    List serviceEpisodeIds =  form.getServiceEpisodeIdList();
 	    if(serviceEpisodeIds != null && !serviceEpisodeIds.isEmpty())
 	    {
 	        for(int i=0; i<serviceEpisodeIds.size(); i++)
 	        {
 	            String serviceEpisodeId = (String)serviceEpisodeIds.get(i);
 	            if(StringUtils.isEmpty(serviceEpisodeId))
 	            {
 	                if(!form.isServiceEpisodeEmpty(i))
 	                {
 	                    //add a new military service episode
 	                    MilitaryServiceEpisode newMSEpisode = creatNewMilitaryServiceEpisode(form,i);
 	                    form.setServiceEpisodeHashCode(i,String.valueOf(newMSEpisode.hashCode()));
 	                    hecMSSiteRecord.addMilitaryServiceEpisode(newMSEpisode);
 	                }
 	 	 	     	continue;
 	            }
 	            if(!form.isServiceEpisodeEmpty(i))
 	            {
 	                MilitaryServiceEpisode msEpisode = (MilitaryServiceEpisode)existingServiceEpisodeMap.get(serviceEpisodeId);
 	                //update military service episode
 	                msEpisode = msEpisode == null ? creatNewMilitaryServiceEpisode(form,i) : updateMilitaryServiceEpisode(form,i,msEpisode);
 	                form.setServiceEpisodeHashCode(i,String.valueOf(msEpisode.hashCode()));
 	                hecMSSiteRecord.addMilitaryServiceEpisode(msEpisode);
 	            }
 	        }
 	    }
 	}

 	private MilitaryServiceEpisode creatNewMilitaryServiceEpisode(MilitaryServiceInfoForm form, int index)
 	throws ConversionServiceException
 	{
 	    MilitaryServiceEpisode newMSEpisode = new MilitaryServiceEpisode();
 	    return updateMilitaryServiceEpisode(form,index,newMSEpisode);
 	}

 	private MilitaryServiceEpisode updateMilitaryServiceEpisode(MilitaryServiceInfoForm form, int index,MilitaryServiceEpisode msEpisode)
 	throws ConversionServiceException
 	{
 	    String serviceNumber = form.getServiceEpisodeMilitaryServiceNumber(index);
 	    ServiceBranch branchOfService = (ServiceBranch)getLookup(ServiceBranch.class,form.getServiceEpisodeBranchOfService(index));
 	    ImpreciseDate entryDate = DateUtils.getImpreciseDate(form.getServiceEpisodeEntryDate(index));
 	    ImpreciseDate separationDate = DateUtils.getImpreciseDate(form.getServiceEpisodeSeparationDate(index));
 	    DischargeType dischargeType = (DischargeType)getLookup(DischargeType.class,form.getServiceEpisodeDischargeType(index));
        MilitaryServiceComponent serviceComponent = (MilitaryServiceComponent)getLookup(MilitaryServiceComponent.class,form.getServiceEpisodeServiceComponent(index));

 	    msEpisode.setServiceNumber(serviceNumber);
 	    msEpisode.setServiceBranch(branchOfService);
 	    msEpisode.setStartDate(entryDate);
 	    msEpisode.setEndDate(separationDate);
 	    msEpisode.setDischargeType(dischargeType);
 	    msEpisode.setMilitaryServiceComponent(serviceComponent);

 	    return msEpisode;
 	}

 	private void updateConflictExperiences(MilitaryServiceInfoForm form, MilitaryServiceSiteRecord hecMSSiteRecord)
 	throws ConversionServiceException
 	{
	    Set existingConflictExperiences = hecMSSiteRecord.getConflictExperiences();
	    Map existingConflictExperienceMap = MilitaryServiceActionHelper.getMapFromCollection(existingConflictExperiences);

	    //update service episodes
	    hecMSSiteRecord.removeAllConflictExperiences();
	    List conflictEpisodeIds =  form.getConflictEpisodeIdList();
	    if(conflictEpisodeIds != null && !conflictEpisodeIds.isEmpty())
	    {
	        for(int i=0; i<conflictEpisodeIds.size(); i++)
	        {
	            String conflictEpisodeId = (String)conflictEpisodeIds.get(i);
	            if(StringUtils.isEmpty(conflictEpisodeId))
	            {
	                if(!form.isConflictEpisodeEmpty(i))
	                {
	                    //add a new military service episode
	                    ConflictExperience newConflictExperience = createNewConflictExperience(form,i);
	                    form.setConflictEpisodeHashCode(i,String.valueOf(newConflictExperience.hashCode()));
	                    hecMSSiteRecord.addConflictExperience(newConflictExperience);
	                }
	                continue;
	            }
	            if(!form.isConflictEpisodeEmpty(i))
	            {
	                ConflictExperience conflictExperience = (ConflictExperience)existingConflictExperienceMap.get(conflictEpisodeId);

	                //update conflict episode
	                conflictExperience = conflictExperience == null ? createNewConflictExperience(form,i) : updateConflictExperience(form,i,conflictExperience);
	                form.setConflictEpisodeHashCode(i,String.valueOf(conflictExperience.hashCode()));
	                hecMSSiteRecord.addConflictExperience(conflictExperience);
	            }
	        }
	    }
 	}

 	private ConflictExperience createNewConflictExperience(MilitaryServiceInfoForm form, int index)
 	throws ConversionServiceException
 	{
 	    ConflictExperience newConflictEpisode = new ConflictExperience();
 	    return updateConflictExperience(form,index,newConflictEpisode);
 	}

 	private ConflictExperience updateConflictExperience(MilitaryServiceInfoForm form, int index, ConflictExperience conflictExperience)
 	throws ConversionServiceException
 	{
 	    ImpreciseDate entryDate = DateUtils.getImpreciseDate(form.getConflictEpisodeStartDate(index));
 	    ImpreciseDate separationDate = DateUtils.getImpreciseDate(form.getConflictEpisodeEndDate(index));

 	    ConflictLocation conflictLocation = (ConflictLocation)getLookup(ConflictLocation.class,form.getConflictEpisodeLocation(index));

 	    conflictExperience.setStartDate(entryDate);
 	    conflictExperience.setEndDate(separationDate);
 	    conflictExperience.setConflictLocation(conflictLocation);
 	    return conflictExperience;
 	}

}
