/*******************************************************************************
 * Copyright © 2006 VHA. All rights reserved
 ******************************************************************************/
package gov.va.med.esr.common.batchprocess;

import java.util.Calendar;
import java.util.Date;

import org.apache.commons.collections.OrderedMap;
import org.apache.commons.lang.builder.ToStringBuilder;

import com.infomata.data.DataRow;

import gov.va.med.esr.common.infra.ImpreciseDate;
import gov.va.med.esr.common.model.ee.CombatEpisode;
import gov.va.med.esr.common.model.ee.SHAD;
import gov.va.med.esr.common.model.ee.SHADDocument;
import gov.va.med.esr.common.model.lookup.ConflictLocation;
import gov.va.med.fw.io.ClassMapping;
import gov.va.med.fw.io.RawFileDataContainer;
import gov.va.med.fw.io.RawFileDataContainerUtils;
import gov.va.med.fw.model.lookup.Lookup;
import gov.va.med.fw.util.DateUtils;
import gov.va.med.fw.util.StringUtils;


public class VSSCFileData extends BatchProcessPersonIdentityTraits implements
		RawFileDataContainer {

	private static Class[] AUTO_REGISTER_CLASSES = new Class[] {CombatEpisode.class};
	static {
		RawFileDataContainerUtils.autoRegisterConvertersForClasses(AUTO_REGISTER_CLASSES);
	}
	
	private static final long serialVersionUID = -5955729754075793417L;
		

    
	//OEF/OIF fields other than Identity Traits
    private String icn = null;	//Integration Control Number
    private CombatEpisode combatEpisode = null;
    private Date lastUpdateDate = null;    
	
	/* (non-Javadoc)
	 * @see gov.va.med.fw.io.RawFileDataContainer#setRawFileData(java.lang.String, com.infomata.data.DataRow, gov.va.med.fw.io.ClassMapping)
	 */
	public void setRawFileData(String rawFileData, DataRow parsedRow,
			ClassMapping classMapping) throws Exception {
                
        //Parse Identity Traits and Military Service data (OEF and OIF episodes)
		combatEpisode = new CombatEpisode ();
        int i=0; 
		setFirstName(parsedRow.getString(i++)); //1
		setMiddleInitial(parsedRow.getString(i++));//2
        setLastName(parsedRow.getString(i++));//3
		setSsn(parsedRow.getString(i++)); //4
		setIcn(parsedRow.getString(i++)); //5
		RawFileDataContainerUtils.setConvertedField(this,"dateOfBirth", parsedRow.getString(i++));//6
		parsedRow.getString(i++); //7 Gender not used  
		RawFileDataContainerUtils.setConvertedField(combatEpisode,"startDate", parsedRow.getString(i++));//8
		RawFileDataContainerUtils.setConvertedField(combatEpisode,"endDate", parsedRow.getString(i++));//9
		parsedRow.getString(i++); //10 not used  
		RawFileDataContainerUtils.setConvertedField(combatEpisode,"combatPayType", parsedRow.getString(i++));//11
		RawFileDataContainerUtils.setConvertedField(combatEpisode,"conflictLocation", parsedRow.getString(i++));//12
		RawFileDataContainerUtils.setConvertedField(combatEpisode,"OEFOIFSource", parsedRow.getString(i++));//13		
		RawFileDataContainerUtils.setConvertedField(this,"lastUpdateDate",parsedRow.getString(i++)); //14

		//verify that all the required fields are specified
		if (!isDataValid()){
			combatEpisode = null;
			throw new Exception(LoadVSSCDataResult.EXP_REQUIRED_FIELDS_MISSING_INVALID);			
		}
		//set default date values for start and end date
		setDefaultDates();
		
		if (!isDataConsistent(combatEpisode)) {
			combatEpisode = null;
			throw new Exception(LoadVSSCDataResult.EXP_CONSISTENCY_CHECKS_FAILED);
		}
	}

	/* (non-Javadoc)
	 * @see gov.va.med.fw.io.RawFileDataContainer#getRawFileData()
	 */
	public OrderedMap getRawFileData() throws Exception {
		// Not required as we are not generating output file
		return null;
	}
	/* (non-Javadoc)
	 * @see gov.va.med.fw.model.AbstractEntity#buildToString(org.apache.commons.lang.builder.ToStringBuilder)
	 */
	protected void buildToString(ToStringBuilder builder) {
		builder.append("icn",this.icn);
	}
	
    protected String transformLookup(Lookup lookup)
    {
        return lookup == null ? null : lookup.getCode();
    }

	public String getIcn() {
		return this.icn;
	}

	public void setIcn(String icn) {
		this.icn = icn;
	}

	public Date getLastUpdateDate() {
		return this.lastUpdateDate;
	}

	/**
	 * @param lastUpdateDate The lastUpdateDate to set.
	 */
	public void setLastUpdateDate(Date lastUpdateDate) {
		this.lastUpdateDate = lastUpdateDate;
	}

	/**
	 * Validate all the required fields
	 * @return
	 */
	private boolean isDataValid(){
		
		//All fields are required
		if (StringUtils.isEmpty(getLastName()) ||
				StringUtils.isEmpty(getSsn()) ||
				getDateOfBirth() == null ||
				combatEpisode.getStartDate() == null ||
				combatEpisode.getEndDate() == null ||
				combatEpisode.getCombatPayType() == null ||
				combatEpisode.getConflictLocation() == null ||
				combatEpisode.getOEFOIFSource() == null ||
				getLastUpdateDate() == null
				)		
		{		
		    return false;
		}
		//Start and end dates should atleast have year and month specified
		if (!combatEpisode.getStartDate().isMonthPrecise()){
			return false;
		}
		if (!combatEpisode.getEndDate().isMonthPrecise()){
			return false;
		}
				
		return true;
	}
	
	private boolean isDataConsistent(CombatEpisode episode) {
		//check dates
		Date currentDate = DateUtils.getCurrentDate();
		Date startDate = episode.getStartDate().getCalendar().getTime();
		Date endDate = episode.getEndDate().getCalendar().getTime();
		//start date after end date
		if (startDate.after(endDate))
			return false;
		//start and end dates future
		if (startDate.after(currentDate) || endDate.after(currentDate))
			return false;
		
		//Start date should not be before the start date of the location
		if (startDate.before(episode.getConflictLocation().getStartDate())){
			return false;
		}		
		//OEF
		if (ConflictLocation.CODE_OEF.getCode().equals(
				episode.getConflictLocation().getCode()) 
				&& endDate.before(getDate(2001,9,11)))
		{
			return false;
		}
		//OIF
		if (ConflictLocation.CODE_OIF.getCode().equals(
				episode.getConflictLocation().getCode())
				&& endDate.before(getDate(2003,3,19)))
		{
			return false;
		}
		if (ConflictLocation.CODE_UNKNOWN_OEF_OIF.getCode().equals(
				episode.getConflictLocation().getCode())
				&& endDate.before(getDate(2001,9,11)))
		{
			return false;
		}
		return true;
	}
	
	private Date getDate(int year, int month, int day){
		return DateUtils.createCalendar(year, month, day).getTime();
	}
	/**
	 * If the start is imprecise and date is missing set to first of the month
	 * If the end date is imprecise and date is missing set to last day of the month
	 *
	 */
	private void setDefaultDates(){
		if (!combatEpisode.getStartDate().isDayPrecise() ){			
			//set the first day of the month as the date
	        Calendar calendar = combatEpisode.getStartDate().getCalendar();
	        calendar.set(Calendar.DAY_OF_MONTH,1);
	        Calendar newDate = (Calendar)calendar.clone();
	        newDate.clear();
	        newDate.set(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH));	        
	        combatEpisode.setStartDate(new ImpreciseDate(newDate));
		}
		
		if (!combatEpisode.getEndDate().isDayPrecise()){
			//set the last day of the month as the day
	        Calendar calendar = combatEpisode.getEndDate().getCalendar();
	        //set the day to 1st
	        //calendar.set(Calendar.DAY_OF_MONTH,1);	        
	        int lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
	        calendar.set(Calendar.DAY_OF_MONTH,lastDay);
	        Calendar newDate = (Calendar)calendar.clone();
	        newDate.clear();
	        newDate.set(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH));		        
	        combatEpisode.setEndDate(new ImpreciseDate(newDate));
		}
	}
	
	public CombatEpisode getCombatEpisode() {
		return this.combatEpisode;
	}

	public void setCombatEpisode(CombatEpisode combatEpisode) {
		this.combatEpisode = combatEpisode;
	}

	/* (non-Javadoc)
	 * @see gov.va.med.fw.io.RawFileDataContainer#getClassesForAutoRegisterConverters()
	 */
	public Class[] getClassesForAutoRegisterConverters() {
		return AUTO_REGISTER_CLASSES;
	}

	/**
	 * @author DNS   KATIKM
	 * VSSC data file format
	 * 	VSSC Field Name			Position	Format	Len	Nulls Allowed
		FNAME					1			CHAR	20	Y
		MNAME					2			CHAR	2	Y
		LNAME					3			CHAR	26	N
		REALSSN					4			CHAR	11	N
		ICN						5			NUMERIC	10	Y
		DOB						6			DATE	10	N
		SEX 					7			CHAR	1	N
		Combat From Date		8			DATE	10	N
		Combat To Date			9			DATE	10	N
		COMBAT_ELIGIBLE			10			NUMERIC	1	N
		COMBAT_ELIGIBILTY_CODE	11			CHAR	2	N
		OEFOIF_FLAG				12			CHAR	2	N
		DATA_SOURCE				13			CHAR	7	N
		LAST_UPDATED_ON			14			DATE	10	N
	 */	
}
