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


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

import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.builder.entity.ActivationMetaData;
import gov.va.med.esr.common.builder.entity.CombatEpisodeMetaData;
import gov.va.med.esr.common.builder.entity.CombatServiceMetaData;
import gov.va.med.esr.common.builder.entity.MilitaryServiceEpisodeMetaData;
import gov.va.med.esr.common.builder.entity.MilitaryServiceSiteRecordMetaData;
import gov.va.med.esr.common.builder.entity.metaData.AbstractMetaData;
import gov.va.med.esr.common.model.ee.MilitaryService;
import gov.va.med.esr.jms.vadir.outboundResponse.VadirServiceResponseWrapper;
import gov.va.med.esr.jms.vadir.outboundResponse.model.militaryHistory.Activation;
import gov.va.med.esr.jms.vadir.outboundResponse.model.militaryHistory.MilitaryHistory;
import gov.va.med.esr.jms.vadir.outboundResponse.model.militaryHistory.MilitaryPay;
import gov.va.med.esr.jms.vadir.outboundResponse.model.militaryHistory.ServicePeriod;
import gov.va.med.esr.jms.vadir.outboundResponse.model.militaryHistory.VADIR;
import gov.va.med.esr.service.MsdsResponseInfo;
import gov.va.med.fw.util.StringUtils;


/**
 * Please note that this data object only knows about certain MSDS data. Do not
 * use for any other purpose.
 * 
 * @author DNS   ruizc
 *
 */
public class MilitaryServiceMetaDataFromVADIR extends AbstractMetaData implements MilitaryServiceMetaDataMSDS {

	private MilitaryService militaryService = null;
	private MilitaryServiceSiteRecordMetaData militaryServiceSiteRecordMetaData = null;
	private ActivationMetaData[] activations = null;
	private CombatServiceMetaData[] combatServices = null;
	private CombatEpisodeMetaData[] combatEpisodes = null;	
	private VADIR vadir = null;
	private String metaDataError = null;	
		
	/*
	 * Ignore these records with incoming codes 
	 * Y Civilian Retirees
	 * D Disabled American veteran
	 * E DoD and Uniformed Service contract employee
	 * W DoD Beneficiary,
	 * U DoD OCONUS Hires
	 * T Foreign Affiliate
	 * F Former member
	 * L Lighthouse service
	 * H Medal of Honor recipient
	 * K Non-appropriated fund DoD and Uniformed Service employee (NAF)
	 * I Non-DoD civil service employee
	 * O Non-DoD contract employee
	 * M Non-federal Agency civilian associates
	 * B Presidential Appointees
	 * R Retired military member eligible for retired pay
	 * 
	 */
	private final String[] invalidComponent = 
		{"Y","D","E","W","U","T","F","L","H","K","I","O","M","B","R" };	
	private final String[] invalidTerminationReason = {"F","W"};
	private final String[] invalidCombatPayType = {"03"};
	
    public MilitaryServiceMetaDataFromVADIR(VadirServiceResponseWrapper wrapper) {
	        super();

	        // unwrap the wrapper
	        processWrapper(wrapper);
    }
	
	public String getCombatVeteranEligibilityEndDate() {
		return null;
	}

	public String getDisabilityRetirementStatus() {
		return (vadir != null) ? vadir.getRetirementStatusIndicator() : null;
	}

	public String getDischargeDueToDisability() {
		return null;
	}

	public MilitaryService getEntity() {
		return this.militaryService;
	}

	public MilitaryServiceSiteRecordMetaData getMilitaryServiceSiteRecord() {
		return this.militaryServiceSiteRecordMetaData;
	}

	public void setEntity(MilitaryService entity) {
		this.militaryService = entity;
	}

	/**
	 * @see gov.va.med.esr.common.builder.msds.MilitaryServiceMetaDataMSDS#getActivations()
	 */
	public ActivationMetaData[] getActivations() {
		return this.activations;
	}

	/**
	 * @see gov.va.med.esr.common.builder.msds.MilitaryServiceMetaDataMSDS#getCombatServices()
	 */
	public CombatServiceMetaData[] getCombatServices() {
		return this.combatServices;
	}

	
	public CombatEpisodeMetaData[] getCombatEpisodes() {
		return this.combatEpisodes;
	}

	/* (non-Javadoc)
	 * @see gov.va.med.esr.common.builder.msds.MilitaryServiceMetaDataMSDS#getMetaDataError()
	 */
	public String getMetaDataError() {
		return this.metaDataError;
	}
	
	/**
	 * @param metaDataError the metaDataError to set
	 */
	public void setMetaDataError(String metaDataError) {
		this.metaDataError = metaDataError;
	}	

	private void processWrapper(VadirServiceResponseWrapper wrapper) {
		List militaryPays = new ArrayList();
		List combatEpisodesList = new ArrayList();		
		List activations = new ArrayList();
		List servicePeriodsHEC = new ArrayList();
		
		MilitaryHistory history = wrapper != null ?	(MilitaryHistory)wrapper.getResult() : null;

		if (history != null) {
			this.vadir = history.getVadir();

			List servicePeriods = vadir != null ? vadir.getServicePeriods() : new ArrayList();
			if (servicePeriods != null) {
				for (Iterator iter = servicePeriods.iterator(); iter.hasNext();) {
					ServicePeriod period = (ServicePeriod)iter.next();
					// BIRLS & VADIR & ESR Code Reference says to ignore certain data
					if (StringUtils.contains(this.invalidComponent, period.getPersonnelCategory()))
						continue;
					if (period.getCharacterOfService() == null || 
							StringUtils.isBlank(period.getCharacterOfService()) ||
							"UNK".equals(period.getCharacterOfService()) ||
							"Z".equals(period.getCharacterOfService())) {
						/*
						 * CCR 10616 temporarily excludes these records up front, so no reason to generate
						 * work item. Also skipped below when adding episode.
						 * 
						 * N	National Guard member
						 * V	Reserve member
						 * Q	Reserve retiree not yet eligible for retired pay (“Grey Area Retiree”) 
						 */
						if (!("N".equals(period.getPersonnelCategory()) ||
								"V".equals(period.getPersonnelCategory()) ||
								"Q".equals(period.getPersonnelCategory()))) {
							this.setMetaDataError(MsdsResponseInfo.INVALID_CHARACTER_OF_SERVICE_VADIR);							
						}
					}

					// Activations
					List acts = period.getActivations();
					if (acts != null) {
						for (Iterator itr = acts.iterator(); itr.hasNext();) {
							Activation activation = (Activation )itr.next();
							if (StringUtils.contains(this.invalidTerminationReason, 
									activation.getTerminationRsn()))
								continue;			
							ActivationMetaData data = new ActivationMetaDataFromMSDS(period, activation);
							activations.add(data);
						}
					}
					// Combat Pay AND Combat Episodes
					List combatPays = period.getMilitaryPayments();
					//	Pay records for use in making Combat Episodes
					List paysForConversion = new ArrayList(); 
					if (combatPays != null) {
						for (Iterator itr = combatPays.iterator(); itr.hasNext();) {
							MilitaryPay pay = (MilitaryPay)itr.next();
							if (StringUtils.contains(this.invalidCombatPayType, 
									pay.getPayType()))
								continue;										
							CombatServiceMetaData data = new CombatServiceMetaDataFromMSDS(period, pay);
							militaryPays.add(data);
							paysForConversion.add(pay);
						}
						/*
						 * Create Combat Episodes From Military Pay
						 */
						processCombatEpisodes(combatEpisodesList, paysForConversion, period.getDeployments());
					}
					// Military Service Episodes
					/*
					 * CCR 10616 temporarily excludes these records up front
					 * N	National Guard member
					 * V	Reserve member
					 * Q	Reserve retiree not yet eligible for retired pay (“Grey Area Retiree”) 
					 */
					
					if (!("N".equals(period.getPersonnelCategory()) ||
							"V".equals(period.getPersonnelCategory()) ||
							"Q".equals(period.getPersonnelCategory()))) {
						MilitaryServiceEpisodeMetaData periodMeta = new MilitaryServiceEpisodeMetaDataFromVADIR(period);
						servicePeriodsHEC.add(periodMeta);						
					}
					
					if("N".equals(period.getPersonnelCategory()) ||
							"V".equals(period.getPersonnelCategory()) ||
							"Q".equals(period.getPersonnelCategory())){
						List periodActs = period.getActivations();
						if (periodActs != null) {
							for (Iterator itr = periodActs.iterator(); itr.hasNext();) {
								Activation activation = (Activation )itr.next();
								if (StringUtils.contains(this.invalidTerminationReason, 
										activation.getTerminationRsn()))
									continue;									
								ServicePeriod actServicePeriod = createServicePeriod(period,activation);
								if(actServicePeriod != null){
									MilitaryServiceEpisodeMetaData actperiodMeta = new MilitaryServiceEpisodeMetaDataFromVADIR(actServicePeriod);
									servicePeriodsHEC.add(actperiodMeta);									
								}
								
							}
						}
						
					}
				}
				
			}
		}

		this.combatServices = (CombatServiceMetaData[])militaryPays.toArray(new CombatServiceMetaData[0]);
		this.combatEpisodes = (CombatEpisodeMetaDataFromVADIR[])
			combatEpisodesList.toArray(new CombatEpisodeMetaDataFromVADIR[0]);		
 		this.militaryServiceSiteRecordMetaData = 
			new MilitaryServiceSiteRecordMetaDataFromMSDS((MilitaryServiceEpisodeMetaData[])
					servicePeriodsHEC.toArray(new MilitaryServiceEpisodeMetaData[0]));
		this.activations = (ActivationMetaData[])activations.toArray(new ActivationMetaData[0]);		
	}
	
	private void processCombatEpisodes(List combatEpisodesMetaData, List pays, List deployments) {
		VadirCombatServiceBuilderStrategy militaryPayStrategy = new VadirCombatServiceBuilderStrategy();
		List paysForConversion = militaryPayStrategy.determineMilitaryPayToKeep(pays);
		
		for (Iterator itr = paysForConversion.iterator(); itr.hasNext();) {
			MilitaryPay pay = (MilitaryPay)itr.next();
			VadirCombatEpisodeBuilderStrategy strategy = new VadirCombatEpisodeBuilderStrategy();
			strategy.setCombatPayStart(pay.getStartDate());
			strategy.setCombatPayEnd(pay.getEndDate());
			strategy.setDeployments(deployments);
			String location = strategy.determineConflictLocationCode();
			ImpreciseDate calculatedStartDt = strategy.determineStartDate();
			ImpreciseDate calculatedEndDt = strategy.determineEndDate();
			CombatEpisodeMetaDataFromVADIR metadata = 
				new CombatEpisodeMetaDataFromVADIR(pay, location, calculatedStartDt, calculatedEndDt);
			combatEpisodesMetaData.add(metadata);
		}
		
	}
	
	private ServicePeriod createServicePeriod(ServicePeriod incomingServicePeriod, Activation incomingActivation){
		ServicePeriod createdServicePeriod = null;
		if(incomingActivation != null){
			createdServicePeriod = new ServicePeriod();
			createdServicePeriod.setPersonnelCategory(incomingServicePeriod.getPersonnelCategory());
			createdServicePeriod.setBranchOfService(incomingServicePeriod.getBranchOfService());
			createdServicePeriod.setCharacterOfService(incomingActivation.getCharacterOfService());
			createdServicePeriod.setStartDate(incomingActivation.getStartDate());
			createdServicePeriod.setEndDate(incomingActivation.getEndDate());			
		}
		
		return createdServicePeriod;
		
	}
}
